瀏覽代碼

Add ASCIIEncoding to be used internally and also by Silverlight implementations
Misc logic sepeartion to prepare for Silverlight

olegkap_cp 14 年之前
父節點
當前提交
445d995f44

+ 68 - 0
Renci.SshClient/Renci.SshNet.Silverlight/Common/ASCIIEncoding.Silverlight.cs

@@ -0,0 +1,68 @@
+using System;
+using System.Net;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Shapes;
+using System.Text;
+
+namespace Renci.SshNet.Common
+{
+    public partial class ASCIIEncoding : Encoding
+    {
+        /// <summary>
+        /// Gets the name registered with the
+        /// Internet Assigned Numbers Authority (IANA) for the current encoding.
+        /// </summary>
+        /// <returns>
+        /// The IANA name for the current <see cref="System.Text.Encoding"/>.
+        /// </returns>
+        public override string WebName
+        {
+            get
+            {
+                return "iso-8859-1";
+            }
+        }
+
+        /// <summary>
+        /// Decodes all the bytes in the specified byte array into a string.
+        /// </summary>
+        /// <param name="bytes">The byte array containing the sequence of bytes to decode.</param>
+        /// <returns>
+        /// A <see cref="T:System.String"/> containing the results of decoding the specified sequence of bytes.
+        /// </returns>
+        /// <exception cref="T:System.ArgumentException">The byte array contains invalid Unicode code points.</exception>
+        ///   
+        /// <exception cref="T:System.ArgumentNullException">
+        ///   <paramref name="bytes"/> is null. </exception>
+        ///   
+        /// <exception cref="T:System.Text.DecoderFallbackException">A fallback occurred (see Understanding Encodings for complete explanation)-and-<see cref="P:System.Text.Encoding.DecoderFallback"/> is set to <see cref="T:System.Text.DecoderExceptionFallback"/>.</exception>
+        public String GetString(byte[] bytes)
+        {
+            if (bytes == null)
+            {
+                throw new ArgumentNullException("bytes");
+            }
+            if (bytes.Length == 0)
+            {
+                return String.Empty;
+            }
+            int count = bytes.Length;
+            int posn = 0;
+
+            char[] chars = new char[count];
+
+            while (count-- > 0)
+            {
+                chars[posn] = (char)(bytes[posn]);
+                ++posn;
+            }
+            return new string(chars);
+        }    
+    }
+}

+ 10 - 3
Renci.SshClient/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj

@@ -80,6 +80,9 @@
     <Compile Include="..\Renci.SshNet\Channels\ChannelTypes.cs">
       <Link>Channels\ChannelTypes.cs</Link>
     </Compile>
+    <Compile Include="..\Renci.SshNet\Common\ASCIIEncoding.cs">
+      <Link>Common\ASCIIEncoding.cs</Link>
+    </Compile>
     <Compile Include="..\Renci.SshNet\Common\AsyncResult.cs">
       <Link>Common\AsyncResult.cs</Link>
     </Compile>
@@ -98,6 +101,9 @@
     <Compile Include="..\Renci.SshNet\Common\AuthenticationPromptEventArgs.cs">
       <Link>Common\AuthenticationPromptEventArgs.cs</Link>
     </Compile>
+    <Compile Include="..\Renci.SshNet\Common\BigInteger.cs">
+      <Link>Common\BigInteger.cs</Link>
+    </Compile>
     <Compile Include="..\Renci.SshNet\Common\ChannelDataEventArgs.cs">
       <Link>Common\ChannelDataEventArgs.cs</Link>
     </Compile>
@@ -122,6 +128,9 @@
     <Compile Include="..\Renci.SshNet\Common\PortForwardEventArgs.cs">
       <Link>Common\PortForwardEventArgs.cs</Link>
     </Compile>
+    <Compile Include="..\Renci.SshNet\Common\SemaphoreLight.cs">
+      <Link>Common\SemaphoreLight.cs</Link>
+    </Compile>
     <Compile Include="..\Renci.SshNet\Common\SftpPathNotFoundException.cs">
       <Link>Common\SftpPathNotFoundException.cs</Link>
     </Compile>
@@ -158,9 +167,6 @@
     <Compile Include="..\Renci.SshNet\ConnectionInfo.cs">
       <Link>ConnectionInfo.cs</Link>
     </Compile>
-    <Compile Include="..\Renci.SshNet\ExceptionEventArgs.cs">
-      <Link>ExceptionEventArgs.cs</Link>
-    </Compile>
     <Compile Include="..\Renci.SshNet\ForwardedPort.cs">
       <Link>ForwardedPort.cs</Link>
     </Compile>
@@ -659,6 +665,7 @@
     <Compile Include="..\Renci.SshNet\SshCommand.cs">
       <Link>SshCommand.cs</Link>
     </Compile>
+    <Compile Include="Common\ASCIIEncoding.Silverlight.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Silverlight\$(SilverlightVersion)\Microsoft.Silverlight.CSharp.targets" />

+ 11 - 0
Renci.SshClient/Renci.SshNet/Channels/ChannelDirectTcpip.NET40.cs

@@ -1,5 +1,6 @@
 using System.Threading.Tasks;
 using System;
+using System.Net.Sockets;
 
 namespace Renci.SshNet.Channels
 {
@@ -12,5 +13,15 @@ namespace Renci.SshNet.Channels
         {
             Task.Factory.StartNew(action, TaskCreationOptions.LongRunning);
         }
+
+        partial void InternalSocketReceive(byte[] buffer, ref int read)
+        {
+            read = this._socket.Receive(buffer);
+        }
+
+        partial void InternalSocketSend(byte[] data)
+        {
+            this._socket.Send(data, 0, data.Length, SocketFlags.None);
+        }
     }
 }

+ 7 - 2
Renci.SshClient/Renci.SshNet/Channels/ChannelDirectTcpip.cs

@@ -83,7 +83,8 @@ namespace Renci.SshNet.Channels
                         try
                         {
 
-                            var read = this._socket.Receive(buffer);
+                            var read = 0;
+                            this.InternalSocketReceive(buffer, ref read);
                             if (read > 0)
                             {
                                 this.SendMessage(new ChannelDataMessage(this.RemoteChannelNumber, buffer.Take(read).ToArray()));
@@ -144,7 +145,7 @@ namespace Renci.SshNet.Channels
         {
             base.OnData(data);
 
-            this._socket.Send(data, 0, data.Length, SocketFlags.None);
+            this.InternalSocketSend(data);
         }
 
         /// <summary>
@@ -172,6 +173,10 @@ namespace Renci.SshNet.Channels
 
         partial void ExecuteThread(Action action);
 
+        partial void InternalSocketReceive(byte[] buffer, ref int read);
+
+        partial void InternalSocketSend(byte[] data);
+
         protected override void Dispose(bool disposing)
         {
             if (this._socket != null)

+ 35 - 0
Renci.SshClient/Renci.SshNet/Channels/ChannelForwardedTcpip.NET40.cs

@@ -0,0 +1,35 @@
+using System;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+using Renci.SshNet.Common;
+using Renci.SshNet.Messages.Connection;
+
+namespace Renci.SshNet.Channels
+{
+    /// <summary>
+    /// Implements "forwarded-tcpip" SSH channel.
+    /// </summary>
+    internal partial class ChannelForwardedTcpip : Channel
+    {
+        partial void OpenSocket(string connectedHost, uint connectedPort)
+        {
+            var ep = new IPEndPoint(Dns.GetHostEntry(connectedHost).AddressList[0], (int)connectedPort);
+            this._socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
+            this._socket.Connect(ep);
+            this._socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, 1);
+        }
+
+        partial void InternalSocketReceive(byte[] buffer, ref int read)
+        {
+            read = this._socket.Receive(buffer);
+        }
+
+
+        partial void InternalSocketSend(byte[] data)
+        {
+            this._socket.Send(data);
+        }
+    }
+}

+ 12 - 7
Renci.SshClient/Renci.SshNet/Channels/ChannelForwardedTcpip.cs

@@ -11,7 +11,7 @@ namespace Renci.SshNet.Channels
     /// <summary>
     /// Implements "forwarded-tcpip" SSH channel.
     /// </summary>
-    internal class ChannelForwardedTcpip : Channel
+    internal partial class ChannelForwardedTcpip : Channel
     {
         private Socket _socket;
 
@@ -57,10 +57,7 @@ namespace Renci.SshNet.Channels
                 //  Get buffer in memory for data exchange
                 buffer = new byte[this.PacketSize - 9];
 
-                var ep = new IPEndPoint(Dns.GetHostEntry(connectedHost).AddressList[0], (int)connectedPort);
-                this._socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
-                this._socket.Connect(ep);
-                this._socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, 1);
+                this.OpenSocket(connectedHost, connectedPort);
 
                 //  Send channel open confirmation message
                 this.SendMessage(new ChannelOpenConfirmationMessage(this.RemoteChannelNumber, this.LocalWindowSize, this.PacketSize, this.LocalChannelNumber));
@@ -78,7 +75,9 @@ namespace Renci.SshNet.Channels
             {
                 try
                 {
-                    var read = this._socket.Receive(buffer);
+                    int read = 0;
+                    this.InternalSocketReceive(buffer, ref read);
+
                     if (read > 0)
                     {
                         this.SendMessage(new ChannelDataMessage(this.RemoteChannelNumber, buffer.Take(read).ToArray()));
@@ -112,6 +111,8 @@ namespace Renci.SshNet.Channels
             this.Close();
         }
 
+        partial void OpenSocket(string connectedHost, uint connectedPort);
+
         /// <summary>
         /// Called when channel data is received.
         /// </summary>
@@ -121,9 +122,13 @@ namespace Renci.SshNet.Channels
             base.OnData(data);
 
             //  Read data from the channel and send it to the port
-            this._socket.Send(data);
+            this.InternalSocketSend(data);
         }
 
+        partial void InternalSocketSend(byte[] data);
+        
+        partial void InternalSocketReceive(byte[] buffer, ref int read);
+
         /// <summary>
         /// Releases unmanaged and - optionally - managed resources
         /// </summary>

+ 73 - 0
Renci.SshClient/Renci.SshNet/Common/ASCIIEncoding.NET40.cs

@@ -0,0 +1,73 @@
+/*
+ * ASCIIEncoding.cs - Implementation of the "System.Text.ASCIIEncoding" class.
+ *
+ * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+using System;
+using System.Text;
+
+namespace Renci.SshNet.Common
+{
+    [Serializable]
+    public partial class ASCIIEncoding : Encoding
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ASCIIEncoding"/> class.
+        /// </summary>
+        public ASCIIEncoding()
+            : base(ASCII_CODE_PAGE)
+        {
+        }
+
+        /// <summary>
+        /// Decodes all the bytes in the specified byte array into a string.
+        /// </summary>
+        /// <param name="bytes">The byte array containing the sequence of bytes to decode.</param>
+        /// <returns>
+        /// A <see cref="T:System.String"/> containing the results of decoding the specified sequence of bytes.
+        /// </returns>
+        /// <exception cref="T:System.ArgumentException">The byte array contains invalid Unicode code points.</exception>
+        ///   
+        /// <exception cref="T:System.ArgumentNullException">
+        ///   <paramref name="bytes"/> is null. </exception>
+        ///   
+        /// <exception cref="T:System.Text.DecoderFallbackException">A fallback occurred (see Understanding Encodings for complete explanation)-and-<see cref="P:System.Text.Encoding.DecoderFallback"/> is set to <see cref="T:System.Text.DecoderExceptionFallback"/>.</exception>
+        public override String GetString(byte[] bytes)
+        {
+            if (bytes == null)
+            {
+                throw new ArgumentNullException("bytes");
+            }
+            if (bytes.Length == 0)
+            {
+                return String.Empty;
+            }
+            int count = bytes.Length;
+            int posn = 0;
+
+            char[] chars = new char[count];
+
+            while (count-- > 0)
+            {
+                chars[posn] = (char)(bytes[posn]);
+                ++posn;
+            }
+            return new string(chars);
+        }    
+    }; 
+}

+ 402 - 0
Renci.SshClient/Renci.SshNet/Common/ASCIIEncoding.cs

@@ -0,0 +1,402 @@
+/*
+ * ASCIIEncoding.cs - Implementation of the "System.Text.ASCIIEncoding" class.
+ *
+ * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+using System;
+using System.Text;
+
+namespace Renci.SshNet.Common
+{
+    public partial class ASCIIEncoding : Encoding
+    {
+        // Magic number used by Windows for "ASCII".
+        internal const int ASCII_CODE_PAGE = 20127;
+
+        private static ASCIIEncoding _current = new ASCIIEncoding();
+        /// <summary>
+        /// Gets the current encoding.
+        /// </summary>
+        public static ASCIIEncoding Current
+        {
+            get
+            {
+                return _current;
+            }
+        }
+
+        /// <summary>
+        /// Calculates the number of bytes produced by encoding a set of characters from the specified character array.
+        /// </summary>
+        /// <param name="chars">The character array containing the set of characters to encode.</param>
+        /// <param name="index">The index of the first character to encode.</param>
+        /// <param name="count">The number of characters to encode.</param>
+        /// <returns>
+        /// The number of bytes produced by encoding the specified characters.
+        /// </returns>
+        /// <exception cref="T:System.ArgumentNullException">
+        ///   <paramref name="chars"/> is null. </exception>
+        ///   
+        /// <exception cref="T:System.ArgumentOutOfRangeException">
+        ///   <paramref name="index"/> or <paramref name="count"/> is less than zero.-or- <paramref name="index"/> and <paramref name="count"/> do not denote a valid range in <paramref name="chars"/>. </exception>
+        ///   
+        /// <exception cref="T:System.Text.EncoderFallbackException">A fallback occurred (see Understanding Encodings for complete explanation)-and-<see cref="P:System.Text.Encoding.EncoderFallback"/> is set to <see cref="T:System.Text.EncoderExceptionFallback"/>.</exception>
+        public override int GetByteCount(char[] chars, int index, int count)
+        {
+            if (chars == null)
+            {
+                throw new ArgumentNullException("chars");
+            }
+            if (index < 0 || index > chars.Length)
+            {
+                throw new ArgumentOutOfRangeException("index");
+            }
+            if (count < 0 || count > (chars.Length - index))
+            {
+                throw new ArgumentOutOfRangeException("count");
+            }
+            return count;
+        }
+
+        /// <summary>
+        /// Gets the byte count.
+        /// </summary>
+        /// <param name="chars">The chars.</param>
+        /// <returns></returns>
+        public override int GetByteCount(string chars)
+        {
+            if (chars == null)
+            {
+                throw new ArgumentNullException("chars");
+            }
+            return chars.Length;
+        }
+
+        /// <summary>
+        /// Encodes a set of characters from the specified character array into the specified byte array.
+        /// </summary>
+        /// <param name="chars">The character array containing the set of characters to encode.</param>
+        /// <param name="charIndex">The index of the first character to encode.</param>
+        /// <param name="charCount">The number of characters to encode.</param>
+        /// <param name="bytes">The byte array to contain the resulting sequence of bytes.</param>
+        /// <param name="byteIndex">The index at which to start writing the resulting sequence of bytes.</param>
+        /// <returns>
+        /// The actual number of bytes written into <paramref name="bytes"/>.
+        /// </returns>
+        /// <exception cref="T:System.ArgumentNullException">
+        ///   <paramref name="chars"/> is null.-or- <paramref name="bytes"/> is null. </exception>
+        ///   
+        /// <exception cref="T:System.ArgumentOutOfRangeException">
+        ///   <paramref name="charIndex"/> or <paramref name="charCount"/> or <paramref name="byteIndex"/> is less than zero.-or- <paramref name="charIndex"/> and <paramref name="charCount"/> do not denote a valid range in <paramref name="chars"/>.-or- <paramref name="byteIndex"/> is not a valid index in <paramref name="bytes"/>. </exception>
+        ///   
+        /// <exception cref="T:System.ArgumentException">
+        ///   <paramref name="bytes"/> does not have enough capacity from <paramref name="byteIndex"/> to the end of the array to accommodate the resulting bytes. </exception>
+        ///   
+        /// <exception cref="T:System.Text.EncoderFallbackException">A fallback occurred (see Understanding Encodings for complete explanation)-and-<see cref="P:System.Text.Encoding.EncoderFallback"/> is set to <see cref="T:System.Text.EncoderExceptionFallback"/>.</exception>
+        public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
+        {
+            if (chars == null)
+            {
+                throw new ArgumentNullException("chars");
+            }
+            if (bytes == null)
+            {
+                throw new ArgumentNullException("bytes");
+            }
+            if (charIndex < 0 || charIndex > chars.Length)
+            {
+                throw new ArgumentOutOfRangeException("charIndex");
+            }
+            if (charCount < 0 || charCount > (chars.Length - charIndex))
+            {
+                throw new ArgumentOutOfRangeException("charCount");
+            }
+            if (byteIndex < 0 || byteIndex > bytes.Length)
+            {
+                throw new ArgumentOutOfRangeException("byteIndex");
+            }
+            if ((bytes.Length - byteIndex) < charCount)
+            {
+                throw new ArgumentException();
+            }
+            int count = charCount;
+            char ch;
+            while (count-- > 0)
+            {
+                ch = chars[charIndex++];
+                if (ch < (char)0x80)
+                {
+                    bytes[byteIndex++] = (byte)ch;
+                }
+                else
+                {
+                    bytes[byteIndex++] = (byte)'?';
+                }
+            }
+            return charCount;
+        }
+
+        /// <summary>
+        /// Encodes a set of characters from the specified <see cref="T:System.String"/> into the specified byte array.
+        /// </summary>
+        /// <param name="s">The <see cref="T:System.String"/> containing the set of characters to encode.</param>
+        /// <param name="charIndex">The index of the first character to encode.</param>
+        /// <param name="charCount">The number of characters to encode.</param>
+        /// <param name="bytes">The byte array to contain the resulting sequence of bytes.</param>
+        /// <param name="byteIndex">The index at which to start writing the resulting sequence of bytes.</param>
+        /// <returns>
+        /// The actual number of bytes written into <paramref name="bytes"/>.
+        /// </returns>
+        /// <exception cref="T:System.ArgumentNullException">
+        ///   <paramref name="s"/> is null.-or- <paramref name="bytes"/> is null. </exception>
+        ///   
+        /// <exception cref="T:System.ArgumentOutOfRangeException">
+        ///   <paramref name="charIndex"/> or <paramref name="charCount"/> or <paramref name="byteIndex"/> is less than zero.-or- <paramref name="charIndex"/> and <paramref name="charCount"/> do not denote a valid range in <paramref name="chars"/>.-or- <paramref name="byteIndex"/> is not a valid index in <paramref name="bytes"/>. </exception>
+        ///   
+        /// <exception cref="T:System.ArgumentException">
+        ///   <paramref name="bytes"/> does not have enough capacity from <paramref name="byteIndex"/> to the end of the array to accommodate the resulting bytes. </exception>
+        ///   
+        /// <exception cref="T:System.Text.EncoderFallbackException">A fallback occurred (see Understanding Encodings for complete explanation)-and-<see cref="P:System.Text.Encoding.EncoderFallback"/> is set to <see cref="T:System.Text.EncoderExceptionFallback"/>.</exception>
+        public override int GetBytes(String s, int charIndex, int charCount, byte[] bytes, int byteIndex)
+        {
+            if (s == null)
+            {
+                throw new ArgumentNullException("s");
+            }
+            if (bytes == null)
+            {
+                throw new ArgumentNullException("bytes");
+            }
+            if (charIndex < 0 || charIndex > s.Length)
+            {
+                throw new ArgumentOutOfRangeException("charIndex");
+            }
+            if (charCount < 0 || charCount > (s.Length - charIndex))
+            {
+                throw new ArgumentOutOfRangeException("charCount");
+            }
+            if (byteIndex < 0 || byteIndex > bytes.Length)
+            {
+                throw new ArgumentOutOfRangeException("byteIndex");
+            }
+            if ((bytes.Length - byteIndex) < charCount)
+            {
+                throw new ArgumentException();
+            }
+            int count = charCount;
+            char ch;
+            while (count-- > 0)
+            {
+                ch = s[charIndex++];
+                if (ch < (char)0x80)
+                {
+                    bytes[byteIndex++] = (byte)ch;
+                }
+                else
+                {
+                    bytes[byteIndex++] = (byte)'?';
+                }
+            }
+            return charCount;
+        }
+
+        /// <summary>
+        /// Calculates the number of characters produced by decoding a sequence of bytes from the specified byte array.
+        /// </summary>
+        /// <param name="bytes">The byte array containing the sequence of bytes to decode.</param>
+        /// <param name="index">The index of the first byte to decode.</param>
+        /// <param name="count">The number of bytes to decode.</param>
+        /// <returns>
+        /// The number of characters produced by decoding the specified sequence of bytes.
+        /// </returns>
+        /// <exception cref="T:System.ArgumentNullException">
+        ///   <paramref name="bytes"/> is null. </exception>
+        ///   
+        /// <exception cref="T:System.ArgumentOutOfRangeException">
+        ///   <paramref name="index"/> or <paramref name="count"/> is less than zero.-or- <paramref name="index"/> and <paramref name="count"/> do not denote a valid range in <paramref name="bytes"/>. </exception>
+        ///   
+        /// <exception cref="T:System.Text.DecoderFallbackException">A fallback occurred (see Understanding Encodings for complete explanation)-and-<see cref="P:System.Text.Encoding.DecoderFallback"/> is set to <see cref="T:System.Text.DecoderExceptionFallback"/>.</exception>
+        public override int GetCharCount(byte[] bytes, int index, int count)
+        {
+            if (bytes == null)
+            {
+                throw new ArgumentNullException("bytes");
+            }
+            if (index < 0 || index > bytes.Length)
+            {
+                throw new ArgumentOutOfRangeException("index");
+            }
+            if (count < 0 || count > (bytes.Length - index))
+            {
+                throw new ArgumentOutOfRangeException("count");
+            }
+            return count;
+        }
+
+        /// <summary>
+        /// Decodes a sequence of bytes from the specified byte array into the specified character array.
+        /// </summary>
+        /// <param name="bytes">The byte array containing the sequence of bytes to decode.</param>
+        /// <param name="byteIndex">The index of the first byte to decode.</param>
+        /// <param name="byteCount">The number of bytes to decode.</param>
+        /// <param name="chars">The character array to contain the resulting set of characters.</param>
+        /// <param name="charIndex">The index at which to start writing the resulting set of characters.</param>
+        /// <returns>
+        /// The actual number of characters written into <paramref name="chars"/>.
+        /// </returns>
+        /// <exception cref="T:System.ArgumentNullException">
+        ///   <paramref name="bytes"/> is null.-or- <paramref name="chars"/> is null. </exception>
+        ///   
+        /// <exception cref="T:System.ArgumentOutOfRangeException">
+        ///   <paramref name="byteIndex"/> or <paramref name="byteCount"/> or <paramref name="charIndex"/> is less than zero.-or- <paramref name="byteindex"/> and <paramref name="byteCount"/> do not denote a valid range in <paramref name="bytes"/>.-or- <paramref name="charIndex"/> is not a valid index in <paramref name="chars"/>. </exception>
+        ///   
+        /// <exception cref="T:System.ArgumentException">
+        ///   <paramref name="chars"/> does not have enough capacity from <paramref name="charIndex"/> to the end of the array to accommodate the resulting characters. </exception>
+        ///   
+        /// <exception cref="T:System.Text.DecoderFallbackException">A fallback occurred (see Understanding Encodings for complete explanation)-and-<see cref="P:System.Text.Encoding.DecoderFallback"/> is set to <see cref="T:System.Text.DecoderExceptionFallback"/>.</exception>
+        public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
+        {
+            if (bytes == null)
+            {
+                throw new ArgumentNullException("bytes");
+            }
+            if (chars == null)
+            {
+                throw new ArgumentNullException("chars");
+            }
+            if (byteIndex < 0 || byteIndex > bytes.Length)
+            {
+                throw new ArgumentOutOfRangeException("byteIndex");
+            }
+            if (byteCount < 0 || byteCount > (bytes.Length - byteIndex))
+            {
+                throw new ArgumentOutOfRangeException("byteCount");
+            }
+            if (charIndex < 0 || charIndex > chars.Length)
+            {
+                throw new ArgumentOutOfRangeException("charIndex");
+            }
+            if ((chars.Length - charIndex) < byteCount)
+            {
+                throw new ArgumentException();
+            }
+            int count = byteCount;
+            byte ch;
+            while (count-- > 0)
+            {
+                ch = bytes[byteIndex++];
+                if (ch < 0x80)
+                {
+                    chars[charIndex++] = (char)ch;
+                }
+                else
+                {
+                    chars[charIndex++] = '?';
+                }
+            }
+            return byteCount;
+        }
+
+        /// <summary>
+        /// Calculates the maximum number of bytes produced by encoding the specified number of characters.
+        /// </summary>
+        /// <param name="charCount">The number of characters to encode.</param>
+        /// <returns>
+        /// The maximum number of bytes produced by encoding the specified number of characters.
+        /// </returns>
+        /// <exception cref="T:System.ArgumentOutOfRangeException">
+        ///   <paramref name="charCount"/> is less than zero. </exception>
+        ///   
+        /// <exception cref="T:System.Text.EncoderFallbackException">A fallback occurred (see Understanding Encodings for complete explanation)-and-<see cref="P:System.Text.Encoding.EncoderFallback"/> is set to <see cref="T:System.Text.EncoderExceptionFallback"/>.</exception>
+        public override int GetMaxByteCount(int charCount)
+        {
+            if (charCount < 0)
+            {
+                throw new ArgumentOutOfRangeException("charCount");
+            }
+
+            return charCount;
+        }
+
+        /// <summary>
+        /// Calculates the maximum number of characters produced by decoding the specified number of bytes.
+        /// </summary>
+        /// <param name="byteCount">The number of bytes to decode.</param>
+        /// <returns>
+        /// The maximum number of characters produced by decoding the specified number of bytes.
+        /// </returns>
+        /// <exception cref="T:System.ArgumentOutOfRangeException">
+        ///   <paramref name="byteCount"/> is less than zero. </exception>
+        ///   
+        /// <exception cref="T:System.Text.DecoderFallbackException">A fallback occurred (see Understanding Encodings for complete explanation)-and-<see cref="P:System.Text.Encoding.DecoderFallback"/> is set to <see cref="T:System.Text.DecoderExceptionFallback"/>.</exception>
+        public override int GetMaxCharCount(int byteCount)
+        {
+            if (byteCount < 0)
+            {
+                throw new ArgumentOutOfRangeException("byteCount");
+            }
+            return byteCount;
+        }
+
+        /// <summary>
+        /// Decodes a sequence of bytes from the specified byte array into a string.
+        /// </summary>
+        /// <param name="bytes">The byte array containing the sequence of bytes to decode.</param>
+        /// <param name="index">The index of the first byte to decode.</param>
+        /// <param name="count">The number of bytes to decode.</param>
+        /// <returns>
+        /// A <see cref="T:System.String"/> containing the results of decoding the specified sequence of bytes.
+        /// </returns>
+        /// <exception cref="T:System.ArgumentException">The byte array contains invalid Unicode code points.</exception>
+        ///   
+        /// <exception cref="T:System.ArgumentNullException">
+        ///   <paramref name="bytes"/> is null. </exception>
+        ///   
+        /// <exception cref="T:System.ArgumentOutOfRangeException">
+        ///   <paramref name="index"/> or <paramref name="count"/> is less than zero.-or- <paramref name="index"/> and <paramref name="count"/> do not denote a valid range in <paramref name="bytes"/>. </exception>
+        ///   
+        /// <exception cref="T:System.Text.DecoderFallbackException">A fallback occurred (see Understanding Encodings for complete explanation)-and-<see cref="P:System.Text.Encoding.DecoderFallback"/> is set to <see cref="T:System.Text.DecoderExceptionFallback"/>.</exception>
+        public override String GetString(byte[] bytes, int index, int count)
+        {
+            if (bytes == null)
+            {
+                throw new ArgumentNullException("bytes");
+            }
+            if (index < 0 || index > bytes.Length)
+            {
+                throw new ArgumentOutOfRangeException("index");
+            }
+            if (count < 0 || count > (bytes.Length - index))
+            {
+                throw new ArgumentOutOfRangeException("count");
+            }
+            if (count == 0)
+            {
+                return String.Empty;
+            }
+
+            char[] chars = new char[count];
+            int posn = 0;
+            while (count-- > 0)
+            {
+                chars[posn++] = (char)(bytes[index++]);
+            }
+            return new string(chars);
+        }
+    }; 
+}

+ 2 - 2
Renci.SshClient/Renci.SshNet/Common/SshData.cs

@@ -203,7 +203,7 @@ namespace Renci.SshNet.Common
                 throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "String that longer that {0} are not supported.", int.MaxValue));
             }
 
-            return Encoding.ASCII.GetString(this.ReadBytes(length));
+            return Renci.SshNet.Common.ASCIIEncoding.Current.GetString(this.ReadBytes(length));
         }
 
         /// <summary>
@@ -348,7 +348,7 @@ namespace Renci.SshNet.Common
         /// <param name="data">string data to write.</param>
         protected void Write(string data)
         {
-            this.Write(data, Encoding.ASCII);
+            this.Write(data, Renci.SshNet.Common.ASCIIEncoding.Current);
         }
 
         /// <summary>

+ 1 - 1
Renci.SshClient/Renci.SshNet/Messages/Authentication/RequestMessage.cs

@@ -66,7 +66,7 @@ namespace Renci.SshNet.Messages.Authentication
                 default:
                     throw new NotSupportedException("Not supported service name");
             }
-            this.Write(this.MethodName, Encoding.ASCII);
+            this.Write(this.MethodName, Renci.SshNet.Common.ASCIIEncoding.Current);
         }
     }
 }

+ 1 - 1
Renci.SshClient/Renci.SshNet/Messages/Authentication/RequestMessageHost.cs

@@ -85,7 +85,7 @@ namespace Renci.SshNet.Messages.Authentication
 
             this.Write(this.PublicKeyAlgorithm);
             this.WriteBinaryString(this.PublicHostKey);
-            this.Write(this.ClientHostName, Encoding.ASCII);
+            this.Write(this.ClientHostName, Renci.SshNet.Common.ASCIIEncoding.Current);
             this.Write(this.ClientUsername, Encoding.UTF8);
 
             if (this.Signature != null)

+ 98 - 33
Renci.SshClient/Renci.SshNet/Renci.SshNet.csproj

@@ -63,6 +63,11 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Channels\ChannelDirectTcpip.NET40.cs" />
+    <Compile Include="Channels\ChannelForwardedTcpip.NET40.cs" />
+    <Compile Include="Common\ASCIIEncoding.cs" />
+    <Compile Include="Common\ASCIIEncoding.NET40.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="Common\AsyncResult.cs" />
     <Compile Include="Common\AuthenticationBannerEventArgs.cs" />
     <Compile Include="Common\AuthenticationEventArgs.cs" />
@@ -98,12 +103,105 @@
     <Compile Include="ForwardedPortLocal.cs">
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Security\Algorithm.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\Cipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\CipherAESCBC.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\CipherAESCTR.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\CipherBlowfish.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\CipherCast.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\CipherDES.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\CipherSerpent.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\CipherTripleDES.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="Security\Cryptography\Aes.cs">
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Security\Cryptography\Blowfish.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\Cryptography\Cast.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\Cryptography\CipherTransform.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\Cryptography\Des.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="Security\Cryptography\Serpent.cs">
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Security\Cryptography\TransformMode.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\Cryptography\TripleDes.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\CryptoKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\CryptoPrivateKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\CryptoPrivateKeyDss.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\CryptoPrivateKeyRsa.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\CryptoPublicKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\CryptoPublicKeyDss.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\CryptoPublicKeyRsa.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\HMac.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\HMacMD5.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\HMacSha1.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\KeyExchange.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\KeyExchangeDiffieHellman.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\KeyExchangeDiffieHellmanGroup14Sha1.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\KeyExchangeDiffieHellmanGroup1Sha1.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\KeyExchangeDiffieHellmanGroupExchangeSha1.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\KeyExchangeDiffieHellmanGroupExchangeSha256.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="Shell.NET40.cs" />
     <Compile Include="SftpClient.NET40.cs" />
     <Compile Include="PasswordConnectionInfo.NET40.cs" />
@@ -134,29 +232,19 @@
     <Compile Include="Messages\Connection\ChannelRequest\XonXoffRequestInfo.cs" />
     <Compile Include="Messages\MessageAttribute.cs" />
     <Compile Include="NoneConnectionInfo.cs" />
-    <Compile Include="Security\CipherBlowfish.cs" />
-    <Compile Include="Security\CipherAESCTR.cs" />
-    <Compile Include="Security\CipherCast.cs" />
-    <Compile Include="Security\CipherSerpent.cs" />
-    <Compile Include="Security\Cryptography\Cast.cs" />
     <Compile Include="Security\Cryptography\Ciphers\AesCipher.cs" />
-    <Compile Include="Security\Cryptography\Blowfish.cs" />
     <Compile Include="Security\Cryptography\Ciphers\BlowfishCipher.cs" />
     <Compile Include="Security\Cryptography\Ciphers\CastCipher.cs" />
     <Compile Include="Security\Cryptography\Ciphers\SerpentCipher.cs" />
     <Compile Include="Security\Cryptography\Ciphers\TwofishCipher.cs" />
     <Compile Include="Security\Cryptography\Modes\CfbMode.cs" />
     <Compile Include="Security\Cryptography\Modes\CipherModeEx.cs" />
-    <Compile Include="Security\Cryptography\CipherTransform.cs" />
     <Compile Include="Security\Cryptography\Modes\ModeBase.cs" />
     <Compile Include="Security\Cryptography\Modes\CbcMode.cs" />
     <Compile Include="Security\Cryptography\Ciphers\CipherBase.cs" />
-    <Compile Include="Security\Cryptography\TripleDes.cs" />
     <Compile Include="Security\Cryptography\Ciphers\TripleDesCipher.cs" />
     <Compile Include="Security\Cryptography\Modes\CtrMode.cs" />
-    <Compile Include="Security\Cryptography\Des.cs" />
     <Compile Include="Security\Cryptography\Modes\OfbMode.cs" />
-    <Compile Include="Security\Cryptography\TransformMode.cs" />
     <Compile Include="Security\Cryptography\Ciphers\DesCipher.cs" />
     <Compile Include="Sftp\Flags.cs" />
     <Compile Include="Sftp\SftpDataMessage.cs">
@@ -208,16 +296,6 @@
     <Compile Include="Messages\Transport\KeyExchangeDhGroupExchangeRequest.cs" />
     <Compile Include="PasswordConnectionInfo.cs" />
     <Compile Include="PrivateKeyConnectionInfo.cs" />
-    <Compile Include="Security\CipherDES.cs" />
-    <Compile Include="Security\KeyExchangeDiffieHellmanGroupExchangeSha256.cs" />
-    <Compile Include="Security\HMac.cs" />
-    <Compile Include="Security\HMacMD5.cs" />
-    <Compile Include="Security\HMacSha1.cs" />
-    <Compile Include="Security\KeyExchangeDiffieHellman.cs">
-      <SubType>Code</SubType>
-    </Compile>
-    <Compile Include="Security\KeyExchangeDiffieHellmanGroup14Sha1.cs" />
-    <Compile Include="Security\KeyExchangeDiffieHellmanGroupExchangeSha1.cs" />
     <Compile Include="SftpClient.cs" />
     <Compile Include="Sftp\SftpFile.cs" />
     <Compile Include="Sftp\SftpSession.cs" />
@@ -232,22 +310,9 @@
     <Compile Include="ForwardedPort.cs" />
     <Compile Include="ForwardedPortRemote.cs" />
     <Compile Include="Messages\Connection\GlobalRequestName.cs" />
-    <Compile Include="Security\Algorithm.cs" />
-    <Compile Include="Security\Cipher.cs" />
-    <Compile Include="Security\CipherAESCBC.cs" />
-    <Compile Include="Security\CipherTripleDES.cs" />
     <Compile Include="Compression\Compressor.cs" />
     <Compile Include="Compression\Zlib.cs" />
     <Compile Include="Compression\ZlibOpenSsh.cs" />
-    <Compile Include="Security\CryptoKey.cs" />
-    <Compile Include="Security\CryptoPrivateKey.cs" />
-    <Compile Include="Security\CryptoPrivateKeyDss.cs" />
-    <Compile Include="Security\CryptoPrivateKeyRsa.cs" />
-    <Compile Include="Security\CryptoPublicKey.cs" />
-    <Compile Include="Security\CryptoPublicKeyDss.cs" />
-    <Compile Include="Security\CryptoPublicKeyRsa.cs" />
-    <Compile Include="Security\KeyExchange.cs" />
-    <Compile Include="Security\KeyExchangeDiffieHellmanGroup1Sha1.cs" />
     <Compile Include="PrivateKeyFile.cs" />
     <Compile Include="Messages\Connection\ChannelMessage.cs" />
     <Compile Include="Channels\Channel.cs" />

+ 1 - 1
Renci.SshClient/Renci.SshNet/Security/KeyExchangeDiffieHellman.cs

@@ -76,7 +76,7 @@ namespace Renci.SshNet.Security
 
             var length = (uint)(this._hostKey[0] << 24 | this._hostKey[1] << 16 | this._hostKey[2] << 8 | this._hostKey[3]);
 
-            var algorithmName = Encoding.ASCII.GetString(bytes.Skip(4).Take((int)length).ToArray());
+            var algorithmName = Renci.SshNet.Common.ASCIIEncoding.Current.GetString(bytes.Skip(4).Take((int)length).ToArray());
 
             var data = bytes.Skip(4 + algorithmName.Length);
 

+ 98 - 0
Renci.SshClient/Renci.SshNet/Session.NET40.cs

@@ -1,6 +1,12 @@
 using System.Threading.Tasks;
 using System.Linq;
 using System;
+using System.Net.Sockets;
+using System.Net;
+using Renci.SshNet.Messages;
+using Renci.SshNet.Common;
+using System.Threading;
+using Renci.SshNet.Messages.Transport;
 
 namespace Renci.SshNet
 {
@@ -34,5 +40,97 @@ namespace Renci.SshNet
             }
         }
 
+        partial void OpenSocket()
+        {
+            var ep = new IPEndPoint(Dns.GetHostAddresses(this.ConnectionInfo.Host)[0], this.ConnectionInfo.Port);
+            this._socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
+
+            var socketBufferSize = 2 * MAXIMUM_PACKET_SIZE;
+
+            this._socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
+            this._socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer, socketBufferSize);
+            this._socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, socketBufferSize);
+
+
+            //  Connect socket with 5 seconds timeout
+            var connectResult = this._socket.BeginConnect(ep, null, null);
+
+            connectResult.AsyncWaitHandle.WaitOne(this.ConnectionInfo.Timeout);
+
+            //  Build list of available messages while connecting
+            this._messagesMetadata = (from type in this.GetType().Assembly.GetTypes()
+                                      from messageAttribute in type.GetCustomAttributes(false).OfType<MessageAttribute>()
+                                      select new MessageMetadata
+                                      {
+                                          Name = messageAttribute.Name,
+                                          Number = messageAttribute.Number,
+                                          Enabled = false,
+                                          Activated = false,
+                                          Type = type,
+                                      }).ToList();
+
+            this._socket.EndConnect(connectResult);
+        }
+
+        partial void InternalRead(int length, ref byte[] buffer)
+        {
+            var offset = 0;
+            int receivedTotal = 0;  // how many bytes is already received
+
+            do
+            {
+                try
+                {
+                    var receivedBytes = this._socket.Receive(buffer, offset + receivedTotal, length - receivedTotal, SocketFlags.None);
+                    if (receivedBytes > 0)
+                    {
+                        receivedTotal += receivedBytes;
+                        continue;
+                    }
+                    else
+                    {
+                        throw new SshConnectionException("An established connection was aborted by the software in your host machine.", DisconnectReason.ConnectionLost);
+                    }
+                }
+                catch (SocketException exp)
+                {
+                    if (exp.SocketErrorCode == SocketError.WouldBlock ||
+                        exp.SocketErrorCode == SocketError.IOPending ||
+                        exp.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
+                    {
+                        // socket buffer is probably empty, wait and try again
+                        Thread.Sleep(30);
+                    }
+                    else
+                        throw;  // any serious error occurred
+                }
+            } while (receivedTotal < length);
+        }
+
+        partial void Write(byte[] data)
+        {
+            int sent = 0;  // how many bytes is already sent
+            int length = data.Length;
+
+            do
+            {
+                try
+                {
+                    sent += this._socket.Send(data, sent, length - sent, SocketFlags.None);
+                }
+                catch (SocketException ex)
+                {
+                    if (ex.SocketErrorCode == SocketError.WouldBlock ||
+                        ex.SocketErrorCode == SocketError.IOPending ||
+                        ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
+                    {
+                        // socket buffer is probably full, wait and try again
+                        Thread.Sleep(30);
+                    }
+                    else
+                        throw;  // any serious error occurr
+                }
+            } while (sent < length);
+        }
     }
 }

+ 9 - 83
Renci.SshClient/Renci.SshNet/Session.cs

@@ -416,32 +416,7 @@ namespace Renci.SshNet
                     if (this.IsConnected)
                         return;
 
-                    var ep = new IPEndPoint(Dns.GetHostAddresses(this.ConnectionInfo.Host)[0], this.ConnectionInfo.Port);
-                    this._socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
-
-                    var socketBufferSize = 2 * MAXIMUM_PACKET_SIZE;
-                    this._socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
-                    this._socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer, socketBufferSize);
-                    this._socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, socketBufferSize);
-
-                    //  Connect socket with 5 seconds timeout
-                    var connectResult = this._socket.BeginConnect(ep, null, null);
-
-                    connectResult.AsyncWaitHandle.WaitOne(this.ConnectionInfo.Timeout);
-
-                    //  Build list of available messages while connecting
-                    this._messagesMetadata = (from type in this.GetType().Assembly.GetTypes()
-                                              from messageAttribute in type.GetCustomAttributes(false).OfType<MessageAttribute>()
-                                              select new MessageMetadata
-                                              {
-                                                  Name = messageAttribute.Name,
-                                                  Number = messageAttribute.Number,
-                                                  Enabled = false,
-                                                  Activated = false,
-                                                  Type = type,
-                                              }).ToList();
-
-                    this._socket.EndConnect(connectResult);
+                    this.OpenSocket();
 
                     Match versionMatch = null;
                     //  Get server version from the server,
@@ -476,7 +451,7 @@ namespace Renci.SshNet
                         throw new SshConnectionException(string.Format(CultureInfo.CurrentCulture, "Server version '{0}' is not supported.", version), DisconnectReason.ProtocolVersionNotSupported);
                     }
 
-                    this.Write(Encoding.ASCII.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0}\x0D\x0A", this.ClientVersion)));
+                    this.Write(Renci.SshNet.Common.ASCIIEncoding.Current.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0}\x0D\x0A", this.ClientVersion)));
 
                     //  Register Transport response messages
                     this.RegisterMessage("SSH_MSG_DISCONNECT");
@@ -1431,38 +1406,9 @@ namespace Renci.SshNet
         /// <returns></returns>
         private byte[] Read(int length)
         {
-            var buffer = new byte[length];
-            var offset = 0;
-            int receivedTotal = 0;  // how many bytes is already received
+            byte[] buffer = new byte[length];
 
-            do
-            {
-                try
-                {
-                    var receivedBytes = this._socket.Receive(buffer, offset + receivedTotal, length - receivedTotal, SocketFlags.None);
-                    if (receivedBytes > 0)
-                    {
-                        receivedTotal += receivedBytes;
-                        continue;
-                    }
-                    else
-                    {
-                        throw new SshConnectionException("An established connection was aborted by the software in your host machine.", DisconnectReason.ConnectionLost);
-                    }
-                }
-                catch (SocketException exp)
-                {
-                    if (exp.SocketErrorCode == SocketError.WouldBlock ||
-                        exp.SocketErrorCode == SocketError.IOPending ||
-                        exp.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
-                    {
-                        // socket buffer is probably empty, wait and try again
-                        Thread.Sleep(30);
-                    }
-                    else
-                        throw;  // any serious error occurred
-                }
-            } while (receivedTotal < length);
+            this.InternalRead(length, ref buffer);
 
             return buffer;
         }
@@ -1471,31 +1417,7 @@ namespace Renci.SshNet
         /// Writes the specified data to the server.
         /// </summary>
         /// <param name="data">The data.</param>
-        private void Write(byte[] data)
-        {
-            int sent = 0;  // how many bytes is already sent
-            int length = data.Length;
-
-            do
-            {
-                try
-                {
-                    sent += this._socket.Send(data, sent, length - sent, SocketFlags.None);
-                }
-                catch (SocketException ex)
-                {
-                    if (ex.SocketErrorCode == SocketError.WouldBlock ||
-                        ex.SocketErrorCode == SocketError.IOPending ||
-                        ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
-                    {
-                        // socket buffer is probably full, wait and try again
-                        Thread.Sleep(30);
-                    }
-                    else
-                        throw;  // any serious error occurr
-                }
-            } while (sent < length);
-        }
+        partial void Write(byte[] data);
 
         #endregion
 
@@ -1547,6 +1469,10 @@ namespace Renci.SshNet
 
         partial void ExecuteThread(Action action);
 
+        partial void OpenSocket();
+
+        partial void InternalRead(int length, ref byte[] buffer);
+
         /// <summary>
         /// Listens for incoming message from the server and handles them. This method run as a task on separate thread.
         /// </summary>

+ 1 - 1
Renci.SshClient/Renci.SshNet/SshClient.cs

@@ -197,7 +197,7 @@ namespace Renci.SshNet
         /// <returns><see cref="SshCommand"/> object.</returns>
         public SshCommand CreateCommand(string commandText)
         {
-            return this.CreateCommand(commandText, Encoding.ASCII);
+            return this.CreateCommand(commandText, Renci.SshNet.Common.ASCIIEncoding.Current);
         }
 
         /// <summary>