Move IsSocketConnected to Session.cs.

Move HandleMessageCore to Session.cs, and use FEATURE_DYNAMIC_TYPE conditional compilation symbol to use dynamic code.
This commit is contained in:
drieseng
2016-09-15 21:23:58 +02:00
parent 536f9bd2a4
commit 6237dd4982
6 changed files with 299 additions and 156 deletions
@@ -29,7 +29,7 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>Bin\Debug</OutputPath>
<DefineConstants>TRACE;DEBUG;FEATURE_DIRECTORYINFO_ENUMERATEFILES;FEATURE_RNG_CSP;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_STREAM_APM;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_HASH_SHA1_MANAGED;FEATURE_HASH_SHA256_MANAGED;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256</DefineConstants>
<DefineConstants>TRACE;DEBUG;FEATURE_DIRECTORYINFO_ENUMERATEFILES;FEATURE_RNG_CSP;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_STREAM_APM;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_HASH_SHA1_MANAGED;FEATURE_HASH_SHA256_MANAGED;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_DYNAMIC_TYPE</DefineConstants>
<NoStdLib>true</NoStdLib>
<NoConfig>true</NoConfig>
<ErrorReport>prompt</ErrorReport>
@@ -42,7 +42,7 @@
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>Bin\Release</OutputPath>
<DefineConstants>TRACE;FEATURE_DIRECTORYINFO_ENUMERATEFILES;FEATURE_RNG_CSP;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_STREAM_APM;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_HASH_SHA1_MANAGED;FEATURE_HASH_SHA256_MANAGED;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256</DefineConstants>
<DefineConstants>TRACE;FEATURE_DIRECTORYINFO_ENUMERATEFILES;FEATURE_RNG_CSP;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_STREAM_APM;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_HASH_SHA1_MANAGED;FEATURE_HASH_SHA256_MANAGED;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_DYNAMIC_TYPE</DefineConstants>
<NoStdLib>true</NoStdLib>
<NoConfig>true</NoConfig>
<ErrorReport>prompt</ErrorReport>
@@ -72,12 +72,6 @@
<Reference Include="System.Net" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Renci.SshNet.Silverlight\Session.SilverlightBrowser.cs">
<Link>Session.SilverlightBrowser.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet.Silverlight\Session.SilverlightShared.cs">
<Link>Session.SilverlightShared.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\Abstractions\CryptoAbstraction.cs">
<Link>Abstractions\CryptoAbstraction.cs</Link>
</Compile>
@@ -929,7 +923,7 @@
<FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}">
<SilverlightProjectProperties />
</FlavorProperties>
<UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" />
<UserProperties ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
</VisualStudio>
</ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
@@ -23,7 +23,7 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII</DefineConstants>
<DefineConstants>TRACE;DEBUG;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII;FEATURE_DYNAMIC_TYPE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\Renci.SshNet.xml</DocumentationFile>
@@ -34,7 +34,7 @@
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII</DefineConstants>
<DefineConstants>TRACE;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII;FEATURE_DYNAMIC_TYPE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\Renci.SshNet.xml</DocumentationFile>
@@ -44,7 +44,7 @@
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII</DefineConstants>
<DefineConstants>TRACE;DEBUG;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII;FEATURE_DYNAMIC_TYPE</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
@@ -54,7 +54,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII</DefineConstants>
<DefineConstants>TRACE;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII;FEATURE_DYNAMIC_TYPE</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
@@ -66,7 +66,7 @@
<PlatformTarget>ARM</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII</DefineConstants>
<DefineConstants>TRACE;DEBUG;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII;FEATURE_DYNAMIC_TYPE</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
@@ -76,7 +76,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<PlatformTarget>ARM</PlatformTarget>
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII</DefineConstants>
<DefineConstants>TRACE;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII;FEATURE_DYNAMIC_TYPE</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
@@ -88,7 +88,7 @@
<PlatformTarget>x64</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII</DefineConstants>
<DefineConstants>TRACE;DEBUG;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII;FEATURE_DYNAMIC_TYPE</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
@@ -98,7 +98,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII</DefineConstants>
<DefineConstants>TRACE;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII;FEATURE_DYNAMIC_TYPE</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
@@ -795,12 +795,6 @@
<Compile Include="..\Renci.SshNet\Session.cs">
<Link>Session.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\Session.NET.cs">
<Link>Session.NET.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\Session.NET40.cs">
<Link>Session.NET40.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\SftpClient.cs">
<Link>SftpClient.cs</Link>
</Compile>
+2 -8
View File
@@ -18,7 +18,7 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;FEATURE_REGEX_COMPILE;FEATURE_BINARY_SERIALIZATION;FEATURE_RNG_CREATE;FEATURE_SOCKET_SYNC;FEATURE_SOCKET_EAP;FEATURE_SOCKET_APM;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_SOCKET_POLL;FEATURE_STREAM_APM;FEATURE_DNS_SYNC;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_HASH_MD5;FEATURE_HASH_SHA1_CREATE;FEATURE_HASH_SHA256_CREATE;FEATURE_HASH_SHA384_CREATE;FEATURE_HASH_SHA512_CREATE;FEATURE_HASH_RIPEMD160_CREATE;FEATURE_HMAC_MD5;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_HMAC_SHA384;FEATURE_HMAC_SHA512;FEATURE_HMAC_RIPEMD160;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_DIAGNOSTICS_TRACESOURCE;FEATURE_ENCODING_ASCII</DefineConstants>
<DefineConstants>TRACE;DEBUG;FEATURE_REGEX_COMPILE;FEATURE_BINARY_SERIALIZATION;FEATURE_RNG_CREATE;FEATURE_SOCKET_SYNC;FEATURE_SOCKET_EAP;FEATURE_SOCKET_APM;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_SOCKET_POLL;FEATURE_STREAM_APM;FEATURE_DNS_SYNC;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_HASH_MD5;FEATURE_HASH_SHA1_CREATE;FEATURE_HASH_SHA256_CREATE;FEATURE_HASH_SHA384_CREATE;FEATURE_HASH_SHA512_CREATE;FEATURE_HASH_RIPEMD160_CREATE;FEATURE_HMAC_MD5;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_HMAC_SHA384;FEATURE_HMAC_SHA512;FEATURE_HMAC_RIPEMD160;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_DIAGNOSTICS_TRACESOURCE;FEATURE_ENCODING_ASCII;FEATURE_DYNAMIC_TYPE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\Renci.SshNet.xml</DocumentationFile>
@@ -29,7 +29,7 @@
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>FEATURE_REGEX_COMPILE;FEATURE_BINARY_SERIALIZATION;FEATURE_RNG_CREATE;FEATURE_SOCKET_SYNC;FEATURE_SOCKET_EAP;FEATURE_SOCKET_APM;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_SOCKET_POLL;FEATURE_STREAM_APM;FEATURE_DNS_SYNC;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_HASH_MD5;FEATURE_HASH_SHA1_CREATE;FEATURE_HASH_SHA256_CREATE;FEATURE_HASH_SHA384_CREATE;FEATURE_HASH_SHA512_CREATE;FEATURE_HASH_RIPEMD160_CREATE;FEATURE_HMAC_MD5;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_HMAC_SHA384;FEATURE_HMAC_SHA512;FEATURE_HMAC_RIPEMD160;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_DIAGNOSTICS_TRACESOURCE;FEATURE_ENCODING_ASCII</DefineConstants>
<DefineConstants>FEATURE_REGEX_COMPILE;FEATURE_BINARY_SERIALIZATION;FEATURE_RNG_CREATE;FEATURE_SOCKET_SYNC;FEATURE_SOCKET_EAP;FEATURE_SOCKET_APM;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_SOCKET_POLL;FEATURE_STREAM_APM;FEATURE_DNS_SYNC;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_HASH_MD5;FEATURE_HASH_SHA1_CREATE;FEATURE_HASH_SHA256_CREATE;FEATURE_HASH_SHA384_CREATE;FEATURE_HASH_SHA512_CREATE;FEATURE_HASH_RIPEMD160_CREATE;FEATURE_HMAC_MD5;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_HMAC_SHA384;FEATURE_HMAC_SHA512;FEATURE_HMAC_RIPEMD160;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_DIAGNOSTICS_TRACESOURCE;FEATURE_ENCODING_ASCII;FEATURE_DYNAMIC_TYPE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\Renci.SshNet.xml</DocumentationFile>
@@ -368,12 +368,6 @@
<Compile Include="Session.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Session.NET.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Session.NET40.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="SftpClient.cs">
<SubType>Code</SubType>
</Compile>
-83
View File
@@ -1,83 +0,0 @@
using System;
using System.Net.Sockets;
using Renci.SshNet.Abstractions;
namespace Renci.SshNet
{
public partial class Session
{
#if FEATURE_SOCKET_POLL
/// <summary>
/// Gets a value indicating whether the socket is connected.
/// </summary>
/// <param name="isConnected"><c>true</c> if the socket is connected; otherwise, <c>false</c></param>
/// <remarks>
/// <para>
/// As a first check we verify whether <see cref="Socket.Connected"/> is
/// <c>true</c>. However, this only returns the state of the socket as of
/// the last I/O operation.
/// </para>
/// <para>
/// Therefore we use the combination of <see cref="Socket.Poll(int, SelectMode)"/> with mode <see cref="SelectMode.SelectRead"/>
/// and <see cref="Socket.Available"/> to verify if the socket is still connected.
/// </para>
/// <para>
/// The MSDN doc mention the following on the return value of <see cref="Socket.Poll(int, SelectMode)"/>
/// with mode <see cref="SelectMode.SelectRead"/>:
/// <list type="bullet">
/// <item>
/// <description><c>true</c> if data is available for reading;</description>
/// </item>
/// <item>
/// <description><c>true</c> if the connection has been closed, reset, or terminated; otherwise, returns <c>false</c>.</description>
/// </item>
/// </list>
/// </para>
/// <para>
/// <c>Conclusion:</c> when the return value is <c>true</c> - but no data is available for reading - then
/// the socket is no longer connected.
/// </para>
/// <para>
/// When a <see cref="Socket"/> is used from multiple threads, there's a race condition
/// between the invocation of <see cref="Socket.Poll(int, SelectMode)"/> and the moment
/// when the value of <see cref="Socket.Available"/> is obtained. To workaround this issue
/// we synchronize reads from the <see cref="Socket"/>.
/// </para>
/// </remarks>
#else
/// <summary>
/// Gets a value indicating whether the socket is connected.
/// </summary>
/// <param name="isConnected"><c>true</c> if the socket is connected; otherwise, <c>false</c></param>
/// <remarks>
/// We verify whether <see cref="Socket.Connected"/> is <c>true</c>. However, this only returns the state
/// of the socket as of the last I/O operation.
/// </remarks>
#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));
}
}
}
-15
View File
@@ -1,15 +0,0 @@
using Renci.SshNet.Messages;
namespace Renci.SshNet
{
/// <summary>
/// Provides functionality to connect and interact with SSH server.
/// </summary>
public partial class Session
{
partial void HandleMessageCore(Message message)
{
HandleMessage((dynamic)message);
}
}
}
+286 -27
View File
@@ -247,7 +247,7 @@ namespace Renci.SshNet
/// <c>true</c> if the session is connected; otherwise, <c>false</c>.
/// </value>
/// <remarks>
/// This methods returns true in all but the following cases:
/// This methods returns <c>true</c> in all but the following cases:
/// <list type="bullet">
/// <item>
/// <description>The <see cref="Session"/> is disposed.</description>
@@ -275,9 +275,7 @@ namespace Renci.SshNet
if (_messageListenerCompleted == null || _messageListenerCompleted.WaitOne(0))
return false;
var isSocketConnected = false;
IsSocketConnected(ref isSocketConnected);
return isSocketConnected;
return IsSocketConnected();
}
}
@@ -1065,7 +1063,202 @@ namespace Renci.SshNet
_isDisconnectMessageSent = true;
}
partial void HandleMessageCore(Message message);
void HandleMessageCore(Message message)
{
if (message == null)
throw new ArgumentNullException("message");
#if FEATURE_DYNAMIC_TYPE
HandleMessage((dynamic) message);
#else
var disconnectMessage = message as DisconnectMessage;
if (disconnectMessage != null)
{
HandleMessage(disconnectMessage);
return;
}
var serviceRequestMessage = message as ServiceRequestMessage;
if (serviceRequestMessage != null)
{
HandleMessage(serviceRequestMessage);
return;
}
var serviceAcceptMessage = message as ServiceAcceptMessage;
if (serviceAcceptMessage != null)
{
HandleMessage(serviceAcceptMessage);
return;
}
var keyExchangeInitMessage = message as KeyExchangeInitMessage;
if (keyExchangeInitMessage != null)
{
HandleMessage(keyExchangeInitMessage);
return;
}
var newKeysMessage = message as NewKeysMessage;
if (newKeysMessage != null)
{
HandleMessage(newKeysMessage);
return;
}
var requestMessage = message as RequestMessage;
if (requestMessage != null)
{
HandleMessage(requestMessage);
return;
}
var failureMessage = message as FailureMessage;
if (failureMessage != null)
{
HandleMessage(failureMessage);
return;
}
var successMessage = message as SuccessMessage;
if (successMessage != null)
{
HandleMessage(successMessage);
return;
}
var bannerMessage = message as BannerMessage;
if (bannerMessage != null)
{
HandleMessage(bannerMessage);
return;
}
var globalRequestMessage = message as GlobalRequestMessage;
if (globalRequestMessage != null)
{
HandleMessage(globalRequestMessage);
return;
}
var requestSuccessMessage = message as RequestSuccessMessage;
if (requestSuccessMessage != null)
{
HandleMessage(requestSuccessMessage);
return;
}
var requestFailureMessage = message as RequestFailureMessage;
if (requestFailureMessage != null)
{
HandleMessage(requestFailureMessage);
return;
}
var channelOpenMessage = message as ChannelOpenMessage;
if (channelOpenMessage != null)
{
HandleMessage(channelOpenMessage);
return;
}
var channelOpenConfirmationMessage = message as ChannelOpenConfirmationMessage;
if (channelOpenConfirmationMessage != null)
{
HandleMessage(channelOpenConfirmationMessage);
return;
}
var channelOpenFailureMessage = message as ChannelOpenFailureMessage;
if (channelOpenFailureMessage != null)
{
HandleMessage(channelOpenFailureMessage);
return;
}
var channelWindowAdjustMessage = message as ChannelWindowAdjustMessage;
if (channelWindowAdjustMessage != null)
{
HandleMessage(channelWindowAdjustMessage);
return;
}
var channelDataMessage = message as ChannelDataMessage;
if (channelDataMessage != null)
{
HandleMessage(channelDataMessage);
return;
}
var channelExtendedDataMessage = message as ChannelExtendedDataMessage;
if (channelExtendedDataMessage != null)
{
HandleMessage(channelExtendedDataMessage);
return;
}
var channelEofMessage = message as ChannelEofMessage;
if (channelEofMessage != null)
{
HandleMessage(channelEofMessage);
return;
}
var channelCloseMessage = message as ChannelCloseMessage;
if (channelCloseMessage != null)
{
HandleMessage(channelCloseMessage);
return;
}
var channelRequestMessage = message as ChannelRequestMessage;
if (channelRequestMessage != null)
{
HandleMessage(channelRequestMessage);
return;
}
var channelSuccessMessage = message as ChannelSuccessMessage;
if (channelSuccessMessage != null)
{
HandleMessage(channelSuccessMessage);
return;
}
var channelFailureMessage = message as ChannelFailureMessage;
if (channelFailureMessage != null)
{
HandleMessage(channelFailureMessage);
return;
}
var ignoreMessage = message as IgnoreMessage;
if (ignoreMessage != null)
{
HandleMessage(ignoreMessage);
return;
}
var unimplementedMessage = message as UnimplementedMessage;
if (unimplementedMessage != null)
{
HandleMessage(unimplementedMessage);
return;
}
var debugMessage = message as DebugMessage;
if (debugMessage != null)
{
HandleMessage(debugMessage);
return;
}
throw new NotImplementedException("Message type '{0}' is not implemented. Please submit an issue.", message.GetType().FullName);
}
#error FUCK
#endif
}
/// <summary>
/// Handles the message.
@@ -1074,10 +1267,11 @@ namespace Renci.SshNet
/// <param name="message">The message.</param>
private void HandleMessage<T>(T message) where T : Message
{
DiagnosticAbstraction.Log(string.Format("[{0}] Message<{1}> received", ToHex(SessionId), typeof(T).FullName));
OnMessageReceived(message);
}
#region Handle transport messages
#region Handle transport messages
/// <summary>
/// Invoked via reflection.
@@ -1146,9 +1340,9 @@ namespace Renci.SshNet
OnNewKeysReceived(message);
}
#endregion
#endregion
#region Handle User Authentication messages
#region Handle User Authentication messages
/// <summary>
/// Invoked via reflection.
@@ -1182,9 +1376,9 @@ namespace Renci.SshNet
OnUserAuthenticationBannerReceived(message);
}
#endregion
#endregion
#region Handle connection messages
#region Handle connection messages
/// <summary>
/// Invoked via reflection.
@@ -1298,9 +1492,9 @@ namespace Renci.SshNet
OnChannelFailureReceived(message);
}
#endregion
#endregion
#region Handle received message events
#region Handle received message events
/// <summary>
/// Called when <see cref="DisconnectMessage"/> received.
@@ -1684,7 +1878,7 @@ namespace Renci.SshNet
handlers(this, new MessageEventArgs<Message>(message));
}
#endregion
#endregion
private void KeyExchange_HostKeyReceived(object sender, HostKeyEventArgs e)
{
@@ -1693,7 +1887,7 @@ namespace Renci.SshNet
handlers(this, e);
}
#region Message loading functions
#region Message loading functions
/// <summary>
/// Registers SSH message with the session.
@@ -1763,15 +1957,7 @@ namespace Renci.SshNet
return ToHex(bytes, 0);
}
#endregion
/// <summary>
/// Gets a value indicating whether the socket is connected.
/// </summary>
/// <value>
/// <c>true</c> if the socket is connected; otherwise, <c>false</c>.
/// </value>
partial void IsSocketConnected(ref bool isConnected);
#endregion
/// <summary>
/// Establishes a socket connection to the specified host and port.
@@ -1820,6 +2006,79 @@ namespace Renci.SshNet
return bytesRead;
}
#if FEATURE_SOCKET_POLL
/// <summary>
/// Gets a value indicating whether the socket is connected.
/// </summary>
/// <returns>
/// <c>true</c> if the socket is connected; otherwise, <c>false</c>.
/// </returns>
/// <remarks>
/// <para>
/// As a first check we verify whether <see cref="Socket.Connected"/> is
/// <c>true</c>. However, this only returns the state of the socket as of
/// the last I/O operation.
/// </para>
/// <para>
/// Therefore we use the combination of <see cref="Socket.Poll(int, SelectMode)"/> with mode <see cref="SelectMode.SelectRead"/>
/// and <see cref="Socket.Available"/> to verify if the socket is still connected.
/// </para>
/// <para>
/// The MSDN doc mention the following on the return value of <see cref="Socket.Poll(int, SelectMode)"/>
/// with mode <see cref="SelectMode.SelectRead"/>:
/// <list type="bullet">
/// <item>
/// <description><c>true</c> if data is available for reading;</description>
/// </item>
/// <item>
/// <description><c>true</c> if the connection has been closed, reset, or terminated; otherwise, returns <c>false</c>.</description>
/// </item>
/// </list>
/// </para>
/// <para>
/// <c>Conclusion:</c> when the return value is <c>true</c> - but no data is available for reading - then
/// the socket is no longer connected.
/// </para>
/// <para>
/// When a <see cref="Socket"/> is used from multiple threads, there's a race condition
/// between the invocation of <see cref="Socket.Poll(int, SelectMode)"/> and the moment
/// when the value of <see cref="Socket.Available"/> is obtained. To workaround this issue
/// we synchronize reads from the <see cref="Socket"/>.
/// </para>
/// </remarks>
#else
/// <summary>
/// Gets a value indicating whether the socket is connected.
/// </summary>
/// <returns>
/// <c>true</c> if the socket is connected; otherwise, <c>false</c>.
/// </returns>
/// <remarks>
/// We verify whether <see cref="Socket.Connected"/> is <c>true</c>. However, this only returns the state
/// of the socket as of the last I/O operation.
/// </remarks>
#endif
private bool IsSocketConnected()
{
lock (_socketDisposeLock)
{
#if FEATURE_SOCKET_POLL
if (!_socket.IsConnected())
{
return false;
}
lock (_socketReadLock)
{
var connectionClosedOrDataAvailable = _socket.Poll(0, SelectMode.SelectRead);
return !(connectionClosedOrDataAvailable && _socket.Available == 0);
}
#else
return _socket.IsConnected();
#endif // FEATURE_SOCKET_POLL
}
}
/// <summary>
/// Performs a blocking read on the socket until <paramref name="length"/> bytes are received.
/// </summary>
@@ -2350,7 +2609,7 @@ namespace Renci.SshNet
DisconnectReason.ConnectionLost);
}
#region IDisposable implementation
#region IDisposable implementation
private bool _disposed;
@@ -2441,9 +2700,9 @@ namespace Renci.SshNet
Dispose(false);
}
#endregion IDisposable implementation
#endregion IDisposable implementation
#region ISession implementation
#region ISession implementation
/// <summary>
/// Gets or sets the connection info.
@@ -2528,6 +2787,6 @@ namespace Renci.SshNet
return TrySendMessage(message);
}
#endregion ISession implementation
#endregion ISession implementation
}
}