diff --git a/src/Renci.SshNet/Channels/ChannelSession.cs b/src/Renci.SshNet/Channels/ChannelSession.cs index 3295c5a5d..38e13096b 100644 --- a/src/Renci.SshNet/Channels/ChannelSession.cs +++ b/src/Renci.SshNet/Channels/ChannelSession.cs @@ -10,7 +10,7 @@ namespace Renci.SshNet.Channels /// /// Implements Session SSH channel. /// - internal class ChannelSession : ClientChannel, IChannelSession + internal sealed class ChannelSession : ClientChannel, IChannelSession { /// /// Counts failed channel open attempts @@ -62,7 +62,7 @@ public override ChannelTypes ChannelType /// /// Opens the channel. /// - public virtual void Open() + public void Open() { // Try to open channel several times while (!IsOpen && _failedOpenAttempts < ConnectionInfo.RetryAttempts) @@ -356,19 +356,53 @@ protected override void OnFailure() /// /// Sends the channel open message. /// - protected void SendChannelOpenMessage() + /// The client is not connected. + /// The operation timed out. + /// The size of the packet exceeds the maximum size defined by the protocol. + /// + /// + /// When a session semaphore for this instance has not yet been obtained by this or any other thread, + /// the thread will block until such a semaphore is available and send a + /// to the remote host. + /// + /// + /// Note that the session semaphore is released in any of the following cases: + /// + /// + /// A is received for the channel being opened. + /// + /// + /// The remote host does not respond to the within the configured . + /// + /// + /// The remote host closes the channel. + /// + /// + /// The is disposed. + /// + /// + /// A socket error occurs sending a message to the remote host. + /// + /// + /// + /// + /// If the session semaphore was already obtained for this instance (and not released), then this method + /// immediately returns control to the caller. This should only happen when another thread has obtain the + /// session semaphore and already sent the , but the remote host did not + /// confirmed or rejected attempt to open the channel. + /// + /// + private void SendChannelOpenMessage() { // do not allow open to be ChannelOpenMessage to be sent again until we've // had a response on the previous attempt for the current channel if (Interlocked.CompareExchange(ref _sessionSemaphoreObtained, 1, 0) == 0) { SessionSemaphore.Wait(); - SendMessage( - new ChannelOpenMessage( - LocalChannelNumber, - LocalWindowSize, - LocalPacketSize, - new SessionChannelOpenInfo())); + SendMessage(new ChannelOpenMessage(LocalChannelNumber, + LocalWindowSize, + LocalPacketSize, + new SessionChannelOpenInfo())); } }