ForwardedPortLocal.NET.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. using System;
  2. using System.Net.Sockets;
  3. using System.Net;
  4. using System.Threading;
  5. using Renci.SshNet.Channels;
  6. namespace Renci.SshNet
  7. {
  8. /// <summary>
  9. /// Provides functionality for local port forwarding
  10. /// </summary>
  11. public partial class ForwardedPortLocal
  12. {
  13. private TcpListener _listener;
  14. private readonly object _listenerLocker = new object();
  15. partial void InternalStart()
  16. {
  17. // If port already started don't start it again
  18. if (this.IsStarted)
  19. return;
  20. IPAddress addr = this.BoundHost.GetIPAddress();
  21. var ep = new IPEndPoint(addr, (int)this.BoundPort);
  22. this._listener = new TcpListener(ep);
  23. this._listener.Start();
  24. // Update bound port if original was passed as zero
  25. this.BoundPort = (uint)((IPEndPoint)_listener.LocalEndpoint).Port;
  26. this.Session.ErrorOccured += Session_ErrorOccured;
  27. this.Session.Disconnected += Session_Disconnected;
  28. this._listenerTaskCompleted = new ManualResetEvent(false);
  29. this.ExecuteThread(() =>
  30. {
  31. try
  32. {
  33. while (true)
  34. {
  35. lock (this._listenerLocker)
  36. {
  37. if (this._listener == null)
  38. break;
  39. }
  40. var socket = this._listener.AcceptSocket();
  41. this.ExecuteThread(() =>
  42. {
  43. try
  44. {
  45. IPEndPoint originatorEndPoint = socket.RemoteEndPoint as IPEndPoint;
  46. this.RaiseRequestReceived(originatorEndPoint.Address.ToString(), (uint)originatorEndPoint.Port);
  47. using (var channel = this.Session.CreateChannel<ChannelDirectTcpip>())
  48. {
  49. channel.Open(this.Host, this.Port, socket);
  50. channel.Bind();
  51. channel.Close();
  52. }
  53. }
  54. catch (Exception exp)
  55. {
  56. this.RaiseExceptionEvent(exp);
  57. }
  58. });
  59. }
  60. }
  61. catch (SocketException exp)
  62. {
  63. if (!(exp.SocketErrorCode == SocketError.Interrupted))
  64. {
  65. this.RaiseExceptionEvent(exp);
  66. }
  67. }
  68. catch (Exception exp)
  69. {
  70. this.RaiseExceptionEvent(exp);
  71. }
  72. finally
  73. {
  74. this._listenerTaskCompleted.Set();
  75. }
  76. });
  77. this.IsStarted = true;
  78. }
  79. partial void InternalStop()
  80. {
  81. // If port not started you cant stop it
  82. if (!this.IsStarted)
  83. return;
  84. this.Session.Disconnected -= Session_Disconnected;
  85. this.Session.ErrorOccured -= Session_ErrorOccured;
  86. this.StopListener();
  87. this._listenerTaskCompleted.WaitOne(this.Session.ConnectionInfo.Timeout);
  88. this._listenerTaskCompleted.Dispose();
  89. this._listenerTaskCompleted = null;
  90. this.IsStarted = false;
  91. }
  92. private void StopListener()
  93. {
  94. lock (this._listenerLocker)
  95. {
  96. if (this._listener != null)
  97. {
  98. this._listener.Stop();
  99. this._listener = null;
  100. }
  101. }
  102. }
  103. private void Session_ErrorOccured(object sender, Common.ExceptionEventArgs e)
  104. {
  105. this.StopListener();
  106. }
  107. private void Session_Disconnected(object sender, EventArgs e)
  108. {
  109. this.StopListener();
  110. }
  111. }
  112. }