@@ -290,6 +290,7 @@ public bool IsConnected
290
290
public byte [ ] SessionId { get ; private set ; }
291
291
292
292
private Message _clientInitMessage ;
293
+
293
294
/// <summary>
294
295
/// Gets the client init message.
295
296
/// </summary>
@@ -756,11 +757,11 @@ internal void WaitOnHandle(WaitHandle waitHandle, TimeSpan timeout)
756
757
throw new ArgumentNullException ( "waitHandle" ) ;
757
758
758
759
var waitHandles = new [ ]
759
- {
760
- _exceptionWaitHandle ,
761
- _messageListenerCompleted ,
762
- waitHandle
763
- } ;
760
+ {
761
+ _exceptionWaitHandle ,
762
+ _messageListenerCompleted ,
763
+ waitHandle
764
+ } ;
764
765
765
766
switch ( WaitHandle . WaitAny ( waitHandles , timeout ) )
766
767
{
@@ -803,9 +804,7 @@ internal void SendMessage(Message message)
803
804
804
805
DiagnosticAbstraction . Log ( string . Format ( "[{0}] SendMessage to server '{1}': '{2}'." , ToHex ( SessionId ) , message . GetType ( ) . Name , message ) ) ;
805
806
806
- // Messages can be sent by different thread so we need to synchronize it
807
- var paddingMultiplier = _clientCipher == null ? ( byte ) 8 : Math . Max ( ( byte ) 8 , _serverCipher . MinimumSize ) ; // Should be recalculate base on cipher min length if cipher specified
808
-
807
+ var paddingMultiplier = _clientCipher == null ? ( byte ) 8 : Math . Max ( ( byte ) 8 , _serverCipher . MinimumSize ) ;
809
808
var packetData = message . GetPacket ( paddingMultiplier , _clientCompression ) ;
810
809
811
810
// take a write lock to ensure the outbound packet sequence number is incremented
@@ -845,7 +844,7 @@ internal void SendMessage(Message message)
845
844
}
846
845
else
847
846
{
848
- var data = new byte [ packetLength + ( _clientMac . HashSize / 8 ) ] ;
847
+ var data = new byte [ packetLength + ( _clientMac . HashSize / 8 ) ] ;
849
848
Buffer . BlockCopy ( packetData , packetDataOffset , data , 0 , packetLength ) ;
850
849
Buffer . BlockCopy ( hash , 0 , data , packetLength , hash . Length ) ;
851
850
@@ -915,7 +914,7 @@ private Message ReceiveMessage()
915
914
// Determine the size of the first block, which is 8 or cipher block size (whichever is larger) bytes
916
915
var blockSize = _serverCipher == null ? ( byte ) 8 : Math . Max ( ( byte ) 8 , _serverCipher . MinimumSize ) ;
917
916
918
- var serverMacLength = _serverMac != null ? _serverMac . HashSize / 8 : 0 ;
917
+ var serverMacLength = _serverMac != null ? _serverMac . HashSize / 8 : 0 ;
919
918
920
919
byte [ ] data ;
921
920
uint packetLength ;
@@ -1053,7 +1052,7 @@ private void HandleMessage<T>(T message) where T : Message
1053
1052
OnMessageReceived ( message ) ;
1054
1053
}
1055
1054
1056
- #region Handle transport messages
1055
+ #region Handle transport messages
1057
1056
1058
1057
/// <summary>
1059
1058
/// Invoked via reflection.
@@ -1122,9 +1121,9 @@ private void HandleMessage(NewKeysMessage message)
1122
1121
OnNewKeysReceived ( message ) ;
1123
1122
}
1124
1123
1125
- #endregion
1124
+ #endregion
1126
1125
1127
- #region Handle User Authentication messages
1126
+ #region Handle User Authentication messages
1128
1127
1129
1128
/// <summary>
1130
1129
/// Invoked via reflection.
@@ -1158,9 +1157,9 @@ private void HandleMessage(BannerMessage message)
1158
1157
OnUserAuthenticationBannerReceived ( message ) ;
1159
1158
}
1160
1159
1161
- #endregion
1160
+ #endregion
1162
1161
1163
- #region Handle connection messages
1162
+ #region Handle connection messages
1164
1163
1165
1164
/// <summary>
1166
1165
/// Invoked via reflection.
@@ -1274,9 +1273,9 @@ private void HandleMessage(ChannelFailureMessage message)
1274
1273
OnChannelFailureReceived ( message ) ;
1275
1274
}
1276
1275
1277
- #endregion
1276
+ #endregion
1278
1277
1279
- #region Handle received message events
1278
+ #region Handle received message events
1280
1279
1281
1280
/// <summary>
1282
1281
/// Called when <see cref="DisconnectMessage"/> received.
@@ -1660,7 +1659,7 @@ protected virtual void OnMessageReceived(Message message)
1660
1659
handlers ( this , new MessageEventArgs < Message > ( message ) ) ;
1661
1660
}
1662
1661
1663
- #endregion
1662
+ #endregion
1664
1663
1665
1664
private void KeyExchange_HostKeyReceived ( object sender , HostKeyEventArgs e )
1666
1665
{
@@ -1739,7 +1738,7 @@ internal static string ToHex(byte[] bytes)
1739
1738
return ToHex ( bytes , 0 ) ;
1740
1739
}
1741
1740
1742
- #endregion
1741
+ #endregion
1743
1742
1744
1743
/// <summary>
1745
1744
/// Gets a value indicating whether the socket is connected.
@@ -1865,22 +1864,33 @@ private void SocketDisconnectAndDispose()
1865
1864
{
1866
1865
if ( _socket . Connected )
1867
1866
{
1868
- // interrupt any pending reads
1869
- _socket . Shutdown ( SocketShutdown . Send ) ;
1867
+ try
1868
+ {
1869
+ // interrupt any pending reads; should be done outside of socket read lock as we
1870
+ // actually want shutdown the socket to make sure blocking reads are interrupted
1871
+ _socket . Shutdown ( SocketShutdown . Send ) ;
1870
1872
1871
1873
#if FEATURE_SOCKET_POLL
1872
- // since we've shut down the socket, there should not be any reads in progress but
1873
- // we still take a read lock to ensure IsSocketConnected continues to provide
1874
- // correct results
1875
- //
1876
- // only necessary if IsSocketConnected actually uses Socket.Poll.
1877
- lock ( _socketReadLock )
1878
- {
1874
+ // since we've shut down the socket, there should not be any reads in progress but
1875
+ // we still take a read lock to ensure IsSocketConnected continues to provide
1876
+ // correct results
1877
+ //
1878
+ // see IsSocketConnected for details on the race condition we avoid with this lock
1879
+ //
1880
+ // this race condition only exists if IsSocketConnected actually uses Socket.Poll,
1881
+ // and as such this read is also only required when Socket.Poll is available
1882
+ lock ( _socketReadLock )
1883
+ {
1879
1884
#endif // FEATURE_SOCKET_POLL
1880
- SocketAbstraction . ClearReadBuffer ( _socket ) ;
1885
+ SocketAbstraction . ClearReadBuffer ( _socket ) ;
1881
1886
#if FEATURE_SOCKET_POLL
1882
- }
1887
+ }
1883
1888
#endif // FEATURE_SOCKET_POLL
1889
+ }
1890
+ catch ( SocketException ex )
1891
+ {
1892
+ DiagnosticAbstraction . Log ( "Failure shutting down socket or clearing read buffer: " + ex ) ;
1893
+ }
1884
1894
}
1885
1895
1886
1896
_socket . Dispose ( ) ;
@@ -2229,11 +2239,13 @@ private void ConnectHttp()
2229
2239
/// <summary>
2230
2240
/// Raises the <see cref="ErrorOccured"/> event.
2231
2241
/// </summary>
2232
- /// <param name="exp">The exp .</param>
2242
+ /// <param name="exp">The <see cref="Exception"/> .</param>
2233
2243
private void RaiseError ( Exception exp )
2234
2244
{
2235
2245
var connectionException = exp as SshConnectionException ;
2236
2246
2247
+ DiagnosticAbstraction . Log ( string . Format ( "[{0}] {1} Raised exception: {2}" , ToHex ( SessionId ) , DateTime . Now . Ticks , exp ) ) ;
2248
+
2237
2249
if ( _isDisconnecting )
2238
2250
{
2239
2251
// a connection exception which is raised while isDisconnecting is normal and
@@ -2248,10 +2260,7 @@ private void RaiseError(Exception exp)
2248
2260
return ;
2249
2261
}
2250
2262
2251
- DiagnosticAbstraction . Log ( string . Format ( "[{0}] {1} Raised exception: {2}" , ToHex ( SessionId ) , DateTime . Now . Ticks , exp ) ) ;
2252
-
2253
2263
_exception = exp ;
2254
-
2255
2264
_exceptionWaitHandle . Set ( ) ;
2256
2265
2257
2266
var errorOccured = ErrorOccured ;
0 commit comments