Description
I need to implement SFTP connection pooling. As part of this I need to have long running SftpClient
s 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?