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; } } }