using System; using System.Net.Sockets; using Renci.SshNet.Abstractions; namespace Renci.SshNet { public partial class Session { #if FEATURE_SOCKET_POLL /// /// Gets a value indicating whether the socket is connected. /// /// true if the socket is connected; otherwise, false /// /// /// As a first check we verify whether is /// true. However, this only returns the state of the socket as of /// the last I/O operation. /// /// /// Therefore we use the combination of with mode /// and to verify if the socket is still connected. /// /// /// The MSDN doc mention the following on the return value of /// with mode : /// /// /// true if data is available for reading; /// /// /// true if the connection has been closed, reset, or terminated; otherwise, returns false. /// /// /// /// /// Conclusion: when the return value is true - but no data is available for reading - then /// the socket is no longer connected. /// /// /// When a is used from multiple threads, there's a race condition /// between the invocation of and the moment /// when the value of is obtained. To workaround this issue /// we synchronize reads from the . /// /// #else /// /// Gets a value indicating whether the socket is connected. /// /// true if the socket is connected; otherwise, false /// /// We verify whether is true. However, this only returns the state /// of the socket as of the last I/O operation. /// #endif partial void IsSocketConnected(ref bool isConnected) { DiagnosticAbstraction.Log(string.Format("[{0}] {1} Checking socket", ToHex(SessionId), DateTime.Now.Ticks)); lock (_socketDisposeLock) { #if FEATURE_SOCKET_POLL if (!_socket.IsConnected()) { isConnected = false; return; } lock (_socketReadLock) { var connectionClosedOrDataAvailable = _socket.Poll(0, SelectMode.SelectRead); isConnected = !(connectionClosedOrDataAvailable && _socket.Available == 0); } #else isConnected = _socket.IsConnected(); #endif // FEATURE_SOCKET_POLL } DiagnosticAbstraction.Log(string.Format("[{0}] {1} Checked socket", ToHex(SessionId), DateTime.Now.Ticks)); } } }