using System; using System.Net.Sockets; using System.Net; using System.Threading; using Renci.SshNet.Channels; namespace Renci.SshNet { /// /// Provides functionality for local port forwarding /// public partial class ForwardedPortLocal { private TcpListener _listener; private readonly object _listenerLocker = new object(); partial void InternalStart() { // If port already started don't start it again if (this.IsStarted) return; IPAddress addr = this.BoundHost.GetIPAddress(); var ep = new IPEndPoint(addr, (int)this.BoundPort); this._listener = new TcpListener(ep); this._listener.Start(); // Update bound port if original was passed as zero this.BoundPort = (uint)((IPEndPoint)_listener.LocalEndpoint).Port; this.Session.ErrorOccured += Session_ErrorOccured; this.Session.Disconnected += Session_Disconnected; this._listenerTaskCompleted = new ManualResetEvent(false); this.ExecuteThread(() => { try { while (true) { lock (this._listenerLocker) { if (this._listener == null) break; } var socket = this._listener.AcceptSocket(); this.ExecuteThread(() => { try { IPEndPoint originatorEndPoint = socket.RemoteEndPoint as IPEndPoint; this.RaiseRequestReceived(originatorEndPoint.Address.ToString(), (uint)originatorEndPoint.Port); using (var channel = this.Session.CreateClientChannel()) { channel.Open(this.Host, this.Port, socket); channel.Bind(); channel.Close(); } } catch (Exception exp) { this.RaiseExceptionEvent(exp); } }); } } catch (SocketException exp) { if (!(exp.SocketErrorCode == SocketError.Interrupted)) { this.RaiseExceptionEvent(exp); } } catch (Exception exp) { this.RaiseExceptionEvent(exp); } finally { this._listenerTaskCompleted.Set(); } }); this.IsStarted = true; } partial void InternalStop() { // If port not started you cant stop it if (!this.IsStarted) return; this.Session.Disconnected -= Session_Disconnected; this.Session.ErrorOccured -= Session_ErrorOccured; this.StopListener(); this._listenerTaskCompleted.WaitOne(this.Session.ConnectionInfo.Timeout); this._listenerTaskCompleted.Dispose(); this._listenerTaskCompleted = null; this.IsStarted = false; } private void StopListener() { lock (this._listenerLocker) { if (this._listener != null) { this._listener.Stop(); this._listener = null; } } } private void Session_ErrorOccured(object sender, Common.ExceptionEventArgs e) { this.StopListener(); } private void Session_Disconnected(object sender, EventArgs e) { this.StopListener(); } } }