Skip to content

Commit

Permalink
Mark ChannelSession sealed, and added doc for SendChannelOpenMessage().
Browse files Browse the repository at this point in the history
  • Loading branch information
drieseng committed Sep 24, 2017
1 parent a353f95 commit 3b23d11
Showing 1 changed file with 43 additions and 9 deletions.
52 changes: 43 additions & 9 deletions src/Renci.SshNet/Channels/ChannelSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Renci.SshNet.Channels
/// <summary>
/// Implements Session SSH channel.
/// </summary>
internal class ChannelSession : ClientChannel, IChannelSession
internal sealed class ChannelSession : ClientChannel, IChannelSession
{
/// <summary>
/// Counts failed channel open attempts
Expand Down Expand Up @@ -62,7 +62,7 @@ public override ChannelTypes ChannelType
/// <summary>
/// Opens the channel.
/// </summary>
public virtual void Open()
public void Open()
{
// Try to open channel several times
while (!IsOpen && _failedOpenAttempts < ConnectionInfo.RetryAttempts)
Expand Down Expand Up @@ -356,19 +356,53 @@ protected override void OnFailure()
/// <summary>
/// Sends the channel open message.
/// </summary>
protected void SendChannelOpenMessage()
/// <exception cref="SshConnectionException">The client is not connected.</exception>
/// <exception cref="SshOperationTimeoutException">The operation timed out.</exception>
/// <exception cref="InvalidOperationException">The size of the packet exceeds the maximum size defined by the protocol.</exception>
/// <remarks>
/// <para>
/// 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 <see cref="ChannelOpenMessage"/>
/// to the remote host.
/// </para>
/// <para>
/// Note that the session semaphore is released in any of the following cases:
/// <list type="bullet">
/// <item>
/// <description>A <see cref="ChannelOpenFailureMessage"/> is received for the channel being opened.</description>
/// </item>
/// <item>
/// <description>The remote host does not respond to the <see cref="ChannelOpenMessage"/> within the configured <see cref="ConnectionInfo.Timeout"/>.</description>
/// </item>
/// <item>
/// <description>The remote host closes the channel.</description>
/// </item>
/// <item>
/// <description>The <see cref="ChannelSession"/> is disposed.</description>
/// </item>
/// <item>
/// <description>A socket error occurs sending a message to the remote host.</description>
/// </item>
/// </list>
/// </para>
/// <para>
/// 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 <see cref="ChannelOpenMessage"/>, but the remote host did not
/// confirmed or rejected attempt to open the channel.
/// </para>
/// </remarks>
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()));
}
}

Expand Down

0 comments on commit 3b23d11

Please sign in to comment.