-
-
Notifications
You must be signed in to change notification settings - Fork 970
Description
I need to implement SFTP connection pooling. As part of this I need to have long running SftpClients and a way to check if the client is still connected. Initially I used SftpClient.IsConnected for this purpose. However, even if SftpClient.IsConnected returned true, I many times got this exception when trying to use the SftpClient instance:
System.InvalidOperationException: The session is not open.
at Renci.SshNet.SubsystemSession.EnsureSessionIsOpen()
at Renci.SshNet.SubsystemSession.SendData(Byte[] data)
at Renci.SshNet.Sftp.SftpSession.SendMessage(SftpMessage sftpMessage)
at Renci.SshNet.Sftp.SftpSession.SendRequest(SftpRequest request)
...
Here is the class diagram of the relevant portion of SSH.NET: https://gitmind.com/app/flowchart/75ace876ac90aec4dbce3b61347c6cf9
Based on this architecture, it seems to me that the described problem is caused by SftpClient not taking into account the SubsystemSession's state. As an intermediate workaround I made BaseClient.IsConnected virtual and implemented it in SftpClient as:
public override bool IsConnected
{
get
{
return base.IsConnected && _sftpSession.IsOpen;
}
}Initial tests show this solves my problem, but further testing is needed to really claim this.
Can someone with more insight into the codebase confirm my reasoning so far? I would also be thankful if the one could answer the questions that pop up in my mind looking at this class diagram:
- There are a lot of classes named *Session in this diagram... can someone explain what these classes do conceptually? Is the naming good?
- Is there a reason for Session and SubsystemSession to hold their own respective status? Does/should a change in one's state relate to a change in the other's state?
- Why do BaseClient and Session each hold ConnectionInfo? Are these two the same?