Skip to content

Commit

Permalink
fix "client not connected" after SFTP reconnect (#1484)
Browse files Browse the repository at this point in the history
* fix "client not connected" after SFTP reconnect

if the server closes the session and the client reconnects,
this currently leads to a broken state because the session
is re-created, but the SFTP subsession is not and still
references the old session.

This causes all operations to fail with "client not connected" or
even throwing the "An established connection was aborted by the server."
exception of the old session.

Always re-create the SFTP subsession to fix this.

fixes #1474

* Dispose old session on reconnect
  • Loading branch information
mus65 authored Sep 6, 2024
1 parent a157dd3 commit 6669309
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 9 deletions.
10 changes: 10 additions & 0 deletions src/Renci.SshNet/BaseClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,11 @@ public void Connect()
var session = Session;
if (session is null || !session.IsConnected)
{
if (session is not null)
{
DisposeSession(session);
}

Session = CreateAndConnectSession();
}

Expand Down Expand Up @@ -304,6 +309,11 @@ public async Task ConnectAsync(CancellationToken cancellationToken)
var session = Session;
if (session is null || !session.IsConnected)
{
if (session is not null)
{
DisposeSession(session);
}

Session = await CreateAndConnectSessionAsync(cancellationToken).ConfigureAwait(false);
}

Expand Down
11 changes: 2 additions & 9 deletions src/Renci.SshNet/SftpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2496,15 +2496,8 @@ protected override void OnConnected()
{
base.OnConnected();

var sftpSession = _sftpSession;
if (sftpSession is null)
{
_sftpSession = CreateAndConnectToSftpSession();
}
else if (!sftpSession.IsOpen)
{
sftpSession.Connect();
}
_sftpSession?.Dispose();
_sftpSession = CreateAndConnectToSftpSession();
}

/// <summary>
Expand Down
48 changes: 48 additions & 0 deletions test/Renci.SshNet.IntegrationTests/ConnectivityTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,54 @@ public async Task SftpClient_HandleSftpSessionCloseAsync()
}
}

[TestMethod]
public void SftpClient_HandleSftpSessionAbortByServer()
{
using (var client = new SftpClient(_connectionInfoFactory.Create()))
{
client.Connect();
Assert.IsTrue(client.IsConnected);

_sshConnectionDisruptor.BreakConnections();
WaitForConnectionInterruption(client);
Assert.IsFalse(client.IsConnected);

client.Connect();
Assert.IsTrue(client.IsConnected);

foreach (var file in client.ListDirectory("."))
{
}

client.Disconnect();
Assert.IsFalse(client.IsConnected);
}
}

[TestMethod]
public async Task SftpClient_HandleSftpSessionAbortByServerAsync()
{
using (var client = new SftpClient(_connectionInfoFactory.Create()))
{
await client.ConnectAsync(CancellationToken.None);
Assert.IsTrue(client.IsConnected);

_sshConnectionDisruptor.BreakConnections();
WaitForConnectionInterruption(client);
Assert.IsFalse(client.IsConnected);

await client.ConnectAsync(CancellationToken.None);
Assert.IsTrue(client.IsConnected);

await foreach (var file in client.ListDirectoryAsync(".", CancellationToken.None))
{
}

client.Disconnect();
Assert.IsFalse(client.IsConnected);
}
}

[TestMethod]
public void Common_DetectSessionKilledOnServer()
{
Expand Down

0 comments on commit 6669309

Please sign in to comment.