|  | @@ -49,8 +49,18 @@ namespace Renci.SshNet.Abstractions
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          public static Socket Connect(IPEndPoint remoteEndpoint, TimeSpan connectTimeout)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var socket = new Socket(remoteEndpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp) {NoDelay = true};
 | 
	
		
			
				|  |  | +            var socket = new Socket(remoteEndpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp) { NoDelay = true };
 | 
	
		
			
				|  |  | +            ConnectCore(socket, remoteEndpoint, connectTimeout, true);
 | 
	
		
			
				|  |  | +            return socket;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        public static void Connect(Socket socket, IPEndPoint remoteEndpoint, TimeSpan connectTimeout)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            ConnectCore(socket, remoteEndpoint, connectTimeout, false);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        private static void ConnectCore(Socket socket, IPEndPoint remoteEndpoint, TimeSpan connectTimeout, bool ownsSocket)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  |  #if FEATURE_SOCKET_EAP
 | 
	
		
			
				|  |  |              var connectCompleted = new ManualResetEvent(false);
 | 
	
		
			
				|  |  |              var args = new SocketAsyncEventArgs
 | 
	
	
		
			
				|  | @@ -66,8 +76,11 @@ namespace Renci.SshNet.Abstractions
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  |                      // avoid ObjectDisposedException in ConnectCompleted
 | 
	
		
			
				|  |  |                      args.Completed -= ConnectCompleted;
 | 
	
		
			
				|  |  | -                    // dispose Socket
 | 
	
		
			
				|  |  | -                    socket.Dispose();
 | 
	
		
			
				|  |  | +                    if (ownsSocket)
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        // dispose Socket
 | 
	
		
			
				|  |  | +                        socket.Dispose();
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  |                      // dispose ManualResetEvent
 | 
	
		
			
				|  |  |                      connectCompleted.Dispose();
 | 
	
		
			
				|  |  |                      // dispose SocketAsyncEventArgs
 | 
	
	
		
			
				|  | @@ -86,8 +99,12 @@ namespace Renci.SshNet.Abstractions
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  var socketError = (int) args.SocketError;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                // dispose Socket
 | 
	
		
			
				|  |  | -                socket.Dispose();
 | 
	
		
			
				|  |  | +                if (ownsSocket)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    // dispose Socket
 | 
	
		
			
				|  |  | +                    socket.Dispose();
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |                  // dispose SocketAsyncEventArgs
 | 
	
		
			
				|  |  |                  args.Dispose();
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -96,20 +113,16 @@ namespace Renci.SshNet.Abstractions
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              // dispose SocketAsyncEventArgs
 | 
	
		
			
				|  |  |              args.Dispose();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            return socket;
 | 
	
		
			
				|  |  |  #elif FEATURE_SOCKET_APM
 | 
	
		
			
				|  |  |              var connectResult = socket.BeginConnect(remoteEndpoint, null, null);
 | 
	
		
			
				|  |  |              if (!connectResult.AsyncWaitHandle.WaitOne(connectTimeout, false))
 | 
	
		
			
				|  |  |                  throw new SshOperationTimeoutException(string.Format(CultureInfo.InvariantCulture,
 | 
	
		
			
				|  |  |                      "Connection failed to establish within {0:F0} milliseconds.", connectTimeout.TotalMilliseconds));
 | 
	
		
			
				|  |  |              socket.EndConnect(connectResult);
 | 
	
		
			
				|  |  | -            return socket;
 | 
	
		
			
				|  |  |  #elif FEATURE_SOCKET_TAP
 | 
	
		
			
				|  |  |              if (!socket.ConnectAsync(remoteEndpoint).Wait(connectTimeout))
 | 
	
		
			
				|  |  |                  throw new SshOperationTimeoutException(string.Format(CultureInfo.InvariantCulture,
 | 
	
		
			
				|  |  |                      "Connection failed to establish within {0:F0} milliseconds.", connectTimeout.TotalMilliseconds));
 | 
	
		
			
				|  |  | -            return socket;
 | 
	
		
			
				|  |  |  #else
 | 
	
		
			
				|  |  |              #error Connecting to a remote endpoint is not implemented.
 | 
	
		
			
				|  |  |  #endif
 | 
	
	
		
			
				|  | @@ -311,24 +324,28 @@ namespace Renci.SshNet.Abstractions
 | 
	
		
			
				|  |  |          /// <param name="buffer">An array of type <see cref="byte"/> that is the storage location for the received data. </param>
 | 
	
		
			
				|  |  |          /// <param name="offset">The position in <paramref name="buffer"/> parameter to store the received data.</param>
 | 
	
		
			
				|  |  |          /// <param name="size">The number of bytes to receive.</param>
 | 
	
		
			
				|  |  | -        /// <param name="timeout">Specifies the amount of time after which the call will time out.</param>
 | 
	
		
			
				|  |  | +        /// <param name="readTimeout">The maximum time to wait until <paramref name="size"/> bytes have been received.</param>
 | 
	
		
			
				|  |  |          /// <returns>
 | 
	
		
			
				|  |  |          /// The number of bytes received.
 | 
	
		
			
				|  |  |          /// </returns>
 | 
	
		
			
				|  |  |          /// <remarks>
 | 
	
		
			
				|  |  | +        /// <para>
 | 
	
		
			
				|  |  |          /// If no data is available for reading, the <see cref="Read(Socket, byte[], int, int, TimeSpan)"/> method will
 | 
	
		
			
				|  |  |          /// block until data is available or the time-out value is exceeded. If the time-out value is exceeded, the
 | 
	
		
			
				|  |  |          /// <see cref="Read(Socket, byte[], int, int, TimeSpan)"/> call will throw a <see cref="SshOperationTimeoutException"/>.
 | 
	
		
			
				|  |  | -        ///  If you are in non-blocking mode, and there is no data available in the in the protocol stack buffer, the
 | 
	
		
			
				|  |  | +        /// </para>
 | 
	
		
			
				|  |  | +        /// <para>
 | 
	
		
			
				|  |  | +        /// If you are in non-blocking mode, and there is no data available in the in the protocol stack buffer, the
 | 
	
		
			
				|  |  |          /// <see cref="Read(Socket, byte[], int, int, TimeSpan)"/> method will complete immediately and throw a <see cref="SocketException"/>.
 | 
	
		
			
				|  |  | +        /// </para>
 | 
	
		
			
				|  |  |          /// </remarks>
 | 
	
		
			
				|  |  | -        public static int Read(Socket socket, byte[] buffer, int offset, int size, TimeSpan timeout)
 | 
	
		
			
				|  |  | +        public static int Read(Socket socket, byte[] buffer, int offset, int size, TimeSpan readTimeout)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |  #if FEATURE_SOCKET_SYNC
 | 
	
		
			
				|  |  |              var totalBytesRead = 0;
 | 
	
		
			
				|  |  |              var totalBytesToRead = size;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            socket.ReceiveTimeout = (int) timeout.TotalMilliseconds;
 | 
	
		
			
				|  |  | +            socket.ReceiveTimeout = (int)readTimeout.TotalMilliseconds;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              do
 | 
	
		
			
				|  |  |              {
 | 
	
	
		
			
				|  | @@ -350,7 +367,7 @@ namespace Renci.SshNet.Abstractions
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                      if (ex.SocketErrorCode == SocketError.TimedOut)
 | 
	
		
			
				|  |  |                          throw new SshOperationTimeoutException(string.Format(CultureInfo.InvariantCulture,
 | 
	
		
			
				|  |  | -                            "Socket read operation has timed out after {0:F0} milliseconds.", timeout.TotalMilliseconds));
 | 
	
		
			
				|  |  | +                            "Socket read operation has timed out after {0:F0} milliseconds.", readTimeout.TotalMilliseconds));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                       throw;
 | 
	
		
			
				|  |  |                  }
 |