using System;
using Renci.SshNet.Common;
using Renci.SshNet.Messages.Connection;
namespace Renci.SshNet.Channels
{
internal abstract class ClientChannel : Channel
{
///
/// Initializes a new instance of the class.
///
/// The session.
/// The local channel number.
/// Size of the window.
/// Size of the packet.
protected ClientChannel(ISession session, uint localChannelNumber, uint localWindowSize, uint localPacketSize)
: base(session, localChannelNumber, localWindowSize, localPacketSize)
{
session.ChannelOpenConfirmationReceived += OnChannelOpenConfirmation;
session.ChannelOpenFailureReceived += OnChannelOpenFailure;
}
///
/// Occurs when is received.
///
public event EventHandler OpenConfirmed;
///
/// Occurs when is received.
///
public event EventHandler OpenFailed;
///
/// Called when channel is opened by the server.
///
/// The remote channel number.
/// Initial size of the window.
/// Maximum size of the packet.
protected virtual void OnOpenConfirmation(uint remoteChannelNumber, uint initialWindowSize, uint maximumPacketSize)
{
InitializeRemoteInfo(remoteChannelNumber, initialWindowSize, maximumPacketSize);
// Channel is consider to be open when confirmation message was received
IsOpen = true;
OpenConfirmed?.Invoke(this, new ChannelOpenConfirmedEventArgs(remoteChannelNumber, initialWindowSize, maximumPacketSize));
}
///
/// Send message to open a channel.
///
/// Message to send.
/// The client is not connected.
/// The operation timed out.
/// The size of the packet exceeds the maximum size defined by the protocol.
protected void SendMessage(ChannelOpenMessage message)
{
Session.SendMessage(message);
}
///
/// Called when channel failed to open.
///
/// The reason code.
/// The description.
/// The language.
protected virtual void OnOpenFailure(uint reasonCode, string description, string language)
{
OpenFailed?.Invoke(this, new ChannelOpenFailedEventArgs(LocalChannelNumber, reasonCode, description, language));
}
private void OnChannelOpenConfirmation(object sender, MessageEventArgs e)
{
if (e.Message.LocalChannelNumber == LocalChannelNumber)
{
try
{
OnOpenConfirmation(e.Message.RemoteChannelNumber,
e.Message.InitialWindowSize,
e.Message.MaximumPacketSize);
}
catch (Exception ex)
{
OnChannelException(ex);
}
}
}
private void OnChannelOpenFailure(object sender, MessageEventArgs e)
{
if (e.Message.LocalChannelNumber == LocalChannelNumber)
{
try
{
OnOpenFailure(e.Message.ReasonCode, e.Message.Description, e.Message.Language);
}
catch (Exception ex)
{
OnChannelException(ex);
}
}
}
protected override void Dispose(bool disposing)
{
UnsubscribeFromSessionEvents(Session);
base.Dispose(disposing);
}
///
/// Unsubscribes the current from session events.
///
/// The session.
///
/// Does nothing when is .
///
private void UnsubscribeFromSessionEvents(ISession session)
{
if (session is null)
{
return;
}
session.ChannelOpenConfirmationReceived -= OnChannelOpenConfirmation;
session.ChannelOpenFailureReceived -= OnChannelOpenFailure;
}
}
}