|
|
@@ -1,237 +1,233 @@
|
|
|
-using System;
|
|
|
-using System.Globalization;
|
|
|
-using System.Net;
|
|
|
-using System.Net.Sockets;
|
|
|
-using System.Threading;
|
|
|
-using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
|
-using Moq;
|
|
|
-using Renci.SshNet.Channels;
|
|
|
-using Renci.SshNet.Common;
|
|
|
-using Renci.SshNet.Messages.Connection;
|
|
|
-using Renci.SshNet.Tests.Common;
|
|
|
-
|
|
|
-namespace Renci.SshNet.Tests.Classes.Channels
|
|
|
-{
|
|
|
- [TestClass]
|
|
|
- public class ChannelDirectTcpipTest_Close_SessionIsConnectedAndChannelIsOpen
|
|
|
- {
|
|
|
- private Mock<ISession> _sessionMock;
|
|
|
- private Mock<IForwardedPort> _forwardedPortMock;
|
|
|
- private Mock<IConnectionInfo> _connectionInfoMock;
|
|
|
- private ChannelDirectTcpip _channel;
|
|
|
- private uint _localChannelNumber;
|
|
|
- private uint _localWindowSize;
|
|
|
- private uint _localPacketSize;
|
|
|
- private uint _remoteWindowSize;
|
|
|
- private uint _remotePacketSize;
|
|
|
- private uint _remoteChannelNumber;
|
|
|
- private string _remoteHost;
|
|
|
- private uint _port;
|
|
|
- private AsyncSocketListener _listener;
|
|
|
- private EventWaitHandle _channelBindFinishedWaitHandle;
|
|
|
- private EventWaitHandle _clientReceivedFinishedWaitHandle;
|
|
|
- private Socket _client;
|
|
|
- private Exception _channelException;
|
|
|
-
|
|
|
- [TestInitialize]
|
|
|
- public void Initialize()
|
|
|
- {
|
|
|
- Arrange();
|
|
|
- Act();
|
|
|
- }
|
|
|
-
|
|
|
- [TestCleanup]
|
|
|
- public void CleanUp()
|
|
|
- {
|
|
|
- if (_client != null)
|
|
|
- {
|
|
|
- _client.Dispose();
|
|
|
- _client = null;
|
|
|
- }
|
|
|
-
|
|
|
- if (_listener != null)
|
|
|
- {
|
|
|
- _listener.Stop();
|
|
|
- _listener = null;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private void Arrange()
|
|
|
- {
|
|
|
- var random = new Random();
|
|
|
- _localChannelNumber = (uint) random.Next(0, int.MaxValue);
|
|
|
- _localWindowSize = (uint) random.Next(2000, 3000);
|
|
|
- _localPacketSize = (uint) random.Next(1000, 2000);
|
|
|
- _remoteHost = random.Next().ToString(CultureInfo.InvariantCulture);
|
|
|
- _port = (uint) random.Next(IPEndPoint.MinPort, IPEndPoint.MaxPort);
|
|
|
- _channelBindFinishedWaitHandle = new ManualResetEvent(false);
|
|
|
- _clientReceivedFinishedWaitHandle = new ManualResetEvent(false);
|
|
|
- _channelException = null;
|
|
|
-
|
|
|
- _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
|
|
|
- _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
|
|
|
- _remotePacketSize = (uint)random.Next(100, 200);
|
|
|
-
|
|
|
- _sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
|
|
- _forwardedPortMock = new Mock<IForwardedPort>(MockBehavior.Strict);
|
|
|
- _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
|
|
|
-
|
|
|
- var sequence = new MockSequence();
|
|
|
- _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
|
|
|
- _sessionMock.InSequence(sequence)
|
|
|
- .Setup(p => p.SendMessage(It.Is<ChannelOpenMessage>(m => AssertExpectedMessage(m))));
|
|
|
- _sessionMock.InSequence(sequence)
|
|
|
- .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
|
|
|
- .Callback<WaitHandle>(
|
|
|
- w =>
|
|
|
- {
|
|
|
- _sessionMock.Raise(
|
|
|
- s => s.ChannelOpenConfirmationReceived += null,
|
|
|
- new MessageEventArgs<ChannelOpenConfirmationMessage>(
|
|
|
- new ChannelOpenConfirmationMessage(
|
|
|
- _localChannelNumber,
|
|
|
- _remoteWindowSize,
|
|
|
- _remotePacketSize,
|
|
|
- _remoteChannelNumber)));
|
|
|
- w.WaitOne();
|
|
|
- });
|
|
|
- _sessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
|
|
|
- _connectionInfoMock.InSequence(sequence).Setup(p => p.Timeout).Returns(TimeSpan.FromSeconds(60));
|
|
|
- _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
|
|
|
- _sessionMock.InSequence(sequence)
|
|
|
- .Setup(
|
|
|
- p => p.TrySendMessage(It.Is<ChannelEofMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)))
|
|
|
- .Returns(true);
|
|
|
- _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
|
|
|
- _sessionMock.InSequence(sequence)
|
|
|
- .Setup(
|
|
|
- p => p.TrySendMessage(It.Is<ChannelCloseMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)))
|
|
|
- .Returns(true);
|
|
|
- _sessionMock.InSequence(sequence)
|
|
|
- .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
|
|
|
- .Callback<WaitHandle>(
|
|
|
- w =>
|
|
|
- {
|
|
|
- _sessionMock.Raise(
|
|
|
- s => s.ChannelCloseReceived += null,
|
|
|
- new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
|
|
|
- w.WaitOne();
|
|
|
- });
|
|
|
-
|
|
|
- var localEndpoint = new IPEndPoint(IPAddress.Loopback, 8122);
|
|
|
- _listener = new AsyncSocketListener(localEndpoint);
|
|
|
- _listener.Connected += socket =>
|
|
|
- {
|
|
|
- try
|
|
|
- {
|
|
|
- _channel = new ChannelDirectTcpip(
|
|
|
- _sessionMock.Object,
|
|
|
- _localChannelNumber,
|
|
|
- _localWindowSize,
|
|
|
- _localPacketSize);
|
|
|
- _channel.Open(_remoteHost, _port, _forwardedPortMock.Object, socket);
|
|
|
- _channel.Bind();
|
|
|
- }
|
|
|
- catch (Exception ex)
|
|
|
- {
|
|
|
- _channelException = ex;
|
|
|
- }
|
|
|
- finally
|
|
|
- {
|
|
|
- _channelBindFinishedWaitHandle.Set();
|
|
|
- }
|
|
|
- };
|
|
|
- _listener.Start();
|
|
|
-
|
|
|
- _client = new Socket(localEndpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
|
|
- _client.Connect(localEndpoint);
|
|
|
-
|
|
|
- var clientReceiveThread = new Thread(
|
|
|
- () =>
|
|
|
- {
|
|
|
- var buffer = new byte[16];
|
|
|
- var bytesReceived = _client.Receive(buffer, 0, buffer.Length, SocketFlags.None);
|
|
|
- if (bytesReceived == 0)
|
|
|
- {
|
|
|
- _client.Shutdown(SocketShutdown.Send);
|
|
|
- _clientReceivedFinishedWaitHandle.Set();
|
|
|
- }
|
|
|
- }
|
|
|
- );
|
|
|
- clientReceiveThread.Start();
|
|
|
-
|
|
|
- // give channel time to bind to socket
|
|
|
- Thread.Sleep(200);
|
|
|
- }
|
|
|
-
|
|
|
- private void Act()
|
|
|
- {
|
|
|
- if (_channel != null)
|
|
|
- {
|
|
|
- _channel.Close();
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- [TestMethod]
|
|
|
- public void BindShouldHaveFinishedWithoutException()
|
|
|
- {
|
|
|
- Assert.IsTrue(_channelBindFinishedWaitHandle.WaitOne(0));
|
|
|
- Assert.IsNull(_channelException, _channelException != null ? _channelException.ToString() : null);
|
|
|
- }
|
|
|
-
|
|
|
- [TestMethod]
|
|
|
- public void ClientShouldHaveFinished()
|
|
|
- {
|
|
|
- Assert.IsTrue(_clientReceivedFinishedWaitHandle.WaitOne(0));
|
|
|
- }
|
|
|
-
|
|
|
- [TestMethod]
|
|
|
- public void ChannelEofMessageShouldBeSentOnce()
|
|
|
- {
|
|
|
- _sessionMock.Verify(p => p.TrySendMessage(It.Is<ChannelEofMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)), Times.Once);
|
|
|
- }
|
|
|
-
|
|
|
- [TestMethod]
|
|
|
- public void ChannelCloseMessageShouldBeSentOnce()
|
|
|
- {
|
|
|
- _sessionMock.Verify(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)), Times.Once);
|
|
|
- }
|
|
|
-
|
|
|
- [TestMethod]
|
|
|
- public void IsOpenShouldReturnFalse()
|
|
|
- {
|
|
|
- Assert.IsFalse(_channel.IsOpen);
|
|
|
- }
|
|
|
-
|
|
|
- private bool AssertExpectedMessage(ChannelOpenMessage channelOpenMessage)
|
|
|
- {
|
|
|
- if (channelOpenMessage == null)
|
|
|
- return false;
|
|
|
- if (channelOpenMessage.LocalChannelNumber != _localChannelNumber)
|
|
|
- return false;
|
|
|
- if (channelOpenMessage.InitialWindowSize != _localWindowSize)
|
|
|
- return false;
|
|
|
- if (channelOpenMessage.MaximumPacketSize != _localPacketSize)
|
|
|
- return false;
|
|
|
-
|
|
|
- var directTcpipChannelInfo = channelOpenMessage.Info as DirectTcpipChannelInfo;
|
|
|
- if (directTcpipChannelInfo == null)
|
|
|
- return false;
|
|
|
- if (directTcpipChannelInfo.HostToConnect != _remoteHost)
|
|
|
- return false;
|
|
|
- if (directTcpipChannelInfo.PortToConnect != _port)
|
|
|
- return false;
|
|
|
-
|
|
|
- var clientEndpoint = _client.LocalEndPoint as IPEndPoint;
|
|
|
- if (clientEndpoint == null)
|
|
|
- return false;
|
|
|
- if (directTcpipChannelInfo.OriginatorAddress != clientEndpoint.Address.ToString())
|
|
|
- return false;
|
|
|
- if (directTcpipChannelInfo.OriginatorPort != clientEndpoint.Port)
|
|
|
- return false;
|
|
|
-
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
+using System;
|
|
|
+using System.Globalization;
|
|
|
+using System.Net;
|
|
|
+using System.Net.Sockets;
|
|
|
+using System.Threading;
|
|
|
+using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
|
+using Moq;
|
|
|
+using Renci.SshNet.Channels;
|
|
|
+using Renci.SshNet.Messages.Connection;
|
|
|
+using Renci.SshNet.Tests.Common;
|
|
|
+
|
|
|
+namespace Renci.SshNet.Tests.Classes.Channels
|
|
|
+{
|
|
|
+ [TestClass]
|
|
|
+ public class ChannelDirectTcpipTest_Close_SessionIsConnectedAndChannelIsOpen
|
|
|
+ {
|
|
|
+ private Mock<ISession> _sessionMock;
|
|
|
+ private Mock<IForwardedPort> _forwardedPortMock;
|
|
|
+ private Mock<IConnectionInfo> _connectionInfoMock;
|
|
|
+ private ChannelDirectTcpip _channel;
|
|
|
+ private uint _localChannelNumber;
|
|
|
+ private uint _localWindowSize;
|
|
|
+ private uint _localPacketSize;
|
|
|
+ private uint _remoteWindowSize;
|
|
|
+ private uint _remotePacketSize;
|
|
|
+ private uint _remoteChannelNumber;
|
|
|
+ private string _remoteHost;
|
|
|
+ private uint _port;
|
|
|
+ private AsyncSocketListener _listener;
|
|
|
+ private EventWaitHandle _channelBindFinishedWaitHandle;
|
|
|
+ private EventWaitHandle _clientReceivedFinishedWaitHandle;
|
|
|
+ private Socket _client;
|
|
|
+ private Exception _channelException;
|
|
|
+
|
|
|
+ [TestInitialize]
|
|
|
+ public void Initialize()
|
|
|
+ {
|
|
|
+ Arrange();
|
|
|
+ Act();
|
|
|
+ }
|
|
|
+
|
|
|
+ [TestCleanup]
|
|
|
+ public void CleanUp()
|
|
|
+ {
|
|
|
+ if (_client != null)
|
|
|
+ {
|
|
|
+ _client.Dispose();
|
|
|
+ _client = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_listener != null)
|
|
|
+ {
|
|
|
+ _listener.Stop();
|
|
|
+ _listener = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void Arrange()
|
|
|
+ {
|
|
|
+ var random = new Random();
|
|
|
+ _localChannelNumber = (uint) random.Next(0, int.MaxValue);
|
|
|
+ _localWindowSize = (uint) random.Next(2000, 3000);
|
|
|
+ _localPacketSize = (uint) random.Next(1000, 2000);
|
|
|
+ _remoteHost = random.Next().ToString(CultureInfo.InvariantCulture);
|
|
|
+ _port = (uint) random.Next(IPEndPoint.MinPort, IPEndPoint.MaxPort);
|
|
|
+ _channelBindFinishedWaitHandle = new ManualResetEvent(false);
|
|
|
+ _clientReceivedFinishedWaitHandle = new ManualResetEvent(false);
|
|
|
+ _channelException = null;
|
|
|
+
|
|
|
+ _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
|
|
|
+ _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
|
|
|
+ _remotePacketSize = (uint)random.Next(100, 200);
|
|
|
+
|
|
|
+ _sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
|
|
+ _forwardedPortMock = new Mock<IForwardedPort>(MockBehavior.Strict);
|
|
|
+ _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
|
|
|
+
|
|
|
+ var sequence = new MockSequence();
|
|
|
+ _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
|
|
|
+ _sessionMock.InSequence(sequence)
|
|
|
+ .Setup(p => p.SendMessage(It.Is<ChannelOpenMessage>(m => AssertExpectedMessage(m))));
|
|
|
+ _sessionMock.InSequence(sequence)
|
|
|
+ .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
|
|
|
+ .Callback<WaitHandle>(
|
|
|
+ w =>
|
|
|
+ {
|
|
|
+ _sessionMock.Raise(
|
|
|
+ s => s.ChannelOpenConfirmationReceived += null,
|
|
|
+ new MessageEventArgs<ChannelOpenConfirmationMessage>(
|
|
|
+ new ChannelOpenConfirmationMessage(
|
|
|
+ _localChannelNumber,
|
|
|
+ _remoteWindowSize,
|
|
|
+ _remotePacketSize,
|
|
|
+ _remoteChannelNumber)));
|
|
|
+ w.WaitOne();
|
|
|
+ });
|
|
|
+ _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
|
|
|
+ _sessionMock.InSequence(sequence)
|
|
|
+ .Setup(
|
|
|
+ p => p.TrySendMessage(It.Is<ChannelEofMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)))
|
|
|
+ .Returns(true);
|
|
|
+ _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
|
|
|
+ _sessionMock.InSequence(sequence)
|
|
|
+ .Setup(
|
|
|
+ p => p.TrySendMessage(It.Is<ChannelCloseMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)))
|
|
|
+ .Returns(true);
|
|
|
+ _sessionMock.InSequence(sequence)
|
|
|
+ .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
|
|
|
+ .Callback<WaitHandle>(
|
|
|
+ w =>
|
|
|
+ {
|
|
|
+ _sessionMock.Raise(
|
|
|
+ s => s.ChannelCloseReceived += null,
|
|
|
+ new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
|
|
|
+ w.WaitOne();
|
|
|
+ });
|
|
|
+
|
|
|
+ var localEndpoint = new IPEndPoint(IPAddress.Loopback, 8122);
|
|
|
+ _listener = new AsyncSocketListener(localEndpoint);
|
|
|
+ _listener.Connected += socket =>
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ _channel = new ChannelDirectTcpip(
|
|
|
+ _sessionMock.Object,
|
|
|
+ _localChannelNumber,
|
|
|
+ _localWindowSize,
|
|
|
+ _localPacketSize);
|
|
|
+ _channel.Open(_remoteHost, _port, _forwardedPortMock.Object, socket);
|
|
|
+ _channel.Bind();
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ _channelException = ex;
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ _channelBindFinishedWaitHandle.Set();
|
|
|
+ }
|
|
|
+ };
|
|
|
+ _listener.Start();
|
|
|
+
|
|
|
+ _client = new Socket(localEndpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
|
|
+ _client.Connect(localEndpoint);
|
|
|
+
|
|
|
+ var clientReceiveThread = new Thread(
|
|
|
+ () =>
|
|
|
+ {
|
|
|
+ var buffer = new byte[16];
|
|
|
+ var bytesReceived = _client.Receive(buffer, 0, buffer.Length, SocketFlags.None);
|
|
|
+ if (bytesReceived == 0)
|
|
|
+ {
|
|
|
+ _client.Shutdown(SocketShutdown.Send);
|
|
|
+ _clientReceivedFinishedWaitHandle.Set();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+ clientReceiveThread.Start();
|
|
|
+
|
|
|
+ // give channel time to bind to socket
|
|
|
+ Thread.Sleep(200);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void Act()
|
|
|
+ {
|
|
|
+ if (_channel != null)
|
|
|
+ {
|
|
|
+ _channel.Close();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ [TestMethod]
|
|
|
+ public void BindShouldHaveFinishedWithoutException()
|
|
|
+ {
|
|
|
+ Assert.IsTrue(_channelBindFinishedWaitHandle.WaitOne(0));
|
|
|
+ Assert.IsNull(_channelException, _channelException != null ? _channelException.ToString() : null);
|
|
|
+ }
|
|
|
+
|
|
|
+ [TestMethod]
|
|
|
+ public void ClientShouldHaveFinished()
|
|
|
+ {
|
|
|
+ Assert.IsTrue(_clientReceivedFinishedWaitHandle.WaitOne(0));
|
|
|
+ }
|
|
|
+
|
|
|
+ [TestMethod]
|
|
|
+ public void ChannelEofMessageShouldBeSentOnce()
|
|
|
+ {
|
|
|
+ _sessionMock.Verify(p => p.TrySendMessage(It.Is<ChannelEofMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)), Times.Once);
|
|
|
+ }
|
|
|
+
|
|
|
+ [TestMethod]
|
|
|
+ public void ChannelCloseMessageShouldBeSentOnce()
|
|
|
+ {
|
|
|
+ _sessionMock.Verify(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)), Times.Once);
|
|
|
+ }
|
|
|
+
|
|
|
+ [TestMethod]
|
|
|
+ public void IsOpenShouldReturnFalse()
|
|
|
+ {
|
|
|
+ Assert.IsFalse(_channel.IsOpen);
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool AssertExpectedMessage(ChannelOpenMessage channelOpenMessage)
|
|
|
+ {
|
|
|
+ if (channelOpenMessage == null)
|
|
|
+ return false;
|
|
|
+ if (channelOpenMessage.LocalChannelNumber != _localChannelNumber)
|
|
|
+ return false;
|
|
|
+ if (channelOpenMessage.InitialWindowSize != _localWindowSize)
|
|
|
+ return false;
|
|
|
+ if (channelOpenMessage.MaximumPacketSize != _localPacketSize)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ var directTcpipChannelInfo = channelOpenMessage.Info as DirectTcpipChannelInfo;
|
|
|
+ if (directTcpipChannelInfo == null)
|
|
|
+ return false;
|
|
|
+ if (directTcpipChannelInfo.HostToConnect != _remoteHost)
|
|
|
+ return false;
|
|
|
+ if (directTcpipChannelInfo.PortToConnect != _port)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ var clientEndpoint = _client.LocalEndPoint as IPEndPoint;
|
|
|
+ if (clientEndpoint == null)
|
|
|
+ return false;
|
|
|
+ if (directTcpipChannelInfo.OriginatorAddress != clientEndpoint.Address.ToString())
|
|
|
+ return false;
|
|
|
+ if (directTcpipChannelInfo.OriginatorPort != clientEndpoint.Port)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|