Skip to content

Commit

Permalink
fix "client not connected" after SFTP reconnect
Browse files Browse the repository at this point in the history
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 sshnet#1474
  • Loading branch information
mus65 committed Sep 5, 2024
1 parent a157dd3 commit 7b3ea80
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 9 deletions.
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 7b3ea80

Please sign in to comment.