using System;
using Renci.SshNet.Common;
namespace Renci.SshNet
{
///
/// Base class for port forwarding functionality.
///
public abstract class ForwardedPort : IForwardedPort
{
///
/// Gets or sets the session.
///
///
/// The session.
///
internal ISession Session { get; set; }
///
/// The event occurs as the forwarded port is being stopped.
///
internal event EventHandler Closing;
///
/// The event occurs as the forwarded port is being stopped.
///
event EventHandler IForwardedPort.Closing
{
add { Closing += value; }
remove { Closing -= value; }
}
///
/// Gets a value indicating whether port forwarding is started.
///
///
/// true if port forwarding is started; otherwise, false.
///
public abstract bool IsStarted { get; }
///
/// Occurs when an exception is thrown.
///
public event EventHandler Exception;
///
/// Occurs when a port forwarding request is received.
///
public event EventHandler RequestReceived;
///
/// Starts port forwarding.
///
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();
}
///
/// Stops port forwarding.
///
public virtual void Stop()
{
if (IsStarted)
{
StopPort(Session.ConnectionInfo.Timeout);
}
}
///
/// Starts port forwarding.
///
protected abstract void StartPort();
///
/// Stops 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 virtual void StopPort(TimeSpan timeout)
{
RaiseClosing();
var session = Session;
if (session != null)
{
session.ErrorOccured -= Session_ErrorOccured;
}
}
///
/// Releases unmanaged and - optionally - managed resources
///
/// true to release both managed and unmanaged resources; false to release only unmanaged resources.
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
var session = Session;
if (session != null)
{
StopPort(session.ConnectionInfo.Timeout);
Session = null;
}
}
}
///
/// Ensures the current instance is not disposed.
///
/// The current instance is disposed.
protected abstract void CheckDisposed();
///
/// Raises event.
///
/// The exception.
protected void RaiseExceptionEvent(Exception exception)
{
var handlers = Exception;
if (handlers != null)
{
handlers(this, new ExceptionEventArgs(exception));
}
}
///
/// Raises event.
///
/// Request originator host.
/// Request originator port.
protected void RaiseRequestReceived(string host, uint port)
{
var handlers = RequestReceived;
if (handlers != null)
{
handlers(this, new PortForwardEventArgs(host, port));
}
}
///
/// Raises the event.
///
private void RaiseClosing()
{
var handlers = Closing;
if (handlers != null)
{
handlers(this, EventArgs.Empty);
}
}
///
/// Handles session ErrorOccured event.
///
/// The source of the event.
/// The instance containing the event data.
private void Session_ErrorOccured(object sender, ExceptionEventArgs e)
{
RaiseExceptionEvent(e.Exception);
}
}
}