<PackageReference Include="SSH.NET" Version="2024.2.0" />

ForwardedPort

public abstract class ForwardedPort : IForwardedPort, IDisposable
Base class for port forwarding functionality.
using Renci.SshNet.Common; using System; namespace Renci.SshNet { public abstract class ForwardedPort : IForwardedPort, IDisposable { internal ISession Session { get; set; } public abstract bool IsStarted { get; } public event EventHandler Closing; public event EventHandler<ExceptionEventArgs> Exception; public event EventHandler<PortForwardEventArgs> RequestReceived; public virtual void Start() { CheckDisposed(); if (IsStarted) throw new InvalidOperationException("Forwarded port is already started."); if (Session == null) throw new InvalidOperationException("Forwarded port is not added to a client."); if (!Session.IsConnected) throw new SshConnectionException("Client not connected."); Session.ErrorOccured += Session_ErrorOccured; StartPort(); } public virtual void Stop() { if (IsStarted) StopPort(Session.ConnectionInfo.Timeout); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected abstract void StartPort(); protected virtual void StopPort(TimeSpan timeout) { timeout.EnsureValidTimeout("timeout"); RaiseClosing(); ISession session = Session; if (session != null) session.ErrorOccured -= Session_ErrorOccured; } protected virtual void Dispose(bool disposing) { if (disposing) { ISession session = Session; if (session != null) { StopPort(session.ConnectionInfo.Timeout); Session = null; } } } protected abstract void CheckDisposed(); protected void RaiseExceptionEvent(Exception exception) { this.Exception?.Invoke(this, new ExceptionEventArgs(exception)); } protected void RaiseRequestReceived(string host, uint port) { this.RequestReceived?.Invoke(this, new PortForwardEventArgs(host, port)); } private void RaiseClosing() { this.Closing?.Invoke(this, EventArgs.Empty); } private void Session_ErrorOccured(object sender, ExceptionEventArgs e) { RaiseExceptionEvent(e.Exception); } } }