using System; namespace Renci.SshNet { /// /// Provides functionality for forwarding connections from the client to destination servers via the SSH server, /// also known as dynamic port forwarding. /// public partial class ForwardedPortDynamic : ForwardedPort { private ForwardedPortStatus _status; /// /// Gets the bound host. /// public string BoundHost { get; private set; } /// /// Gets the bound port. /// public uint BoundPort { get; private set; } /// /// Gets a value indicating whether port forwarding is started. /// /// /// true if port forwarding is started; otherwise, false. /// public override bool IsStarted { get { return _status == ForwardedPortStatus.Started; } } /// /// Initializes a new instance of the class. /// /// The port. public ForwardedPortDynamic(uint port) : this(string.Empty, port) { } /// /// Initializes a new instance of the class. /// /// The host. /// The port. public ForwardedPortDynamic(string host, uint port) { BoundHost = host; BoundPort = port; _status = ForwardedPortStatus.Stopped; } /// /// Starts local port forwarding. /// protected override void StartPort() { if (!ForwardedPortStatus.ToStarting(ref _status)) return; try { InternalStart(); } catch (Exception) { _status = ForwardedPortStatus.Stopped; throw; } } /// /// Stops local port forwarding, and waits for the specified timeout until all pending /// requests are processed. /// /// The maximum amount of time to wait for pending requests to finish processing. protected override void StopPort(TimeSpan timeout) { if (!ForwardedPortStatus.ToStopping(ref _status)) return; // signal existing channels that the port is closing base.StopPort(timeout); // prevent new requests from getting processed StopListener(); // wait for open channels to close InternalStop(timeout); // mark port stopped _status = ForwardedPortStatus.Stopped; } /// /// Ensures the current instance is not disposed. /// /// The current instance is disposed. protected override void CheckDisposed() { if (_isDisposed) throw new ObjectDisposedException(GetType().FullName); } partial void InternalStart(); /// /// Stops the listener. /// partial void StopListener(); /// /// Waits for pending requests to finish, and channels to close. /// /// The maximum time to wait for the forwarded port to stop. partial void InternalStop(TimeSpan timeout); #region IDisposable Members /// /// Holds a value indicating whether the current instance is disposed. /// /// /// true if the current instance is disposed; otherwise, false. /// private bool _isDisposed; /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } partial void InternalDispose(bool disposing); /// /// Releases unmanaged and - optionally - managed resources /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected override void Dispose(bool disposing) { if (_isDisposed) return; base.Dispose(disposing); InternalDispose(disposing); _isDisposed = true; } /// /// Releases unmanaged resources and performs other cleanup operations before the /// is reclaimed by garbage collection. /// ~ForwardedPortDynamic() { Dispose(false); } #endregion } }