Переглянути джерело

Add Connect overload that takes existing Socket instance.

drieseng 4 роки тому
батько
коміт
e0b32a41ea
1 змінених файлів з 31 додано та 14 видалено
  1. 31 14
      src/Renci.SshNet/Abstractions/SocketAbstraction.cs

+ 31 - 14
src/Renci.SshNet/Abstractions/SocketAbstraction.cs

@@ -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;
                 }