ChannelDirectTcpipTest.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. using System;
  2. using System.Globalization;
  3. using System.Net;
  4. using System.Net.Sockets;
  5. using System.Threading;
  6. using Microsoft.VisualStudio.TestTools.UnitTesting;
  7. using Moq;
  8. using Renci.SshNet.Channels;
  9. using Renci.SshNet.Common;
  10. using Renci.SshNet.Messages;
  11. using Renci.SshNet.Messages.Connection;
  12. using Renci.SshNet.Tests.Common;
  13. namespace Renci.SshNet.Tests.Classes.Channels
  14. {
  15. [TestClass]
  16. public partial class ChannelDirectTcpipTestTest : TestBase
  17. {
  18. private Mock<ISession> _sessionMock;
  19. private Mock<IForwardedPort> _forwardedPortMock;
  20. private uint _localWindowSize;
  21. private uint _localPacketSize;
  22. private string _remoteHost;
  23. private uint _port;
  24. private uint _localChannelNumber;
  25. private uint _remoteWindowSize;
  26. private uint _remotePacketSize;
  27. private uint _remoteChannelNumber;
  28. protected override void OnInit()
  29. {
  30. base.OnInit();
  31. var random = new Random();
  32. _localWindowSize = (uint) random.Next(2000, 3000);
  33. _localPacketSize = (uint) random.Next(1000, 2000);
  34. _remoteHost = random.Next().ToString(CultureInfo.InvariantCulture);
  35. _port = (uint) random.Next(IPEndPoint.MinPort, IPEndPoint.MaxPort);
  36. _localChannelNumber = (uint) random.Next(0, int.MaxValue);
  37. _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
  38. _remotePacketSize = (uint)random.Next(100, 200);
  39. _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
  40. _sessionMock = new Mock<ISession>(MockBehavior.Strict);
  41. _forwardedPortMock = new Mock<IForwardedPort>(MockBehavior.Strict);
  42. }
  43. [TestMethod]
  44. public void SocketShouldBeClosedAndBindShouldEndWhenForwardedPortSignalsClosingEvent()
  45. {
  46. _sessionMock.Setup(p => p.NextChannelNumber).Returns(_localChannelNumber);
  47. _sessionMock.Setup(p => p.IsConnected).Returns(true);
  48. _sessionMock.Setup(p => p.SendMessage(It.IsAny<ChannelOpenMessage>()))
  49. .Callback<Message>(m => _sessionMock.Raise(p => p.ChannelOpenConfirmationReceived += null,
  50. new MessageEventArgs<ChannelOpenConfirmationMessage>(
  51. new ChannelOpenConfirmationMessage(((ChannelOpenMessage)m).LocalChannelNumber, _remoteWindowSize, _remotePacketSize, _remoteChannelNumber))));
  52. _sessionMock.Setup(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()))
  53. .Callback<WaitHandle>(p => p.WaitOne(-1));
  54. var localPortEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
  55. using (var localPortListener = new AsyncSocketListener(localPortEndPoint))
  56. {
  57. localPortListener.Start();
  58. localPortListener.Connected += socket =>
  59. {
  60. var channel = new ChannelDirectTcpip();
  61. channel.Initialize(_sessionMock.Object, _localWindowSize, _localPacketSize);
  62. channel.Open(_remoteHost, _port, _forwardedPortMock.Object, socket);
  63. var closeForwardedPortThread =
  64. new Thread(() =>
  65. {
  66. // sleep for a short period to allow channel to actually start receiving from socket
  67. Thread.Sleep(100);
  68. // raise Closing event on forwarded port
  69. _forwardedPortMock.Raise(p => p.Closing += null, EventArgs.Empty);
  70. });
  71. closeForwardedPortThread.Start();
  72. channel.Bind();
  73. closeForwardedPortThread.Join();
  74. };
  75. var client = new Socket(localPortEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
  76. client.Connect(localPortEndPoint);
  77. // attempt to receive from socket to verify it was shut down by channel
  78. var buffer = new byte[16];
  79. var bytesReceived = client.Receive(buffer, 0, buffer.Length, SocketFlags.None);
  80. Assert.AreEqual(0, bytesReceived);
  81. }
  82. }
  83. [TestMethod]
  84. public void SocketShouldBeClosedAndBindShouldEndWhenOnErrorOccurredIsInvoked()
  85. {
  86. _sessionMock.Setup(p => p.NextChannelNumber).Returns(_localChannelNumber);
  87. _sessionMock.Setup(p => p.IsConnected).Returns(true);
  88. _sessionMock.Setup(p => p.SendMessage(It.IsAny<ChannelOpenMessage>()))
  89. .Callback<Message>(m => _sessionMock.Raise(p => p.ChannelOpenConfirmationReceived += null,
  90. new MessageEventArgs<ChannelOpenConfirmationMessage>(
  91. new ChannelOpenConfirmationMessage(((ChannelOpenMessage)m).LocalChannelNumber, _remoteWindowSize, _remotePacketSize, _remoteChannelNumber))));
  92. _sessionMock.Setup(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()))
  93. .Callback<WaitHandle>(p => p.WaitOne(-1));
  94. var localPortEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
  95. using (var localPortListener = new AsyncSocketListener(localPortEndPoint))
  96. {
  97. localPortListener.Start();
  98. localPortListener.Connected += socket =>
  99. {
  100. var channel = new ChannelDirectTcpip();
  101. channel.Initialize(_sessionMock.Object, _localWindowSize, _localPacketSize);
  102. channel.Open(_remoteHost, _port, _forwardedPortMock.Object, socket);
  103. var signalSessionErrorOccurredThread =
  104. new Thread(() =>
  105. {
  106. // sleep for a short period to allow channel to actually start receiving from socket
  107. Thread.Sleep(100);
  108. // raise ErrorOccured event on session
  109. _sessionMock.Raise(s => s.ErrorOccured += null,
  110. new ExceptionEventArgs(new SystemException()));
  111. });
  112. signalSessionErrorOccurredThread.Start();
  113. channel.Bind();
  114. signalSessionErrorOccurredThread.Join();
  115. };
  116. var client = new Socket(localPortEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
  117. client.Connect(localPortEndPoint);
  118. // attempt to receive from socket to verify it was shut down by channel
  119. var buffer = new byte[16];
  120. var bytesReceived = client.Receive(buffer, 0, buffer.Length, SocketFlags.None);
  121. Assert.AreEqual(0, bytesReceived);
  122. }
  123. }
  124. [TestMethod]
  125. public void SocketShouldBeClosedAndEofShouldBeSentToServerWhenClientShutsDownSocket()
  126. {
  127. _sessionMock.Setup(p => p.NextChannelNumber).Returns(_localChannelNumber);
  128. _sessionMock.Setup(p => p.IsConnected).Returns(true);
  129. _sessionMock.Setup(p => p.SendMessage(It.IsAny<ChannelOpenMessage>()))
  130. .Callback<Message>(m => _sessionMock.Raise(p => p.ChannelOpenConfirmationReceived += null,
  131. new MessageEventArgs<ChannelOpenConfirmationMessage>(
  132. new ChannelOpenConfirmationMessage(((ChannelOpenMessage) m).LocalChannelNumber,
  133. _remoteWindowSize, _remotePacketSize, _remoteChannelNumber))));
  134. _sessionMock.Setup(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()))
  135. .Callback<WaitHandle>(p => p.WaitOne(-1));
  136. _sessionMock.Setup(p => p.SendMessage(It.IsAny<ChannelEofMessage>()))
  137. .Callback<Message>(
  138. m => new Thread(() =>
  139. {
  140. Thread.Sleep(50);
  141. _sessionMock.Raise(s => s.ChannelEofReceived += null,
  142. new MessageEventArgs<ChannelEofMessage>(new ChannelEofMessage(_localChannelNumber)));
  143. }).Start());
  144. _sessionMock.Setup(p => p.SendMessage(It.IsAny<ChannelCloseMessage>()))
  145. .Callback<Message>(
  146. m => new Thread(() =>
  147. {
  148. Thread.Sleep(50);
  149. _sessionMock.Raise(s => s.ChannelCloseReceived += null,
  150. new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
  151. }).Start());
  152. var channelBindFinishedWaitHandle = new ManualResetEvent(false);
  153. Socket handler = null;
  154. ChannelDirectTcpip channel = null;
  155. var localPortEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
  156. using (var localPortListener = new AsyncSocketListener(localPortEndPoint))
  157. {
  158. localPortListener.Start();
  159. localPortListener.Connected += socket =>
  160. {
  161. channel = new ChannelDirectTcpip();
  162. channel.Initialize(_sessionMock.Object, _localWindowSize, _localPacketSize);
  163. channel.Open(_remoteHost, _port, _forwardedPortMock.Object, socket);
  164. channel.Bind();
  165. handler = socket;
  166. channelBindFinishedWaitHandle.Set();
  167. };
  168. var client = new Socket(localPortEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
  169. client.Connect(localPortEndPoint);
  170. client.Shutdown(SocketShutdown.Send);
  171. channelBindFinishedWaitHandle.WaitOne();
  172. Assert.IsNotNull(handler);
  173. Assert.IsFalse(handler.Connected);
  174. _sessionMock.Verify(p => p.SendMessage(It.IsAny<ChannelEofMessage>()), Times.Once);
  175. _sessionMock.Verify(p => p.SendMessage(It.IsAny<ChannelCloseMessage>()), Times.Never);
  176. channel.Close();
  177. _sessionMock.Verify(p => p.SendMessage(It.IsAny<ChannelEofMessage>()), Times.Once);
  178. _sessionMock.Verify(p => p.SendMessage(It.IsAny<ChannelCloseMessage>()), Times.Once);
  179. }
  180. }
  181. }
  182. }