Browse Source

Make line endings consistent (PR #19)

drieseng 9 năm trước cách đây
mục cha
commit
57a78fc3a4
100 tập tin đã thay đổi với 13235 bổ sung13235 xóa
  1. 169 169
      src/Renci.SshNet/ClientAuthentication.cs
  2. 68 68
      src/Renci.SshNet/CommandAsyncResult.cs
  3. 209 209
      src/Renci.SshNet/Common/ASCIIEncoding.cs
  4. 197 197
      src/Renci.SshNet/Common/AsyncResult.cs
  5. 31 31
      src/Renci.SshNet/Common/AuthenticationBannerEventArgs.cs
  6. 24 24
      src/Renci.SshNet/Common/AuthenticationEventArgs.cs
  7. 25 25
      src/Renci.SshNet/Common/AuthenticationPasswordChangeEventArgs.cs
  8. 47 47
      src/Renci.SshNet/Common/AuthenticationPrompt.cs
  9. 40 40
      src/Renci.SshNet/Common/AuthenticationPromptEventArgs.cs
  10. 4225 4225
      src/Renci.SshNet/Common/BigInteger.cs
  11. 24 24
      src/Renci.SshNet/Common/ChannelDataEventArgs.cs
  12. 24 24
      src/Renci.SshNet/Common/ChannelEventArgs.cs
  13. 24 24
      src/Renci.SshNet/Common/ChannelExtendedDataEventArgs.cs
  14. 37 37
      src/Renci.SshNet/Common/ChannelOpenConfirmedEventArgs.cs
  15. 38 38
      src/Renci.SshNet/Common/ChannelOpenFailedEventArgs.cs
  16. 25 25
      src/Renci.SshNet/Common/ChannelRequestEventArgs.cs
  17. 333 333
      src/Renci.SshNet/Common/DerData.cs
  18. 24 24
      src/Renci.SshNet/Common/ExceptionEventArgs.cs
  19. 32 32
      src/Renci.SshNet/Common/Extensions.NET40.cs
  20. 359 359
      src/Renci.SshNet/Common/Extensions.cs
  21. 63 63
      src/Renci.SshNet/Common/HostKeyEventArgs.cs
  22. 24 24
      src/Renci.SshNet/Common/NetConfServerException.NET40.cs
  23. 36 36
      src/Renci.SshNet/Common/NetConfServerException.cs
  24. 28 28
      src/Renci.SshNet/Common/ObjectIdentifier.cs
  25. 346 346
      src/Renci.SshNet/Common/PipeStream.cs
  26. 37 37
      src/Renci.SshNet/Common/PortForwardEventArgs.cs
  27. 22 22
      src/Renci.SshNet/Common/ProxyException.NET40.cs
  28. 37 37
      src/Renci.SshNet/Common/ProxyException.cs
  29. 38 38
      src/Renci.SshNet/Common/ScpDownloadEventArgs.cs
  30. 21 21
      src/Renci.SshNet/Common/ScpException.NET40.cs
  31. 38 38
      src/Renci.SshNet/Common/ScpException.cs
  32. 38 38
      src/Renci.SshNet/Common/ScpUploadEventArgs.cs
  33. 81 81
      src/Renci.SshNet/Common/SemaphoreLight.cs
  34. 24 24
      src/Renci.SshNet/Common/SftpPathNotFoundException.NET40.cs
  35. 36 36
      src/Renci.SshNet/Common/SftpPathNotFoundException.cs
  36. 24 24
      src/Renci.SshNet/Common/SftpPermissionDeniedException.NET40.cs
  37. 36 36
      src/Renci.SshNet/Common/SftpPermissionDeniedException.cs
  38. 38 38
      src/Renci.SshNet/Common/ShellDataEventArgs.cs
  39. 24 24
      src/Renci.SshNet/Common/SshAuthenticationException.NET40.cs
  40. 38 38
      src/Renci.SshNet/Common/SshAuthenticationException.cs
  41. 24 24
      src/Renci.SshNet/Common/SshConnectionException.NET40.cs
  42. 56 56
      src/Renci.SshNet/Common/SshConnectionException.cs
  43. 443 443
      src/Renci.SshNet/Common/SshData.cs
  44. 253 253
      src/Renci.SshNet/Common/SshDataStream.cs
  45. 25 25
      src/Renci.SshNet/Common/SshException.NET40.cs
  46. 36 36
      src/Renci.SshNet/Common/SshException.cs
  47. 21 21
      src/Renci.SshNet/Common/SshOperationTimeoutException.NET40.cs
  48. 36 36
      src/Renci.SshNet/Common/SshOperationTimeoutException.cs
  49. 24 24
      src/Renci.SshNet/Common/SshPassPhraseNullOrEmptyException.NET40.cs
  50. 38 38
      src/Renci.SshNet/Common/SshPassPhraseNullOrEmptyException.cs
  51. 288 288
      src/Renci.SshNet/Common/TerminalModes.cs
  52. 18 18
      src/Renci.SshNet/Compression/CompressionMode.cs
  53. 183 183
      src/Renci.SshNet/Compression/Compressor.cs
  54. 25 25
      src/Renci.SshNet/Compression/Zlib.cs
  55. 34 34
      src/Renci.SshNet/Compression/ZlibOpenSsh.cs
  56. 45 45
      src/Renci.SshNet/Compression/ZlibStream.cs
  57. 443 443
      src/Renci.SshNet/ConnectionInfo.cs
  58. 31 31
      src/Renci.SshNet/Documentation/Renci.SshNet.content
  59. 57 57
      src/Renci.SshNet/Documentation/SshNet.shfbproj
  60. 57 57
      src/Renci.SshNet/ExpectAction.cs
  61. 21 21
      src/Renci.SshNet/ExpectAsyncResult.cs
  62. 174 174
      src/Renci.SshNet/ForwardedPort.cs
  63. 645 645
      src/Renci.SshNet/ForwardedPortDynamic.NET.cs
  64. 163 163
      src/Renci.SshNet/ForwardedPortDynamic.cs
  65. 257 257
      src/Renci.SshNet/ForwardedPortLocal.NET.cs
  66. 204 204
      src/Renci.SshNet/ForwardedPortLocal.cs
  67. 339 339
      src/Renci.SshNet/ForwardedPortRemote.cs
  68. 35 35
      src/Renci.SshNet/HashInfo.cs
  69. 35 35
      src/Renci.SshNet/IAuthenticationMethod.cs
  70. 7 7
      src/Renci.SshNet/IClientAuthentication.cs
  71. 83 83
      src/Renci.SshNet/IConnectionInfo.cs
  72. 15 15
      src/Renci.SshNet/IForwardedPort.cs
  73. 19 19
      src/Renci.SshNet/IServiceFactory.NET.cs
  74. 61 61
      src/Renci.SshNet/IServiceFactory.cs
  75. 229 229
      src/Renci.SshNet/ISession.cs
  76. 42 42
      src/Renci.SshNet/ISubsystemSession.cs
  77. 181 181
      src/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.cs
  78. 196 196
      src/Renci.SshNet/KeyboardInteractiveConnectionInfo.cs
  79. 29 29
      src/Renci.SshNet/MessageEventArgs.cs
  80. 65 65
      src/Renci.SshNet/Messages/Authentication/BannerMessage.cs
  81. 53 53
      src/Renci.SshNet/Messages/Authentication/FailureMessage.cs
  82. 67 67
      src/Renci.SshNet/Messages/Authentication/InformationRequestMessage.cs
  83. 57 57
      src/Renci.SshNet/Messages/Authentication/InformationResponseMessage.cs
  84. 56 56
      src/Renci.SshNet/Messages/Authentication/PasswordChangeRequiredMessage.cs
  85. 59 59
      src/Renci.SshNet/Messages/Authentication/PublicKeyMessage.cs
  86. 105 105
      src/Renci.SshNet/Messages/Authentication/RequestMessage.cs
  87. 104 104
      src/Renci.SshNet/Messages/Authentication/RequestMessageHost.cs
  88. 62 62
      src/Renci.SshNet/Messages/Authentication/RequestMessageKeyboardInteractive.cs
  89. 18 18
      src/Renci.SshNet/Messages/Authentication/RequestMessageNone.cs
  90. 83 83
      src/Renci.SshNet/Messages/Authentication/RequestMessagePassword.cs
  91. 98 98
      src/Renci.SshNet/Messages/Authentication/RequestMessagePublicKey.cs
  92. 23 23
      src/Renci.SshNet/Messages/Authentication/SuccessMessage.cs
  93. 26 26
      src/Renci.SshNet/Messages/Connection/ChannelCloseMessage.cs
  94. 118 118
      src/Renci.SshNet/Messages/Connection/ChannelDataMessage.cs
  95. 26 26
      src/Renci.SshNet/Messages/Connection/ChannelEofMessage.cs
  96. 77 77
      src/Renci.SshNet/Messages/Connection/ChannelExtendedDataMessage.cs
  97. 26 26
      src/Renci.SshNet/Messages/Connection/ChannelFailureMessage.cs
  98. 77 77
      src/Renci.SshNet/Messages/Connection/ChannelMessage.cs
  99. 32 32
      src/Renci.SshNet/Messages/Connection/ChannelOpen/ChannelOpenInfo.cs
  100. 147 147
      src/Renci.SshNet/Messages/Connection/ChannelOpen/ChannelOpenMessage.cs

+ 169 - 169
src/Renci.SshNet/ClientAuthentication.cs

@@ -1,169 +1,169 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Renci.SshNet.Common;
-
-namespace Renci.SshNet
-{
-    internal class ClientAuthentication : IClientAuthentication
-    {
-        public void Authenticate(IConnectionInfoInternal connectionInfo, ISession session)
-        {
-            if (connectionInfo == null)
-                throw new ArgumentNullException("connectionInfo");
-            if (session == null)
-                throw new ArgumentNullException("session");
-
-            session.RegisterMessage("SSH_MSG_USERAUTH_FAILURE");
-            session.RegisterMessage("SSH_MSG_USERAUTH_SUCCESS");
-            session.RegisterMessage("SSH_MSG_USERAUTH_BANNER");
-            session.UserAuthenticationBannerReceived += connectionInfo.UserAuthenticationBannerReceived;
-
-            try
-            {
-                // the exception to report an authentication failure with
-                SshAuthenticationException authenticationException = null;
-
-                // try to authenticate against none
-                var noneAuthenticationMethod = connectionInfo.CreateNoneAuthenticationMethod();
-
-                var authenticated = noneAuthenticationMethod.Authenticate(session);
-                if (authenticated != AuthenticationResult.Success)
-                {
-                    if (!TryAuthenticate(session, new AuthenticationState(connectionInfo.AuthenticationMethods), noneAuthenticationMethod.AllowedAuthentications.ToList(), ref authenticationException))
-                    {
-                        throw authenticationException;
-                    }
-                }
-            }
-            finally
-            {
-                session.UserAuthenticationBannerReceived -= connectionInfo.UserAuthenticationBannerReceived;
-                session.UnRegisterMessage("SSH_MSG_USERAUTH_FAILURE");
-                session.UnRegisterMessage("SSH_MSG_USERAUTH_SUCCESS");
-                session.UnRegisterMessage("SSH_MSG_USERAUTH_BANNER");
-            }
-
-        }
-
-        private bool TryAuthenticate(ISession session,
-                                     AuthenticationState authenticationState,
-                                     ICollection<string> allowedAuthenticationMethods,
-                                     ref SshAuthenticationException authenticationException)
-        {
-            if (allowedAuthenticationMethods.Count == 0)
-            {
-                authenticationException = new SshAuthenticationException("No authentication methods defined on SSH server.");
-                return false;
-            }
-
-            // we want to try authentication methods in the order in which they were
-            // passed in the ctor, not the order in which the SSH server returns
-            // the allowed authentication methods
-            var matchingAuthenticationMethods = authenticationState.SupportedAuthenticationMethods.Where(a => allowedAuthenticationMethods.Contains(a.Name)).ToList();
-            if (matchingAuthenticationMethods.Count == 0)
-            {
-                authenticationException = new SshAuthenticationException(string.Format("No suitable authentication method found to complete authentication ({0}).", string.Join(",", allowedAuthenticationMethods.ToArray())));
-                return false;
-            }
-
-            foreach (var authenticationMethod in GetOrderedAuthenticationMethods(authenticationState, matchingAuthenticationMethods))
-            {
-                if (authenticationState.FailedAuthenticationMethods.Contains(authenticationMethod))
-                    continue;
-
-                // when the authentication method was previously executed, then skip the authentication
-                // method as long as there's another authentication method to try; this is done to avoid
-                // a stack overflow for servers that do not update the list of allowed authentication
-                // methods after a partial success
-
-                if (!authenticationState.ExecutedAuthenticationMethods.Contains(authenticationMethod))
-                {
-                    // update state to reflect previosuly executed authentication methods
-                    authenticationState.ExecutedAuthenticationMethods.Add(authenticationMethod);
-                }
-
-                var authenticationResult = authenticationMethod.Authenticate(session);
-                switch (authenticationResult)
-                {
-                    case AuthenticationResult.PartialSuccess:
-                        if (TryAuthenticate(session, authenticationState, authenticationMethod.AllowedAuthentications, ref authenticationException))
-                        {
-                            authenticationResult = AuthenticationResult.Success;
-                        }
-                        break;
-                    case AuthenticationResult.Failure:
-                        authenticationState.FailedAuthenticationMethods.Add(authenticationMethod);
-                        authenticationException = new SshAuthenticationException(string.Format("Permission denied ({0}).", authenticationMethod.Name));
-                        break;
-                    case AuthenticationResult.Success:
-                        authenticationException = null;
-                        break;
-                }
-
-                if (authenticationResult == AuthenticationResult.Success)
-                    return true;
-            }
-
-            return false;
-        }
-
-        private IEnumerable<IAuthenticationMethod> GetOrderedAuthenticationMethods(AuthenticationState authenticationState, IEnumerable<IAuthenticationMethod> matchingAuthenticationMethods)
-        {
-            var skippedAuthenticationMethods = new List<IAuthenticationMethod>();
-
-            foreach (var authenticationMethod in matchingAuthenticationMethods)
-            {
-                if (authenticationState.ExecutedAuthenticationMethods.Contains(authenticationMethod))
-                {
-                    skippedAuthenticationMethods.Add(authenticationMethod);
-                    continue;
-                }
-
-                yield return authenticationMethod;
-            }
-
-            foreach (var authenticationMethod in skippedAuthenticationMethods)
-                yield return authenticationMethod;
-        }
-
-        private class AuthenticationState
-        {
-            private readonly IList<IAuthenticationMethod> _supportedAuthenticationMethods;
-
-            public AuthenticationState(IList<IAuthenticationMethod> supportedAuthenticationMethods)
-            {
-                _supportedAuthenticationMethods = supportedAuthenticationMethods;
-                ExecutedAuthenticationMethods = new List<IAuthenticationMethod>();
-                FailedAuthenticationMethods = new List<IAuthenticationMethod>();
-            }
-
-            /// <summary>
-            /// Gets the list of authentication methods that were previously executed.
-            /// </summary>
-            /// <value>
-            /// The list of authentication methods that were previously executed.
-            /// </value>
-            public IList<IAuthenticationMethod> ExecutedAuthenticationMethods { get; private set; }
-
-            /// <summary>
-            /// Gets the list of authentications methods that failed.
-            /// </summary>
-            /// <value>
-            /// The list of authentications methods that failed.
-            /// </value>
-            public IList<IAuthenticationMethod> FailedAuthenticationMethods { get; private set; }
-
-            /// <summary>
-            /// Gets the list of supported authentication methods.
-            /// </summary>
-            /// <value>
-            /// The list of supported authentication methods.
-            /// </value>
-            public IEnumerable<IAuthenticationMethod> SupportedAuthenticationMethods
-            {
-                get { return _supportedAuthenticationMethods; }
-            }
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet
+{
+    internal class ClientAuthentication : IClientAuthentication
+    {
+        public void Authenticate(IConnectionInfoInternal connectionInfo, ISession session)
+        {
+            if (connectionInfo == null)
+                throw new ArgumentNullException("connectionInfo");
+            if (session == null)
+                throw new ArgumentNullException("session");
+
+            session.RegisterMessage("SSH_MSG_USERAUTH_FAILURE");
+            session.RegisterMessage("SSH_MSG_USERAUTH_SUCCESS");
+            session.RegisterMessage("SSH_MSG_USERAUTH_BANNER");
+            session.UserAuthenticationBannerReceived += connectionInfo.UserAuthenticationBannerReceived;
+
+            try
+            {
+                // the exception to report an authentication failure with
+                SshAuthenticationException authenticationException = null;
+
+                // try to authenticate against none
+                var noneAuthenticationMethod = connectionInfo.CreateNoneAuthenticationMethod();
+
+                var authenticated = noneAuthenticationMethod.Authenticate(session);
+                if (authenticated != AuthenticationResult.Success)
+                {
+                    if (!TryAuthenticate(session, new AuthenticationState(connectionInfo.AuthenticationMethods), noneAuthenticationMethod.AllowedAuthentications.ToList(), ref authenticationException))
+                    {
+                        throw authenticationException;
+                    }
+                }
+            }
+            finally
+            {
+                session.UserAuthenticationBannerReceived -= connectionInfo.UserAuthenticationBannerReceived;
+                session.UnRegisterMessage("SSH_MSG_USERAUTH_FAILURE");
+                session.UnRegisterMessage("SSH_MSG_USERAUTH_SUCCESS");
+                session.UnRegisterMessage("SSH_MSG_USERAUTH_BANNER");
+            }
+
+        }
+
+        private bool TryAuthenticate(ISession session,
+                                     AuthenticationState authenticationState,
+                                     ICollection<string> allowedAuthenticationMethods,
+                                     ref SshAuthenticationException authenticationException)
+        {
+            if (allowedAuthenticationMethods.Count == 0)
+            {
+                authenticationException = new SshAuthenticationException("No authentication methods defined on SSH server.");
+                return false;
+            }
+
+            // we want to try authentication methods in the order in which they were
+            // passed in the ctor, not the order in which the SSH server returns
+            // the allowed authentication methods
+            var matchingAuthenticationMethods = authenticationState.SupportedAuthenticationMethods.Where(a => allowedAuthenticationMethods.Contains(a.Name)).ToList();
+            if (matchingAuthenticationMethods.Count == 0)
+            {
+                authenticationException = new SshAuthenticationException(string.Format("No suitable authentication method found to complete authentication ({0}).", string.Join(",", allowedAuthenticationMethods.ToArray())));
+                return false;
+            }
+
+            foreach (var authenticationMethod in GetOrderedAuthenticationMethods(authenticationState, matchingAuthenticationMethods))
+            {
+                if (authenticationState.FailedAuthenticationMethods.Contains(authenticationMethod))
+                    continue;
+
+                // when the authentication method was previously executed, then skip the authentication
+                // method as long as there's another authentication method to try; this is done to avoid
+                // a stack overflow for servers that do not update the list of allowed authentication
+                // methods after a partial success
+
+                if (!authenticationState.ExecutedAuthenticationMethods.Contains(authenticationMethod))
+                {
+                    // update state to reflect previosuly executed authentication methods
+                    authenticationState.ExecutedAuthenticationMethods.Add(authenticationMethod);
+                }
+
+                var authenticationResult = authenticationMethod.Authenticate(session);
+                switch (authenticationResult)
+                {
+                    case AuthenticationResult.PartialSuccess:
+                        if (TryAuthenticate(session, authenticationState, authenticationMethod.AllowedAuthentications, ref authenticationException))
+                        {
+                            authenticationResult = AuthenticationResult.Success;
+                        }
+                        break;
+                    case AuthenticationResult.Failure:
+                        authenticationState.FailedAuthenticationMethods.Add(authenticationMethod);
+                        authenticationException = new SshAuthenticationException(string.Format("Permission denied ({0}).", authenticationMethod.Name));
+                        break;
+                    case AuthenticationResult.Success:
+                        authenticationException = null;
+                        break;
+                }
+
+                if (authenticationResult == AuthenticationResult.Success)
+                    return true;
+            }
+
+            return false;
+        }
+
+        private IEnumerable<IAuthenticationMethod> GetOrderedAuthenticationMethods(AuthenticationState authenticationState, IEnumerable<IAuthenticationMethod> matchingAuthenticationMethods)
+        {
+            var skippedAuthenticationMethods = new List<IAuthenticationMethod>();
+
+            foreach (var authenticationMethod in matchingAuthenticationMethods)
+            {
+                if (authenticationState.ExecutedAuthenticationMethods.Contains(authenticationMethod))
+                {
+                    skippedAuthenticationMethods.Add(authenticationMethod);
+                    continue;
+                }
+
+                yield return authenticationMethod;
+            }
+
+            foreach (var authenticationMethod in skippedAuthenticationMethods)
+                yield return authenticationMethod;
+        }
+
+        private class AuthenticationState
+        {
+            private readonly IList<IAuthenticationMethod> _supportedAuthenticationMethods;
+
+            public AuthenticationState(IList<IAuthenticationMethod> supportedAuthenticationMethods)
+            {
+                _supportedAuthenticationMethods = supportedAuthenticationMethods;
+                ExecutedAuthenticationMethods = new List<IAuthenticationMethod>();
+                FailedAuthenticationMethods = new List<IAuthenticationMethod>();
+            }
+
+            /// <summary>
+            /// Gets the list of authentication methods that were previously executed.
+            /// </summary>
+            /// <value>
+            /// The list of authentication methods that were previously executed.
+            /// </value>
+            public IList<IAuthenticationMethod> ExecutedAuthenticationMethods { get; private set; }
+
+            /// <summary>
+            /// Gets the list of authentications methods that failed.
+            /// </summary>
+            /// <value>
+            /// The list of authentications methods that failed.
+            /// </value>
+            public IList<IAuthenticationMethod> FailedAuthenticationMethods { get; private set; }
+
+            /// <summary>
+            /// Gets the list of supported authentication methods.
+            /// </summary>
+            /// <value>
+            /// The list of supported authentication methods.
+            /// </value>
+            public IEnumerable<IAuthenticationMethod> SupportedAuthenticationMethods
+            {
+                get { return _supportedAuthenticationMethods; }
+            }
+        }
+    }
+}

+ 68 - 68
src/Renci.SshNet/CommandAsyncResult.cs

@@ -1,68 +1,68 @@
-using System;
-using System.Threading;
-
-namespace Renci.SshNet
-{
-    /// <summary>
-    /// Provides additional information for asynchronous command execution
-    /// </summary>
-    public class CommandAsyncResult : IAsyncResult
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="CommandAsyncResult"/> class.
-        /// </summary>
-        internal CommandAsyncResult()
-        {
-        }
-
-        /// <summary>
-        /// Gets or sets the bytes received. If SFTP only file bytes are counted.
-        /// </summary>
-        /// <value>Total bytes received.</value>
-        public int BytesReceived { get; set; }
-
-        /// <summary>
-        /// Gets or sets the bytes sent by SFTP.
-        /// </summary>
-        /// <value>Total bytes sent.</value>
-        public int BytesSent { get; set; }
-
-        #region IAsyncResult Members
-
-        /// <summary>
-        /// Gets a user-defined object that qualifies or contains information about an asynchronous operation.
-        /// </summary>
-        /// <returns>A user-defined object that qualifies or contains information about an asynchronous operation.</returns>
-        public object AsyncState { get; internal set; }
-
-        /// <summary>
-        /// Gets a <see cref="T:System.Threading.WaitHandle"/> that is used to wait for an asynchronous operation to complete.
-        /// </summary>
-        /// <returns>A <see cref="T:System.Threading.WaitHandle"/> that is used to wait for an asynchronous operation to complete.</returns>
-        public WaitHandle AsyncWaitHandle { get; internal set; }
-
-        /// <summary>
-        /// Gets a value that indicates whether the asynchronous operation completed synchronously.
-        /// </summary>
-        /// <returns>true if the asynchronous operation completed synchronously; otherwise, false.</returns>
-        public bool CompletedSynchronously { get; internal set; }
-
-        /// <summary>
-        /// Gets a value that indicates whether the asynchronous operation has completed.
-        /// </summary>
-        /// <returns>true if the operation is complete; otherwise, false.</returns>
-        public bool IsCompleted { get; internal set; }
-
-        #endregion
-
-        /// <summary>
-        /// Gets a value indicating whether <see cref="SshCommand.EndExecute(IAsyncResult)"/> was already called for this
-        /// <see cref="CommandAsyncResult"/>.
-        /// </summary>
-        /// <returns>
-        /// <c>true</c> if <see cref="SshCommand.EndExecute(IAsyncResult)"/> was already called for this <see cref="CommandAsyncResult"/>;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        internal bool EndCalled { get; set; }
-    }
-}
+using System;
+using System.Threading;
+
+namespace Renci.SshNet
+{
+    /// <summary>
+    /// Provides additional information for asynchronous command execution
+    /// </summary>
+    public class CommandAsyncResult : IAsyncResult
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="CommandAsyncResult"/> class.
+        /// </summary>
+        internal CommandAsyncResult()
+        {
+        }
+
+        /// <summary>
+        /// Gets or sets the bytes received. If SFTP only file bytes are counted.
+        /// </summary>
+        /// <value>Total bytes received.</value>
+        public int BytesReceived { get; set; }
+
+        /// <summary>
+        /// Gets or sets the bytes sent by SFTP.
+        /// </summary>
+        /// <value>Total bytes sent.</value>
+        public int BytesSent { get; set; }
+
+        #region IAsyncResult Members
+
+        /// <summary>
+        /// Gets a user-defined object that qualifies or contains information about an asynchronous operation.
+        /// </summary>
+        /// <returns>A user-defined object that qualifies or contains information about an asynchronous operation.</returns>
+        public object AsyncState { get; internal set; }
+
+        /// <summary>
+        /// Gets a <see cref="T:System.Threading.WaitHandle"/> that is used to wait for an asynchronous operation to complete.
+        /// </summary>
+        /// <returns>A <see cref="T:System.Threading.WaitHandle"/> that is used to wait for an asynchronous operation to complete.</returns>
+        public WaitHandle AsyncWaitHandle { get; internal set; }
+
+        /// <summary>
+        /// Gets a value that indicates whether the asynchronous operation completed synchronously.
+        /// </summary>
+        /// <returns>true if the asynchronous operation completed synchronously; otherwise, false.</returns>
+        public bool CompletedSynchronously { get; internal set; }
+
+        /// <summary>
+        /// Gets a value that indicates whether the asynchronous operation has completed.
+        /// </summary>
+        /// <returns>true if the operation is complete; otherwise, false.</returns>
+        public bool IsCompleted { get; internal set; }
+
+        #endregion
+
+        /// <summary>
+        /// Gets a value indicating whether <see cref="SshCommand.EndExecute(IAsyncResult)"/> was already called for this
+        /// <see cref="CommandAsyncResult"/>.
+        /// </summary>
+        /// <returns>
+        /// <c>true</c> if <see cref="SshCommand.EndExecute(IAsyncResult)"/> was already called for this <see cref="CommandAsyncResult"/>;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        internal bool EndCalled { get; set; }
+    }
+}

+ 209 - 209
src/Renci.SshNet/Common/ASCIIEncoding.cs

@@ -1,210 +1,210 @@
-#if !FEATURE_ENCODING_ASCII
-
-using System;
-using System.Text;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Implementation of ASCII Encoding
-    /// </summary>
-    public class ASCIIEncoding : Encoding
-    {
-        private readonly char _fallbackChar;
-
-        private static readonly char[] ByteToChar;
-
-        static ASCIIEncoding()
-        {
-            if (ByteToChar == null)
-            {
-                ByteToChar = new char[128];
-                var ch = '\0';
-                for (byte i = 0; i < 128; i++)
-                {
-                    ByteToChar[i] = ch++;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ASCIIEncoding"/> class.
-        /// </summary>
-        public ASCIIEncoding()
-        {
-            _fallbackChar = '?';
-        }
-
-        /// <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)
-        {
-            return count;
-        }
-
-        /// <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)
-        {
-            for (var i = 0; i < charCount && i < chars.Length; i++)
-            {
-                var b = (byte)chars[i + charIndex];
-
-                if (b > 127)
-                    b = (byte) _fallbackChar;
-
-                bytes[i + byteIndex] = b;
-            }
-            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)
-        {
-            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)
-        {
-            for (var i = 0; i < byteCount; i++)
-            {
-                var b = bytes[i + byteIndex];
-                char ch;
-
-                if (b > 127)
-                {
-                    ch = _fallbackChar;
-                }
-                else 
-                {
-                    ch = ByteToChar[b];
-                }
-
-                chars[i + charIndex] = ch;
-            }
-            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", "Non-negative number required.");
-
-            return charCount + 1;
-        }
-
-        /// <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", "Non-negative number required.");
-
-            return byteCount;
-        }
-
-#if !SILVERLIGHT && !WINDOWS_PHONE
-        /// <summary>
-        /// Gets a value indicating whether the current encoding uses single-byte code points
-        /// </summary>
-        /// <value>
-        /// This property is always <c>true</c>.
-        /// </value>
-        public override bool IsSingleByte
-        {
-            get { return true; }
-        }
-#endif // !SILVERLIGHT && !WINDOWS_PHONE
-    }
-}
-
+#if !FEATURE_ENCODING_ASCII
+
+using System;
+using System.Text;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Implementation of ASCII Encoding
+    /// </summary>
+    public class ASCIIEncoding : Encoding
+    {
+        private readonly char _fallbackChar;
+
+        private static readonly char[] ByteToChar;
+
+        static ASCIIEncoding()
+        {
+            if (ByteToChar == null)
+            {
+                ByteToChar = new char[128];
+                var ch = '\0';
+                for (byte i = 0; i < 128; i++)
+                {
+                    ByteToChar[i] = ch++;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ASCIIEncoding"/> class.
+        /// </summary>
+        public ASCIIEncoding()
+        {
+            _fallbackChar = '?';
+        }
+
+        /// <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)
+        {
+            return count;
+        }
+
+        /// <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)
+        {
+            for (var i = 0; i < charCount && i < chars.Length; i++)
+            {
+                var b = (byte)chars[i + charIndex];
+
+                if (b > 127)
+                    b = (byte) _fallbackChar;
+
+                bytes[i + byteIndex] = b;
+            }
+            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)
+        {
+            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)
+        {
+            for (var i = 0; i < byteCount; i++)
+            {
+                var b = bytes[i + byteIndex];
+                char ch;
+
+                if (b > 127)
+                {
+                    ch = _fallbackChar;
+                }
+                else 
+                {
+                    ch = ByteToChar[b];
+                }
+
+                chars[i + charIndex] = ch;
+            }
+            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", "Non-negative number required.");
+
+            return charCount + 1;
+        }
+
+        /// <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", "Non-negative number required.");
+
+            return byteCount;
+        }
+
+#if !SILVERLIGHT && !WINDOWS_PHONE
+        /// <summary>
+        /// Gets a value indicating whether the current encoding uses single-byte code points
+        /// </summary>
+        /// <value>
+        /// This property is always <c>true</c>.
+        /// </value>
+        public override bool IsSingleByte
+        {
+            get { return true; }
+        }
+#endif // !SILVERLIGHT && !WINDOWS_PHONE
+    }
+}
+
 #endif // !FEATURE_ENCODING_ASCII

+ 197 - 197
src/Renci.SshNet/Common/AsyncResult.cs

@@ -1,198 +1,198 @@
-using System;
-using System.Threading;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Base class to encapsulates the results of an asynchronous operation.
-    /// </summary>
-    public abstract class AsyncResult : IAsyncResult
-    {
-        // Fields set at construction which never change while operation is pending
-        private readonly AsyncCallback _asyncCallback;
-
-        private readonly Object _asyncState;
-
-        // Field set at construction which do change after operation completes
-        private const Int32 StatePending = 0;
-
-        private const Int32 StateCompletedSynchronously = 1;
-
-        private const Int32 StateCompletedAsynchronously = 2;
-
-        private Int32 _completedState = StatePending;
-
-        // Field that may or may not get set depending on usage
-        private ManualResetEvent _asyncWaitHandle;
-
-        // Fields set when operation completes
-        private Exception _exception;
-
-        /// <summary>
-        /// Gets or sets a value indicating whether EndInvoke has been called on the current AsyncResult.
-        /// </summary>
-        /// <value>
-        /// 	<c>true</c> if EndInvoke has been called on the current AsyncResult; otherwise, <c>false</c>.
-        /// </value>
-        public bool EndInvokeCalled { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="AsyncResult"/> class.
-        /// </summary>
-        /// <param name="asyncCallback">The async callback.</param>
-        /// <param name="state">The state.</param>
-        protected AsyncResult(AsyncCallback asyncCallback, Object state)
-        {
-            _asyncCallback = asyncCallback;
-            _asyncState = state;
-        }
-
-        /// <summary>
-        /// Marks asynchronous operation as completed.
-        /// </summary>
-        /// <param name="exception">The exception.</param>
-        /// <param name="completedSynchronously">if set to <c>true</c> [completed synchronously].</param>
-        public void SetAsCompleted(Exception exception, Boolean completedSynchronously)
-        {
-            // Passing null for exception means no error occurred; this is the common case
-            _exception = exception;
-
-            // The m_CompletedState field MUST be set prior calling the callback
-            var prevState = Interlocked.Exchange(ref _completedState,
-               completedSynchronously ? StateCompletedSynchronously : StateCompletedAsynchronously);
-            if (prevState != StatePending)
-                throw new InvalidOperationException("You can set a result only once");
-
-            // If the event exists, set it
-            if (_asyncWaitHandle != null)
-                _asyncWaitHandle.Set();
-
-            // If a callback method was set, call it
-            if (_asyncCallback != null)
-                _asyncCallback(this);
-        }
-
-        /// <summary>
-        /// Waits until the asynchronous operation completes, and then returns. 
-        /// </summary>
-        public void EndInvoke()
-        {
-            // This method assumes that only 1 thread calls EndInvoke for this object
-            if (!IsCompleted)
-            {
-                // If the operation isn't done, wait for it
-                AsyncWaitHandle.WaitOne();
-                AsyncWaitHandle.Dispose();
-                _asyncWaitHandle = null;  // Allow early GC
-            }
-
-            EndInvokeCalled = true;
-
-            // Operation is done: if an exception occurred, throw it
-            if (_exception != null)
-                throw new SshException(_exception.Message, _exception);
-        }
-
-        #region Implementation of IAsyncResult
-
-        /// <summary>
-        /// Gets a user-defined object that qualifies or contains information about an asynchronous operation.
-        /// </summary>
-        /// <returns>A user-defined object that qualifies or contains information about an asynchronous operation.</returns>
-        public Object AsyncState { get { return _asyncState; } }
-
-        /// <summary>
-        /// Gets a value that indicates whether the asynchronous operation completed synchronously.
-        /// </summary>
-        /// <returns>true if the asynchronous operation completed synchronously; otherwise, false.</returns>
-        public Boolean CompletedSynchronously
-        {
-            get { return _completedState == StateCompletedSynchronously; }
-        }
-
-        /// <summary>
-        /// Gets a <see cref="T:System.Threading.WaitHandle"/> that is used to wait for an asynchronous operation to complete.
-        /// </summary>
-        /// <returns>A <see cref="T:System.Threading.WaitHandle"/> that is used to wait for an asynchronous operation to complete.</returns>
-        public WaitHandle AsyncWaitHandle
-        {
-            get
-            {
-                if (_asyncWaitHandle == null)
-                {
-                    var done = IsCompleted;
-                    var mre = new ManualResetEvent(done);
-                    if (Interlocked.CompareExchange(ref _asyncWaitHandle, mre, null) != null)
-                    {
-                        // Another thread created this object's event; dispose the event we just created
-                        mre.Dispose();
-                    }
-                    else
-                    {
-                        if (!done && IsCompleted)
-                        {
-                            // If the operation wasn't done when we created 
-                            // the event but now it is done, set the event
-                            _asyncWaitHandle.Set();
-                        }
-                    }
-                }
-                return _asyncWaitHandle;
-            }
-        }
-
-        /// <summary>
-        /// Gets a value that indicates whether the asynchronous operation has completed.
-        /// </summary>
-        /// <returns>true if the operation is complete; otherwise, false.</returns>
-        public Boolean IsCompleted
-        {
-            get { return _completedState != StatePending; }
-        }
-        #endregion
-    }
-
-    /// <summary>
-    /// Base class to encapsulates the results of an asynchronous operation that returns result.
-    /// </summary>
-    /// <typeparam name="TResult">The type of the result.</typeparam>
-    public abstract class AsyncResult<TResult> : AsyncResult
-    {
-        // Field set when operation completes
-        private TResult _result;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="AsyncResult&lt;TResult&gt;"/> class.
-        /// </summary>
-        /// <param name="asyncCallback">The async callback.</param>
-        /// <param name="state">The state.</param>
-        protected AsyncResult(AsyncCallback asyncCallback, Object state)
-            : base(asyncCallback, state)
-        {
-        }
-
-        /// <summary>
-        /// Marks asynchronous operation as completed.
-        /// </summary>
-        /// <param name="result">The result.</param>
-        /// <param name="completedSynchronously">if set to <c>true</c> [completed synchronously].</param>
-        public void SetAsCompleted(TResult result, Boolean completedSynchronously)
-        {
-            // Save the asynchronous operation's result
-            _result = result;
-
-            // Tell the base class that the operation completed successfully (no exception)
-            base.SetAsCompleted(null, completedSynchronously);
-        }
-
-        /// <summary>
-        /// Waits until the asynchronous operation completes, and then returns the value generated by the asynchronous operation. 
-        /// </summary>
-        /// <returns>Invocation result</returns>
-        public new TResult EndInvoke()
-        {
-            base.EndInvoke(); // Wait until operation has completed 
-            return _result;  // Return the result (if above didn't throw)
-        }
-    }
+using System;
+using System.Threading;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Base class to encapsulates the results of an asynchronous operation.
+    /// </summary>
+    public abstract class AsyncResult : IAsyncResult
+    {
+        // Fields set at construction which never change while operation is pending
+        private readonly AsyncCallback _asyncCallback;
+
+        private readonly Object _asyncState;
+
+        // Field set at construction which do change after operation completes
+        private const Int32 StatePending = 0;
+
+        private const Int32 StateCompletedSynchronously = 1;
+
+        private const Int32 StateCompletedAsynchronously = 2;
+
+        private Int32 _completedState = StatePending;
+
+        // Field that may or may not get set depending on usage
+        private ManualResetEvent _asyncWaitHandle;
+
+        // Fields set when operation completes
+        private Exception _exception;
+
+        /// <summary>
+        /// Gets or sets a value indicating whether EndInvoke has been called on the current AsyncResult.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> if EndInvoke has been called on the current AsyncResult; otherwise, <c>false</c>.
+        /// </value>
+        public bool EndInvokeCalled { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AsyncResult"/> class.
+        /// </summary>
+        /// <param name="asyncCallback">The async callback.</param>
+        /// <param name="state">The state.</param>
+        protected AsyncResult(AsyncCallback asyncCallback, Object state)
+        {
+            _asyncCallback = asyncCallback;
+            _asyncState = state;
+        }
+
+        /// <summary>
+        /// Marks asynchronous operation as completed.
+        /// </summary>
+        /// <param name="exception">The exception.</param>
+        /// <param name="completedSynchronously">if set to <c>true</c> [completed synchronously].</param>
+        public void SetAsCompleted(Exception exception, Boolean completedSynchronously)
+        {
+            // Passing null for exception means no error occurred; this is the common case
+            _exception = exception;
+
+            // The m_CompletedState field MUST be set prior calling the callback
+            var prevState = Interlocked.Exchange(ref _completedState,
+               completedSynchronously ? StateCompletedSynchronously : StateCompletedAsynchronously);
+            if (prevState != StatePending)
+                throw new InvalidOperationException("You can set a result only once");
+
+            // If the event exists, set it
+            if (_asyncWaitHandle != null)
+                _asyncWaitHandle.Set();
+
+            // If a callback method was set, call it
+            if (_asyncCallback != null)
+                _asyncCallback(this);
+        }
+
+        /// <summary>
+        /// Waits until the asynchronous operation completes, and then returns. 
+        /// </summary>
+        public void EndInvoke()
+        {
+            // This method assumes that only 1 thread calls EndInvoke for this object
+            if (!IsCompleted)
+            {
+                // If the operation isn't done, wait for it
+                AsyncWaitHandle.WaitOne();
+                AsyncWaitHandle.Dispose();
+                _asyncWaitHandle = null;  // Allow early GC
+            }
+
+            EndInvokeCalled = true;
+
+            // Operation is done: if an exception occurred, throw it
+            if (_exception != null)
+                throw new SshException(_exception.Message, _exception);
+        }
+
+        #region Implementation of IAsyncResult
+
+        /// <summary>
+        /// Gets a user-defined object that qualifies or contains information about an asynchronous operation.
+        /// </summary>
+        /// <returns>A user-defined object that qualifies or contains information about an asynchronous operation.</returns>
+        public Object AsyncState { get { return _asyncState; } }
+
+        /// <summary>
+        /// Gets a value that indicates whether the asynchronous operation completed synchronously.
+        /// </summary>
+        /// <returns>true if the asynchronous operation completed synchronously; otherwise, false.</returns>
+        public Boolean CompletedSynchronously
+        {
+            get { return _completedState == StateCompletedSynchronously; }
+        }
+
+        /// <summary>
+        /// Gets a <see cref="T:System.Threading.WaitHandle"/> that is used to wait for an asynchronous operation to complete.
+        /// </summary>
+        /// <returns>A <see cref="T:System.Threading.WaitHandle"/> that is used to wait for an asynchronous operation to complete.</returns>
+        public WaitHandle AsyncWaitHandle
+        {
+            get
+            {
+                if (_asyncWaitHandle == null)
+                {
+                    var done = IsCompleted;
+                    var mre = new ManualResetEvent(done);
+                    if (Interlocked.CompareExchange(ref _asyncWaitHandle, mre, null) != null)
+                    {
+                        // Another thread created this object's event; dispose the event we just created
+                        mre.Dispose();
+                    }
+                    else
+                    {
+                        if (!done && IsCompleted)
+                        {
+                            // If the operation wasn't done when we created 
+                            // the event but now it is done, set the event
+                            _asyncWaitHandle.Set();
+                        }
+                    }
+                }
+                return _asyncWaitHandle;
+            }
+        }
+
+        /// <summary>
+        /// Gets a value that indicates whether the asynchronous operation has completed.
+        /// </summary>
+        /// <returns>true if the operation is complete; otherwise, false.</returns>
+        public Boolean IsCompleted
+        {
+            get { return _completedState != StatePending; }
+        }
+        #endregion
+    }
+
+    /// <summary>
+    /// Base class to encapsulates the results of an asynchronous operation that returns result.
+    /// </summary>
+    /// <typeparam name="TResult">The type of the result.</typeparam>
+    public abstract class AsyncResult<TResult> : AsyncResult
+    {
+        // Field set when operation completes
+        private TResult _result;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AsyncResult&lt;TResult&gt;"/> class.
+        /// </summary>
+        /// <param name="asyncCallback">The async callback.</param>
+        /// <param name="state">The state.</param>
+        protected AsyncResult(AsyncCallback asyncCallback, Object state)
+            : base(asyncCallback, state)
+        {
+        }
+
+        /// <summary>
+        /// Marks asynchronous operation as completed.
+        /// </summary>
+        /// <param name="result">The result.</param>
+        /// <param name="completedSynchronously">if set to <c>true</c> [completed synchronously].</param>
+        public void SetAsCompleted(TResult result, Boolean completedSynchronously)
+        {
+            // Save the asynchronous operation's result
+            _result = result;
+
+            // Tell the base class that the operation completed successfully (no exception)
+            base.SetAsCompleted(null, completedSynchronously);
+        }
+
+        /// <summary>
+        /// Waits until the asynchronous operation completes, and then returns the value generated by the asynchronous operation. 
+        /// </summary>
+        /// <returns>Invocation result</returns>
+        public new TResult EndInvoke()
+        {
+            base.EndInvoke(); // Wait until operation has completed 
+            return _result;  // Return the result (if above didn't throw)
+        }
+    }
 }

+ 31 - 31
src/Renci.SshNet/Common/AuthenticationBannerEventArgs.cs

@@ -1,31 +1,31 @@
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Provides data for <see cref="Renci.SshNet.ConnectionInfo.AuthenticationBanner"/> event.
-    /// </summary>
-    public class AuthenticationBannerEventArgs : AuthenticationEventArgs
-    {
-        /// <summary>
-        /// Gets banner message.
-        /// </summary>
-        public string BannerMessage { get; private set; }
-
-        /// <summary>
-        /// Gets banner language.
-        /// </summary>
-        public string Language { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="AuthenticationBannerEventArgs"/> class.
-        /// </summary>
-        /// <param name="username">The username.</param>
-        /// <param name="message">Banner message.</param>
-        /// <param name="language">Banner language.</param>
-        public AuthenticationBannerEventArgs(string username, string message, string language)
-            : base(username)
-        {
-            BannerMessage = message;
-            Language = language;
-        }
-    }
-}
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Provides data for <see cref="Renci.SshNet.ConnectionInfo.AuthenticationBanner"/> event.
+    /// </summary>
+    public class AuthenticationBannerEventArgs : AuthenticationEventArgs
+    {
+        /// <summary>
+        /// Gets banner message.
+        /// </summary>
+        public string BannerMessage { get; private set; }
+
+        /// <summary>
+        /// Gets banner language.
+        /// </summary>
+        public string Language { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AuthenticationBannerEventArgs"/> class.
+        /// </summary>
+        /// <param name="username">The username.</param>
+        /// <param name="message">Banner message.</param>
+        /// <param name="language">Banner language.</param>
+        public AuthenticationBannerEventArgs(string username, string message, string language)
+            : base(username)
+        {
+            BannerMessage = message;
+            Language = language;
+        }
+    }
+}

+ 24 - 24
src/Renci.SshNet/Common/AuthenticationEventArgs.cs

@@ -1,24 +1,24 @@
-using System;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Base class for authentication events.
-    /// </summary>
-    public abstract class AuthenticationEventArgs : EventArgs
-    {
-        /// <summary>
-        /// Gets the username.
-        /// </summary>
-        public string Username { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="AuthenticationEventArgs"/> class.
-        /// </summary>
-        /// <param name="username">The username.</param>
-        protected AuthenticationEventArgs(string username)
-        {
-            Username = username;
-        }
-    }
-}
+using System;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Base class for authentication events.
+    /// </summary>
+    public abstract class AuthenticationEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Gets the username.
+        /// </summary>
+        public string Username { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AuthenticationEventArgs"/> class.
+        /// </summary>
+        /// <param name="username">The username.</param>
+        protected AuthenticationEventArgs(string username)
+        {
+            Username = username;
+        }
+    }
+}

+ 25 - 25
src/Renci.SshNet/Common/AuthenticationPasswordChangeEventArgs.cs

@@ -1,25 +1,25 @@
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Provides data for <see cref="Renci.SshNet.PasswordConnectionInfo.PasswordExpired"/> event.
-    /// </summary>
-    public class AuthenticationPasswordChangeEventArgs : AuthenticationEventArgs
-    {
-        /// <summary>
-        /// Gets or sets the new password.
-        /// </summary>
-        /// <value>
-        /// The new password.
-        /// </value>
-        public byte[] NewPassword { get; set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="AuthenticationPasswordChangeEventArgs"/> class.
-        /// </summary>
-        /// <param name="username">The username.</param>
-        public AuthenticationPasswordChangeEventArgs(string username)
-            : base(username)
-        {
-        }
-    }
-}
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Provides data for <see cref="Renci.SshNet.PasswordConnectionInfo.PasswordExpired"/> event.
+    /// </summary>
+    public class AuthenticationPasswordChangeEventArgs : AuthenticationEventArgs
+    {
+        /// <summary>
+        /// Gets or sets the new password.
+        /// </summary>
+        /// <value>
+        /// The new password.
+        /// </value>
+        public byte[] NewPassword { get; set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AuthenticationPasswordChangeEventArgs"/> class.
+        /// </summary>
+        /// <param name="username">The username.</param>
+        public AuthenticationPasswordChangeEventArgs(string username)
+            : base(username)
+        {
+        }
+    }
+}

+ 47 - 47
src/Renci.SshNet/Common/AuthenticationPrompt.cs

@@ -1,47 +1,47 @@
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Provides prompt information when <see cref="Renci.SshNet.KeyboardInteractiveConnectionInfo.AuthenticationPrompt"/> is raised
-    /// </summary>
-    public class AuthenticationPrompt
-    {
-        /// <summary>
-        /// Gets the prompt sequence id.
-        /// </summary>
-        public int Id { get; private set; }
-
-        /// <summary>
-        /// Gets or sets a value indicating whether the user input should be echoed as characters are typed.
-        /// </summary>
-        /// <value>
-        ///   <c>true</c> if the user input should be echoed as characters are typed; otherwise, <c>false</c>.
-        /// </value>
-        public bool IsEchoed { get; private set; }
-
-        /// <summary>
-        /// Gets server information request.
-        /// </summary>
-        public string Request { get; private set; }
-
-        /// <summary>
-        /// Gets or sets server information response.
-        /// </summary>
-        /// <value>
-        /// The response.
-        /// </value>
-        public string Response { get; set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="AuthenticationPrompt"/> class.
-        /// </summary>
-        /// <param name="id">The sequence id.</param>
-        /// <param name="isEchoed">if set to <c>true</c> the user input should be echoed.</param>
-        /// <param name="request">The request.</param>
-        public AuthenticationPrompt(int id, bool isEchoed, string request)
-        {
-            Id = id;
-            IsEchoed = isEchoed;
-            Request = request;
-        }
-    }
-}
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Provides prompt information when <see cref="Renci.SshNet.KeyboardInteractiveConnectionInfo.AuthenticationPrompt"/> is raised
+    /// </summary>
+    public class AuthenticationPrompt
+    {
+        /// <summary>
+        /// Gets the prompt sequence id.
+        /// </summary>
+        public int Id { get; private set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether the user input should be echoed as characters are typed.
+        /// </summary>
+        /// <value>
+        ///   <c>true</c> if the user input should be echoed as characters are typed; otherwise, <c>false</c>.
+        /// </value>
+        public bool IsEchoed { get; private set; }
+
+        /// <summary>
+        /// Gets server information request.
+        /// </summary>
+        public string Request { get; private set; }
+
+        /// <summary>
+        /// Gets or sets server information response.
+        /// </summary>
+        /// <value>
+        /// The response.
+        /// </value>
+        public string Response { get; set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AuthenticationPrompt"/> class.
+        /// </summary>
+        /// <param name="id">The sequence id.</param>
+        /// <param name="isEchoed">if set to <c>true</c> the user input should be echoed.</param>
+        /// <param name="request">The request.</param>
+        public AuthenticationPrompt(int id, bool isEchoed, string request)
+        {
+            Id = id;
+            IsEchoed = isEchoed;
+            Request = request;
+        }
+    }
+}

+ 40 - 40
src/Renci.SshNet/Common/AuthenticationPromptEventArgs.cs

@@ -1,40 +1,40 @@
-using System.Collections.Generic;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Provides data for <see cref="Renci.SshNet.KeyboardInteractiveConnectionInfo.AuthenticationPrompt"/> event.
-    /// </summary>
-    public class AuthenticationPromptEventArgs : AuthenticationEventArgs
-    {
-        /// <summary>
-        /// Gets prompt language.
-        /// </summary>
-        public string Language { get; private set; }
-
-        /// <summary>
-        /// Gets prompt instruction.
-        /// </summary>
-        public string Instruction { get; private set; }
-
-        /// <summary>
-        /// Gets server information request prompts.
-        /// </summary>
-        public IEnumerable<AuthenticationPrompt> Prompts { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="AuthenticationPromptEventArgs"/> class.
-        /// </summary>
-        /// <param name="username">The username.</param>
-        /// <param name="instruction">The instruction.</param>
-        /// <param name="language">The language.</param>
-        /// <param name="prompts">The information request prompts.</param>
-        public AuthenticationPromptEventArgs(string username, string instruction, string language, IEnumerable<AuthenticationPrompt> prompts)
-            : base(username)
-        {
-            Instruction = instruction;
-            Language = language;
-            Prompts = prompts;
-        }
-    }
-}
+using System.Collections.Generic;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Provides data for <see cref="Renci.SshNet.KeyboardInteractiveConnectionInfo.AuthenticationPrompt"/> event.
+    /// </summary>
+    public class AuthenticationPromptEventArgs : AuthenticationEventArgs
+    {
+        /// <summary>
+        /// Gets prompt language.
+        /// </summary>
+        public string Language { get; private set; }
+
+        /// <summary>
+        /// Gets prompt instruction.
+        /// </summary>
+        public string Instruction { get; private set; }
+
+        /// <summary>
+        /// Gets server information request prompts.
+        /// </summary>
+        public IEnumerable<AuthenticationPrompt> Prompts { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AuthenticationPromptEventArgs"/> class.
+        /// </summary>
+        /// <param name="username">The username.</param>
+        /// <param name="instruction">The instruction.</param>
+        /// <param name="language">The language.</param>
+        /// <param name="prompts">The information request prompts.</param>
+        public AuthenticationPromptEventArgs(string username, string instruction, string language, IEnumerable<AuthenticationPrompt> prompts)
+            : base(username)
+        {
+            Instruction = instruction;
+            Language = language;
+            Prompts = prompts;
+        }
+    }
+}

+ 4225 - 4225
src/Renci.SshNet/Common/BigInteger.cs

@@ -1,4225 +1,4225 @@
-//
-// System.Numerics.BigInteger
-//
-// Authors:
-//	Rodrigo Kumpera (rkumpera@novell.com)
-//	Marek Safar  <marek.safar@gmail.com>
-//
-// Copyright (C) 2010 Novell, Inc (http://www.novell.com)
-// Copyright (C) 2014 Xamarin Inc (http://www.xamarin.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-// 
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-// 
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-// A big chuck of code comes the DLR (as hosted in http://ironpython.codeplex.com), 
-// which has the following License:
-//
-/* ****************************************************************************
-*
-* Copyright (c) Microsoft Corporation.
-*
-* This source code is subject to terms and conditions of the Microsoft Public License. A
-* copy of the license can be found in the License.html file at the root of this distribution. If
-* you cannot locate the Microsoft Public License, please send an email to
-* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
-* by the terms of the Microsoft Public License.
-*
-* You must not remove this notice, or any other, from this software.
-*
-*
-* ***************************************************************************/
-//
-// slashdocs based on MSDN
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Globalization;
-using Renci.SshNet.Security.Cryptography;
-
-/*
-Optimization
-	Have proper popcount function for IsPowerOfTwo
-	Use unsafe ops to avoid bounds check
-	CoreAdd could avoid some resizes by checking for equal sized array that top overflow
-	For bitwise operators, hoist the conditionals out of their main loop
-	Optimize BitScanBackward
-	Use a carry variable to make shift opts do half the number of array ops.
-	Schoolbook multiply is O(n^2), use Karatsuba /Toom-3 for large numbers
-*/
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Represents an arbitrarily large signed integer.
-    /// </summary>
-    [SuppressMessage("ReSharper", "EmptyEmbeddedStatement")]
-    [SuppressMessage("ReSharper", "RedundantCast")]
-    [SuppressMessage("ReSharper", "RedundantAssignment")]
-    [SuppressMessage("ReSharper", "SuggestBaseTypeForParameter")]
-    [SuppressMessage("ReSharper", "MergeConditionalExpression")]
-    public struct BigInteger : IComparable, IFormattable, IComparable<BigInteger>, IEquatable<BigInteger>
-    {
-        private static readonly BigInteger ZeroSingleton = new BigInteger(0);
-        private static readonly BigInteger OneSingleton = new BigInteger(1);
-        private static readonly BigInteger MinusOneSingleton = new BigInteger(-1);
-
-        private const ulong Base = 0x100000000;
-        private const int Bias = 1075;
-        private const int DecimalSignMask = unchecked((int) 0x80000000);
-
-        //LSB on [0]
-        private readonly uint[] _data;
-        private readonly short _sign;
-
-        #region SSH.NET additions
-
-        /// <summary>
-        /// Gets number of bits used by the number.
-        /// </summary>
-        /// <value>
-        /// The number of the bit used.
-        /// </value>
-        public int BitLength
-        {
-            get
-            {
-                if (_sign == 0)
-                    return 0;
-
-                var msbIndex = _data.Length - 1;
-
-                while (_data[msbIndex] == 0)
-                    msbIndex--;
-
-                var msbBitCount = BitScanBackward(_data[msbIndex]) + 1;
-
-                return msbIndex * 4 * 8 + msbBitCount + ((_sign > 0) ? 0 : 1);
-            }
-        }
-
-        /// <summary>
-        /// Mods the inverse.
-        /// </summary>
-        /// <param name="bi">The bi.</param>
-        /// <param name="modulus">The modulus.</param>
-        /// <returns>
-        /// Modulus inverted number.
-        /// </returns>
-        public static BigInteger ModInverse(BigInteger bi, BigInteger modulus)
-        {
-            BigInteger a = modulus, b = bi % modulus;
-            BigInteger p0 = 0, p1 = 1;
-
-            while (!b.IsZero)
-            {
-                if (b.IsOne)
-                    return p1;
-
-                p0 += (a / b) * p1;
-                a %= b;
-
-                if (a.IsZero)
-                    break;
-
-                if (a.IsOne)
-                    return modulus - p0;
-
-                p1 += (b / a) * p0;
-                b %= a;
-
-            }
-            return 0;
-        }
-
-        /// <summary>
-        /// Returns positive remainder that results from division with two specified <see cref="BigInteger"/> values.
-        /// </summary>
-        /// <param name="dividend">The value to be divided.</param>
-        /// <param name="divisor">The value to divide by.</param>
-        /// <returns>
-        /// Positive remainder that results from the division.
-        /// </returns>
-        public static BigInteger PositiveMod(BigInteger dividend, BigInteger divisor)
-        {
-            var result = dividend % divisor;
-            if (result < 0)
-                result += divisor;
-
-            return result;
-        }
-
-        /// <summary>
-        /// Generates random <see cref="BigInteger"/> number.
-        /// </summary>
-        /// <param name="bitLength">Length of random number in bits.</param>
-        /// <returns>
-        /// A random number.
-        /// </returns>
-        public static BigInteger Random(int bitLength)
-        {
-            var bytesArray = new byte[bitLength / 8 + (((bitLength % 8) > 0) ? 1 : 0)];
-            HashAlgorithmFactory.GenerateRandom(bytesArray);
-            bytesArray[bytesArray.Length - 1] = (byte)(bytesArray[bytesArray.Length - 1] & 0x7F);   //  Ensure not a negative value
-            return new BigInteger(bytesArray);
-        }
-
-        #endregion SSH.NET additions
-
-        private BigInteger(short sign, uint[] data)
-        {
-            _sign = sign;
-            _data = data;
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BigInteger"/> structure using a 32-bit signed integer value.
-        /// </summary>
-        /// <param name="value">A 32-bit signed integer.</param>
-        public BigInteger(int value)
-        {
-            if (value == 0)
-            {
-                _sign = 0;
-                _data = null;
-            }
-            else if (value > 0)
-            {
-                _sign = 1;
-                _data = new[] {(uint) value};
-            }
-            else
-            {
-                _sign = -1;
-                _data = new[] {(uint) -value};
-            }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BigInteger"/> structure using an unsigned 32-bit integer value.
-        /// </summary>
-        /// <param name="value">An unsigned 32-bit integer value.</param>
-        [CLSCompliant(false)]
-        public BigInteger(uint value)
-        {
-            if (value == 0)
-            {
-                _sign = 0;
-                _data = null;
-            }
-            else
-            {
-                _sign = 1;
-                _data = new[] { value };
-            }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BigInteger"/> structure using a 64-bit signed integer value.
-        /// </summary>
-        /// <param name="value">A 64-bit signed integer.</param>
-        public BigInteger(long value)
-        {
-            if (value == 0)
-            {
-                _sign = 0;
-                _data = null;
-            }
-            else if (value > 0)
-            {
-                _sign = 1;
-                var low = (uint)value;
-                var high = (uint)(value >> 32);
-
-                _data = new uint[high != 0 ? 2 : 1];
-                _data[0] = low;
-                if (high != 0)
-                    _data[1] = high;
-            }
-            else
-            {
-                _sign = -1;
-                value = -value;
-                var low = (uint)value;
-                var high = (uint)((ulong)value >> 32);
-
-                _data = new uint[high != 0 ? 2 : 1];
-                _data[0] = low;
-                if (high != 0)
-                    _data[1] = high;
-            }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BigInteger"/> structure with an unsigned 64-bit integer value.
-        /// </summary>
-        /// <param name="value">An unsigned 64-bit integer.</param>
-        [CLSCompliant(false)]
-        public BigInteger(ulong value)
-        {
-            if (value == 0)
-            {
-                _sign = 0;
-                _data = null;
-            }
-            else
-            {
-                _sign = 1;
-                var low = (uint)value;
-                var high = (uint)(value >> 32);
-
-                _data = new uint[high != 0 ? 2 : 1];
-                _data[0] = low;
-                if (high != 0)
-                    _data[1] = high;
-            }
-        }
-
-        private static bool Negative(byte[] v)
-        {
-            return ((v[7] & 0x80) != 0);
-        }
-
-        private static ushort Exponent(byte[] v)
-        {
-            return (ushort)((((ushort)(v[7] & 0x7F)) << (ushort)4) | (((ushort)(v[6] & 0xF0)) >> 4));
-        }
-
-        private static ulong Mantissa(byte[] v)
-        {
-            var i1 = ((uint)v[0] | ((uint)v[1] << 8) | ((uint)v[2] << 16) | ((uint)v[3] << 24));
-            var i2 = ((uint)v[4] | ((uint)v[5] << 8) | ((uint)(v[6] & 0xF) << 16));
-
-            return (ulong)((ulong)i1 | ((ulong)i2 << 32));
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BigInteger"/> structure using a double-precision floating-point value.
-        /// </summary>
-        /// <param name="value">A double-precision floating-point value.</param>
-        public BigInteger(double value)
-        {
-            if (double.IsNaN(value) || double.IsInfinity(value))
-                throw new OverflowException();
-
-            var bytes = BitConverter.GetBytes(value);
-            var mantissa = Mantissa(bytes);
-            if (mantissa == 0)
-            {
-                // 1.0 * 2**exp, we have a power of 2
-                int exponent = Exponent(bytes);
-                if (exponent == 0)
-                {
-                    _sign = 0;
-                    _data = null;
-                    return;
-                }
-
-                var res = Negative(bytes) ? MinusOne : One;
-                res = res << (exponent - 0x3ff);
-                _sign = res._sign;
-                _data = res._data;
-            }
-            else
-            {
-                // 1.mantissa * 2**exp
-                int exponent = Exponent(bytes);
-                mantissa |= 0x10000000000000ul;
-                BigInteger res = mantissa;
-                res = exponent > Bias ? res << (exponent - Bias) : res >> (Bias - exponent);
-
-                _sign = (short)(Negative(bytes) ? -1 : 1);
-                _data = res._data;
-            }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BigInteger"/> structure using a single-precision floating-point value.
-        /// </summary>
-        /// <param name="value">A single-precision floating-point value.</param>
-        public BigInteger(float value) : this((double)value)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BigInteger"/> structure using a <see cref="decimal"/> value.
-        /// </summary>
-        /// <param name="value">A decimal number.</param>
-        public BigInteger(decimal value)
-        {
-            // First truncate to get scale to 0 and extract bits
-            var bits = decimal.GetBits(decimal.Truncate(value));
-
-            var size = 3;
-            while (size > 0 && bits[size - 1] == 0) size--;
-
-            if (size == 0)
-            {
-                _sign = 0;
-                _data = null;
-                return;
-            }
-
-            _sign = (short)((bits[3] & DecimalSignMask) != 0 ? -1 : 1);
-
-            _data = new uint[size];
-            _data[0] = (uint)bits[0];
-            if (size > 1)
-                _data[1] = (uint)bits[1];
-            if (size > 2)
-                _data[2] = (uint)bits[2];
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BigInteger"/> structure using the values in a byte array.
-        /// </summary>
-        /// <param name="value">An array of <see cref="byte"/> values in little-endian order.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c>.</exception>
-        [CLSCompliant(false)]
-        public BigInteger(byte[] value)
-        {
-            if (value == null)
-                throw new ArgumentNullException("value");
-
-            var len = value.Length;
-
-            if (len == 0 || (len == 1 && value[0] == 0))
-            {
-                _sign = 0;
-                _data = null;
-                return;
-            }
-
-            if ((value[len - 1] & 0x80) != 0)
-                _sign = -1;
-            else
-                _sign = 1;
-
-            if (_sign == 1)
-            {
-                while (value[len - 1] == 0)
-                {
-                    if (--len == 0)
-                    {
-                        _sign = 0;
-                        _data = null;
-                        return;
-                    }
-                }
-
-                int size;
-                var fullWords = size = len / 4;
-                if ((len & 0x3) != 0)
-                    ++size;
-
-                _data = new uint[size];
-                var j = 0;
-                for (var i = 0; i < fullWords; ++i)
-                {
-                    _data[i] = (uint) value[j++] |
-                               (uint) (value[j++] << 8) |
-                               (uint) (value[j++] << 16) |
-                               (uint) (value[j++] << 24);
-                }
-                size = len & 0x3;
-                if (size > 0)
-                {
-                    var idx = _data.Length - 1;
-                    for (var i = 0; i < size; ++i)
-                        _data[idx] |= (uint)(value[j++] << (i * 8));
-                }
-            }
-            else
-            {
-                int size;
-                var fullWords = size = len / 4;
-                if ((len & 0x3) != 0)
-                    ++size;
-
-                _data = new uint[size];
-
-                uint word, borrow = 1;
-                ulong sub;
-                var j = 0;
-
-                for (var i = 0; i < fullWords; ++i)
-                {
-                    word = (uint) value[j++] |
-                           (uint) (value[j++] << 8) |
-                           (uint) (value[j++] << 16) |
-                           (uint) (value[j++] << 24);
-
-                    sub = (ulong)word - borrow;
-                    word = (uint)sub;
-                    borrow = (uint)(sub >> 32) & 0x1u;
-                    _data[i] = ~word;
-                }
-                size = len & 0x3;
-
-                if (size > 0)
-                {
-                    word = 0;
-                    uint storeMask = 0;
-                    for (var i = 0; i < size; ++i)
-                    {
-                        word |= (uint)(value[j++] << (i * 8));
-                        storeMask = (storeMask << 8) | 0xFF;
-                    }
-
-                    sub = word - borrow;
-                    word = (uint)sub;
-                    borrow = (uint)(sub >> 32) & 0x1u;
-
-                    if ((~word & storeMask) == 0)
-                        Array.Resize(ref _data, _data.Length - 1);
-                    else
-                        _data[_data.Length - 1] = ~word & storeMask;
-                }
-                if (borrow != 0) //FIXME I believe this can't happen, can someone write a test for it?
-                    throw new Exception("non zero final carry");
-            }
-        }
-
-        /// <summary>
-        /// Indicates whether the value of the current <see cref="BigInteger"/> object is an even number.
-        /// </summary>
-        /// <value>
-        /// <c>true</c> if the value of the BigInteger object is an even number; otherwise, <c>false</c>.
-        /// </value>
-        public bool IsEven
-        {
-            get { return _sign == 0 || (_data[0] & 0x1) == 0; }
-        }
-
-        /// <summary>
-        /// Indicates whether the value of the current <see cref="BigInteger"/> object is <see cref="One"/>.
-        /// </summary>
-        /// <value>
-        /// <c>true</c> if the value of the <see cref="BigInteger"/> object is <see cref="One"/>;
-        /// otherwise, <c>false</c>.
-        /// </value>
-        public bool IsOne
-        {
-            get { return _sign == 1 && _data.Length == 1 && _data[0] == 1; }
-        }
-
-
-        //Gem from Hacker's Delight
-        //Returns the number of bits set in @x
-        static int PopulationCount(uint x)
-        {
-            x = x - ((x >> 1) & 0x55555555);
-            x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
-            x = (x + (x >> 4)) & 0x0F0F0F0F;
-            x = x + (x >> 8);
-            x = x + (x >> 16);
-            return (int)(x & 0x0000003F);
-        }
-
-        //Based on code by Zilong Tan on Ulib released under MIT license
-        //Returns the number of bits set in @x
-        static int PopulationCount(ulong x)
-        {
-            x -= (x >> 1) & 0x5555555555555555UL;
-            x = (x & 0x3333333333333333UL) + ((x >> 2) & 0x3333333333333333UL);
-            x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0fUL;
-            return (int)((x * 0x0101010101010101UL) >> 56);
-        }
-
-        static int LeadingZeroCount(uint value)
-        {
-            value |= value >> 1;
-            value |= value >> 2;
-            value |= value >> 4;
-            value |= value >> 8;
-            value |= value >> 16;
-            return 32 - PopulationCount(value); // 32 = bits in uint
-        }
-
-        static int LeadingZeroCount(ulong value)
-        {
-            value |= value >> 1;
-            value |= value >> 2;
-            value |= value >> 4;
-            value |= value >> 8;
-            value |= value >> 16;
-            value |= value >> 32;
-            return 64 - PopulationCount(value); // 64 = bits in ulong
-        }
-
-        static double BuildDouble(int sign, ulong mantissa, int exponent)
-        {
-            const int exponentBias = 1023;
-            const int mantissaLength = 52;
-            const int exponentLength = 11;
-            const int maxExponent = 2046;
-            const long mantissaMask = 0xfffffffffffffL;
-            const long exponentMask = 0x7ffL;
-            const ulong negativeMark = 0x8000000000000000uL;
-
-            if (sign == 0 || mantissa == 0)
-            {
-                return 0.0;
-            }
-
-            exponent += exponentBias + mantissaLength;
-            var offset = LeadingZeroCount(mantissa) - exponentLength;
-            if (exponent - offset > maxExponent)
-            {
-                return sign > 0 ? double.PositiveInfinity : double.NegativeInfinity;
-            }
-            if (offset < 0)
-            {
-                mantissa >>= -offset;
-                exponent += -offset;
-            }
-            else if (offset >= exponent)
-            {
-                mantissa <<= exponent - 1;
-                exponent = 0;
-            }
-            else
-            {
-                mantissa <<= offset;
-                exponent -= offset;
-            }
-            mantissa = mantissa & mantissaMask;
-            if ((exponent & exponentMask) == exponent)
-            {
-                unchecked
-                {
-                    var bits = mantissa | ((ulong)exponent << mantissaLength);
-                    if (sign < 0)
-                    {
-                        bits |= negativeMark;
-                    }
-                    return BitConverter.Int64BitsToDouble((long)bits);
-                }
-            }
-            return sign > 0 ? double.PositiveInfinity : double.NegativeInfinity;
-        }
-
-        /// <summary>
-        /// Indicates whether the value of the current <see cref="BigInteger"/> object is a power of two.
-        /// </summary>
-        /// <value>
-        /// <c>true</c> if the value of the <see cref="BigInteger"/> object is a power of two;
-        /// otherwise, <c>false</c>.
-        /// </value>
-        public bool IsPowerOfTwo
-        {
-            get
-            {
-                var foundBit = false;
-                if (_sign != 1)
-                    return false;
-                //This function is pop count == 1 for positive numbers
-                foreach (var bit in _data)
-                {
-                    var p = PopulationCount(bit);
-                    if (p > 0)
-                    {
-                        if (p > 1 || foundBit)
-                            return false;
-                        foundBit = true;
-                    }
-                }
-                return foundBit;
-            }
-        }
-
-        /// <summary>
-        /// Indicates whether the value of the current <see cref="BigInteger"/> object is <see cref="Zero"/>.
-        /// </summary>
-        /// <value>
-        /// <c>true</c> if the value of the <see cref="BigInteger"/> object is <see cref="Zero"/>;
-        /// otherwise, <c>false</c>.
-        /// </value>
-        public bool IsZero
-        {
-            get { return _sign == 0; }
-        }
-
-        /// <summary>
-        /// Gets a number that indicates the sign (negative, positive, or zero) of the current <see cref="BigInteger"/> object.
-        /// </summary>
-        /// <value>
-        /// A number that indicates the sign of the <see cref="BigInteger"/> object.
-        /// </value>
-        public int Sign
-        {
-            get { return _sign; }
-        }
-
-        /// <summary>
-        /// Gets a value that represents the number negative one (-1).
-        /// </summary>
-        /// <value>
-        /// An integer whose value is negative one (-1).
-        /// </value>
-        public static BigInteger MinusOne
-        {
-            get { return MinusOneSingleton; }
-        }
-
-        /// <summary>
-        /// Gets a value that represents the number one (1).
-        /// </summary>
-        /// <value>
-        /// An object whose value is one (1).
-        /// </value>
-        public static BigInteger One
-        {
-            get { return OneSingleton; }
-        }
-
-        /// <summary>
-        /// Gets a value that represents the number 0 (zero).
-        /// </summary>
-        /// <value>
-        /// An integer whose value is 0 (zero).
-        /// </value>
-        public static BigInteger Zero
-        {
-            get { return ZeroSingleton; }
-        }
-
-        /// <summary>
-        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a 32-bit signed integer value.
-        /// </summary>
-        /// <param name="value">The value to convert to a 32-bit signed integer.</param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        public static explicit operator int(BigInteger value)
-        {
-            if (value._data == null)
-                return 0;
-            if (value._data.Length > 1)
-                throw new OverflowException();
-            var data = value._data[0];
-
-            if (value._sign == 1)
-            {
-                if (data > (uint)int.MaxValue)
-                    throw new OverflowException();
-                return (int)data;
-            }
-            if (value._sign == -1)
-            {
-                if (data > 0x80000000u)
-                    throw new OverflowException();
-                return -(int)data;
-            }
-
-            return 0;
-        }
-
-        /// <summary>
-        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to an unsigned 32-bit integer value.
-        /// </summary>
-        /// <param name="value">The value to convert to an unsigned 32-bit integer.</param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        [CLSCompliant(false)]
-        public static explicit operator uint(BigInteger value)
-        {
-            if (value._data == null)
-                return 0;
-            if (value._data.Length > 1 || value._sign == -1)
-                throw new OverflowException();
-            return value._data[0];
-        }
-
-        /// <summary>
-        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a 16-bit signed integer value.
-        /// </summary>
-        /// <param name="value">The value to convert to a 16-bit signed integer.</param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        public static explicit operator short(BigInteger value)
-        {
-            var val = (int)value;
-            if (val < short.MinValue || val > short.MaxValue)
-                throw new OverflowException();
-            return (short)val;
-        }
-
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="value"></param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        [CLSCompliantAttribute(false)]
-        public static explicit operator ushort(BigInteger value)
-        {
-            var val = (uint)value;
-            if (val > ushort.MaxValue)
-                throw new OverflowException();
-            return (ushort)val;
-        }
-
-        /// <summary>
-        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to an unsigned byte value.
-        /// </summary>
-        /// <param name="value">The value to convert to a <see cref="byte"/>.</param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        public static explicit operator byte(BigInteger value)
-        {
-            var val = (uint)value;
-            if (val > byte.MaxValue)
-                throw new OverflowException();
-            return (byte)val;
-        }
-
-        /// <summary>
-        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a signed 8-bit value.
-        /// </summary>
-        /// <param name="value">The value to convert to a signed 8-bit value.</param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        [CLSCompliant(false)]
-        public static explicit operator sbyte(BigInteger value)
-        {
-            var val = (int)value;
-            if (val < sbyte.MinValue || val > sbyte.MaxValue)
-                throw new OverflowException();
-            return (sbyte)val;
-        }
-
-        /// <summary>
-        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a 64-bit signed integer value.
-        /// </summary>
-        /// <param name="value">The value to convert to a 64-bit signed integer.</param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        public static explicit operator long(BigInteger value)
-        {
-            if (value._data == null)
-                return 0;
-
-            if (value._data.Length > 2)
-                throw new OverflowException();
-
-            var low = value._data[0];
-
-            if (value._data.Length == 1)
-            {
-                if (value._sign == 1)
-                    return (long)low;
-                var res = (long)low;
-                return -res;
-            }
-
-            var high = value._data[1];
-
-            if (value._sign == 1)
-            {
-                if (high >= 0x80000000u)
-                    throw new OverflowException();
-                return (((long)high) << 32) | low;
-            }
-
-            /*
-            We cannot represent negative numbers smaller than long.MinValue.
-            Those values are encoded into what look negative numbers, so negating
-            them produces a positive value, that's why it's safe to check for that
-            condition.
-
-            long.MinValue works fine since it's bigint encoding looks like a negative
-            number, but since long.MinValue == -long.MinValue, we're good.
-            */
-
-            var result = -((((long)high) << 32) | (long)low);
-            if (result > 0)
-                throw new OverflowException();
-            return result;
-        }
-
-        /// <summary>
-        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to an unsigned 64-bit integer value.
-        /// </summary>
-        /// <param name="value">The value to convert to an unsigned 64-bit integer.</param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        [CLSCompliant(false)]
-        public static explicit operator ulong(BigInteger value)
-        {
-            if (value._data == null)
-                return 0;
-            if (value._data.Length > 2 || value._sign == -1)
-                throw new OverflowException();
-
-            var low = value._data[0];
-            if (value._data.Length == 1)
-                return low;
-
-            var high = value._data[1];
-            return (((ulong)high) << 32) | low;
-        }
-
-        /// <summary>
-        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a <see cref="double"/> value.
-        /// </summary>
-        /// <param name="value">The value to convert to a <see cref="double"/>.</param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        public static explicit operator double(BigInteger value)
-        {
-            if (value._data == null)
-                return 0.0;
-
-            switch (value._data.Length)
-            {
-                case 1:
-                    return BuildDouble(value._sign, value._data[0], 0);
-                case 2:
-                    return BuildDouble(value._sign, (ulong)value._data[1] << 32 | (ulong)value._data[0], 0);
-                default:
-                    var index = value._data.Length - 1;
-                    var word = value._data[index];
-                    var mantissa = ((ulong)word << 32) | value._data[index - 1];
-                    var missing = LeadingZeroCount(word) - 11; // 11 = bits in exponent
-                    if (missing > 0)
-                    {
-                        // add the missing bits from the next word
-                        mantissa = (mantissa << missing) | (value._data[index - 2] >> (32 - missing));
-                    }
-                    else
-                    {
-                        mantissa >>= -missing;
-                    }
-                    return BuildDouble(value._sign, mantissa, ((value._data.Length - 2) * 32) - missing);
-            }
-        }
-
-        /// <summary>
-        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a single-precision floating-point value.
-        /// </summary>
-        /// <param name="value">The value to convert to a single-precision floating-point value.</param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        public static explicit operator float(BigInteger value)
-        {
-            return (float)(double)value;
-        }
-
-        /// <summary>
-        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a <see cref="decimal"/> value.
-        /// </summary>
-        /// <param name="value">The value to convert to a <see cref="decimal"/>.</param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        public static explicit operator decimal(BigInteger value)
-        {
-            if (value._data == null)
-                return decimal.Zero;
-
-            var data = value._data;
-            if (data.Length > 3)
-                throw new OverflowException();
-
-            int lo = 0, mi = 0, hi = 0;
-            if (data.Length > 2)
-                hi = (int)data[2];
-            if (data.Length > 1)
-                mi = (int)data[1];
-            if (data.Length > 0)
-                lo = (int)data[0];
-
-            return new decimal(lo, mi, hi, value._sign < 0, 0);
-        }
-
-        /// <summary>
-        /// Defines an implicit conversion of a signed 32-bit integer to a <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        public static implicit operator BigInteger(int value)
-        {
-            return new BigInteger(value);
-        }
-
-        /// <summary>
-        /// Defines an implicit conversion of a 32-bit unsigned integer to a <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        [CLSCompliant(false)]
-        public static implicit operator BigInteger(uint value)
-        {
-            return new BigInteger(value);
-        }
-
-        /// <summary>
-        /// Defines an implicit conversion of a signed 16-bit integer to a BigInteger value.
-        /// </summary>
-        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        public static implicit operator BigInteger(short value)
-        {
-            return new BigInteger(value);
-        }
-
-        /// <summary>
-        /// Defines an implicit conversion of a 16-bit unsigned integer to a <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        [CLSCompliantAttribute(false)]
-        public static implicit operator BigInteger(ushort value)
-        {
-            return new BigInteger(value);
-        }
-
-        /// <summary>
-        /// Defines an implicit conversion of an unsigned byte to a <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        public static implicit operator BigInteger(byte value)
-        {
-            return new BigInteger(value);
-        }
-
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        [CLSCompliant(false)]
-        public static implicit operator BigInteger(sbyte value)
-        {
-            return new BigInteger(value);
-        }
-
-        /// <summary>
-        /// Defines an implicit conversion of a signed 64-bit integer to a <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        public static implicit operator BigInteger(long value)
-        {
-            return new BigInteger(value);
-        }
-
-        /// <summary>
-        /// Defines an implicit conversion of a 64-bit unsigned integer to a <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        [CLSCompliant(false)]
-        public static implicit operator BigInteger(ulong value)
-        {
-            return new BigInteger(value);
-        }
-
-        /// <summary>
-        /// Defines an explicit conversion of a <see cref="double"/> value to a <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        public static explicit operator BigInteger(double value)
-        {
-            return new BigInteger(value);
-        }
-
-        /// <summary>
-        /// Defines an explicit conversion of a <see cref="float"/> object to a <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        public static explicit operator BigInteger(float value)
-        {
-            return new BigInteger(value);
-        }
-
-        /// <summary>
-        /// Defines an explicit conversion of a <see cref="decimal"/> object to a <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
-        /// <returns>
-        /// An object that contains the value of the <paramref name="value"/> parameter.
-        /// </returns>
-        public static explicit operator BigInteger(decimal value)
-        {
-            return new BigInteger(value);
-        }
-
-        /// <summary>
-        /// Adds the values of two specified <see cref="BigInteger"/> objects.
-        /// </summary>
-        /// <param name="left">The first value to add.</param>
-        /// <param name="right">The second value to add.</param>
-        /// <returns>
-        /// The sum of <paramref name="left"/> and <paramref name="right"/>.
-        /// </returns>
-        public static BigInteger operator +(BigInteger left, BigInteger right)
-        {
-            if (left._sign == 0)
-                return right;
-            if (right._sign == 0)
-                return left;
-
-            if (left._sign == right._sign)
-                return new BigInteger(left._sign, CoreAdd(left._data, right._data));
-
-            var r = CoreCompare(left._data, right._data);
-
-            if (r == 0)
-                return Zero;
-
-            if (r > 0) //left > right
-                return new BigInteger(left._sign, CoreSub(left._data, right._data));
-
-            return new BigInteger(right._sign, CoreSub(right._data, left._data));
-        }
-
-        /// <summary>
-        /// Subtracts a <see cref="BigInteger"/> value from another <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="left">The value to subtract from (the minuend).</param>
-        /// <param name="right">The value to subtract (the subtrahend).</param>
-        /// <returns>
-        /// The result of subtracting <paramref name="right"/> from <paramref name="left"/>.
-        /// </returns>
-        public static BigInteger operator -(BigInteger left, BigInteger right)
-        {
-            if (right._sign == 0)
-                return left;
-            if (left._sign == 0)
-                return new BigInteger((short)-right._sign, right._data);
-
-            if (left._sign == right._sign)
-            {
-                var r = CoreCompare(left._data, right._data);
-
-                if (r == 0)
-                    return Zero;
-
-                if (r > 0) //left > right
-                    return new BigInteger(left._sign, CoreSub(left._data, right._data));
-
-                return new BigInteger((short)-right._sign, CoreSub(right._data, left._data));
-            }
-
-            return new BigInteger(left._sign, CoreAdd(left._data, right._data));
-        }
-
-        /// <summary>
-        /// Multiplies two specified <see cref="BigInteger"/> values.
-        /// </summary>
-        /// <param name="left">The first value to multiply.</param>
-        /// <param name="right">The second value to multiply.</param>
-        /// <returns>
-        /// The product of left and right.
-        /// </returns>
-        public static BigInteger operator *(BigInteger left, BigInteger right)
-        {
-            if (left._sign == 0 || right._sign == 0)
-                return Zero;
-
-            if (left._data[0] == 1 && left._data.Length == 1)
-            {
-                if (left._sign == 1)
-                    return right;
-                return new BigInteger((short)-right._sign, right._data);
-            }
-
-            if (right._data[0] == 1 && right._data.Length == 1)
-            {
-                if (right._sign == 1)
-                    return left;
-                return new BigInteger((short)-left._sign, left._data);
-            }
-
-            var a = left._data;
-            var b = right._data;
-
-            var res = new uint[a.Length + b.Length];
-
-            for (var i = 0; i < a.Length; ++i)
-            {
-                var ai = a[i];
-                var k = i;
-
-                ulong carry = 0;
-                for (var j = 0; j < b.Length; ++j)
-                {
-                    carry = carry + ((ulong)ai) * b[j] + res[k];
-                    res[k++] = (uint)carry;
-                    carry >>= 32;
-                }
-
-                while (carry != 0)
-                {
-                    carry += res[k];
-                    res[k++] = (uint)carry;
-                    carry >>= 32;
-                }
-            }
-
-            int m;
-            for (m = res.Length - 1; m >= 0 && res[m] == 0; --m) ;
-            if (m < res.Length - 1)
-                Array.Resize(ref res, m + 1);
-
-            return new BigInteger((short) (left._sign*right._sign), res);
-        }
-
-        /// <summary>
-        /// Divides a specified <see cref="BigInteger"/> value by another specified <see cref="BigInteger"/> value by using
-        /// integer division.
-        /// </summary>
-        /// <param name="dividend">The value to be divided.</param>
-        /// <param name="divisor">The value to divide by.</param>
-        /// <returns>
-        /// The integral result of the division.
-        /// </returns>
-        public static BigInteger operator /(BigInteger dividend, BigInteger divisor)
-        {
-            if (divisor._sign == 0)
-                throw new DivideByZeroException();
-
-            if (dividend._sign == 0)
-                return dividend;
-
-            uint[] quotient;
-            uint[] remainderValue;
-
-            DivModUnsigned(dividend._data, divisor._data, out quotient, out remainderValue);
-
-            int i;
-            for (i = quotient.Length - 1; i >= 0 && quotient[i] == 0; --i) ;
-            if (i == -1)
-                return Zero;
-            if (i < quotient.Length - 1)
-                Array.Resize(ref quotient, i + 1);
-
-            return new BigInteger((short)(dividend._sign * divisor._sign), quotient);
-        }
-
-        /// <summary>
-        /// Returns the remainder that results from division with two specified <see cref="BigInteger"/> values.
-        /// </summary>
-        /// <param name="dividend">The value to be divided.</param>
-        /// <param name="divisor">The value to divide by.</param>
-        /// <returns>
-        /// The remainder that results from the division.
-        /// </returns>
-        public static BigInteger operator %(BigInteger dividend, BigInteger divisor)
-        {
-            if (divisor._sign == 0)
-                throw new DivideByZeroException();
-
-            if (dividend._sign == 0)
-                return dividend;
-
-            uint[] quotient;
-            uint[] remainderValue;
-
-            DivModUnsigned(dividend._data, divisor._data, out quotient, out remainderValue);
-
-            int i;
-            for (i = remainderValue.Length - 1; i >= 0 && remainderValue[i] == 0; --i) ;
-            if (i == -1)
-                return Zero;
-
-            if (i < remainderValue.Length - 1)
-                Array.Resize(ref remainderValue, i + 1);
-            return new BigInteger(dividend._sign, remainderValue);
-        }
-
-        /// <summary>
-        /// Negates a specified <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="value">The value to negate.</param>
-        ///  <returns>
-        /// The result of the <paramref name="value"/> parameter multiplied by negative one (-1).
-        /// </returns>
-        public static BigInteger operator -(BigInteger value)
-        {
-            if (value._data == null)
-                return value;
-            return new BigInteger((short)-value._sign, value._data);
-        }
-
-        /// <summary>
-        /// Returns the value of the <see cref="BigInteger"/> operand.
-        /// </summary>
-        /// <param name="value">An integer value.</param>
-        /// <returns>
-        /// The value of the <paramref name="value"/> operand.
-        /// </returns>
-        /// <remarks>
-        /// The sign of the operand is unchanged.
-        /// </remarks>
-        public static BigInteger operator +(BigInteger value)
-        {
-            return value;
-        }
-
-        /// <summary>
-        /// Increments a <see cref="BigInteger"/> value by 1.
-        /// </summary>
-        /// <param name="value">The value to increment.</param>
-        /// <returns>
-        /// The value of the <paramref name="value"/> parameter incremented by 1.
-        /// </returns>
-        public static BigInteger operator ++(BigInteger value)
-        {
-            if (value._data == null)
-                return One;
-
-            var sign = value._sign;
-            var data = value._data;
-            if (data.Length == 1)
-            {
-                if (sign == -1 && data[0] == 1)
-                    return Zero;
-                if (sign == 0)
-                    return One;
-            }
-
-            data = sign == -1 ? CoreSub(data, 1) : CoreAdd(data, 1);
-
-            return new BigInteger(sign, data);
-        }
-
-        /// <summary>
-        /// Decrements a <see cref="BigInteger"/> value by 1.
-        /// </summary>
-        /// <param name="value">The value to decrement.</param>
-        /// <returns>
-        /// The value of the <paramref name="value"/> parameter decremented by 1.
-        /// </returns>
-        public static BigInteger operator --(BigInteger value)
-        {
-            if (value._data == null)
-                return MinusOne;
-
-            var sign = value._sign;
-            var data = value._data;
-            if (data.Length == 1)
-            {
-                if (sign == 1 && data[0] == 1)
-                    return Zero;
-                if (sign == 0)
-                    return MinusOne;
-            }
-
-            data = sign == -1 ? CoreAdd(data, 1) : CoreSub(data, 1);
-
-            return new BigInteger(sign, data);
-        }
-
-        /// <summary>
-        /// Performs a bitwise <c>And</c> operation on two <see cref="BigInteger"/> values.
-        /// </summary>
-        /// <param name="left">The first value.</param>
-        /// <param name="right">The second value.</param>
-        /// <returns>
-        /// The result of the bitwise <c>And</c> operation.
-        /// </returns>
-        public static BigInteger operator &(BigInteger left, BigInteger right)
-        {
-            if (left._sign == 0)
-                return left;
-
-            if (right._sign == 0)
-                return right;
-
-            var a = left._data;
-            var b = right._data;
-            int ls = left._sign;
-            int rs = right._sign;
-
-            var negRes = (ls == rs) && (ls == -1);
-
-            var result = new uint[Math.Max(a.Length, b.Length)];
-
-            ulong ac = 1, bc = 1, borrow = 1;
-
-            int i;
-            for (i = 0; i < result.Length; ++i)
-            {
-                uint va = 0;
-                if (i < a.Length)
-                    va = a[i];
-                if (ls == -1)
-                {
-                    ac = ~va + ac;
-                    va = (uint)ac;
-                    ac = (uint)(ac >> 32);
-                }
-
-                uint vb = 0;
-                if (i < b.Length)
-                    vb = b[i];
-                if (rs == -1)
-                {
-                    bc = ~vb + bc;
-                    vb = (uint)bc;
-                    bc = (uint)(bc >> 32);
-                }
-
-                var word = va & vb;
-
-                if (negRes)
-                {
-                    borrow = word - borrow;
-                    word = ~(uint)borrow;
-                    borrow = (uint)(borrow >> 32) & 0x1u;
-                }
-
-                result[i] = word;
-            }
-
-            for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) ;
-            if (i == -1)
-                return Zero;
-
-            if (i < result.Length - 1)
-                Array.Resize(ref result, i + 1);
-
-            return new BigInteger(negRes ? (short)-1 : (short)1, result);
-        }
-
-        /// <summary>
-        /// Performs a bitwise <c>Or</c> operation on two <see cref="BigInteger"/> values.
-        /// </summary>
-        /// <param name="left">The first value.</param>
-        /// <param name="right">The second value.</param>
-        /// <returns>
-        /// The result of the bitwise <c>Or</c> operation.
-        /// </returns>
-        public static BigInteger operator |(BigInteger left, BigInteger right)
-        {
-            if (left._sign == 0)
-                return right;
-
-            if (right._sign == 0)
-                return left;
-
-            var a = left._data;
-            var b = right._data;
-            int ls = left._sign;
-            int rs = right._sign;
-
-            var negRes = (ls == -1) || (rs == -1);
-
-            var result = new uint[Math.Max(a.Length, b.Length)];
-
-            ulong ac = 1, bc = 1, borrow = 1;
-
-            int i;
-            for (i = 0; i < result.Length; ++i)
-            {
-                uint va = 0;
-                if (i < a.Length)
-                    va = a[i];
-                if (ls == -1)
-                {
-                    ac = ~va + ac;
-                    va = (uint)ac;
-                    ac = (uint)(ac >> 32);
-                }
-
-                uint vb = 0;
-                if (i < b.Length)
-                    vb = b[i];
-                if (rs == -1)
-                {
-                    bc = ~vb + bc;
-                    vb = (uint)bc;
-                    bc = (uint)(bc >> 32);
-                }
-
-                var word = va | vb;
-
-                if (negRes)
-                {
-                    borrow = word - borrow;
-                    word = ~(uint)borrow;
-                    borrow = (uint)(borrow >> 32) & 0x1u;
-                }
-
-                result[i] = word;
-            }
-
-            for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) ;
-            if (i == -1)
-                return Zero;
-
-            if (i < result.Length - 1)
-                Array.Resize(ref result, i + 1);
-
-            return new BigInteger(negRes ? (short)-1 : (short)1, result);
-        }
-
-        /// <summary>
-        /// Performs a bitwise exclusive <c>Or</c> (<c>XOr</c>) operation on two <see cref="BigInteger"/> values.
-        /// </summary>
-        /// <param name="left">The first value.</param>
-        /// <param name="right">The second value.</param>
-        /// <returns>
-        /// The result of the bitwise <c>Or</c> operation.
-        /// </returns>
-        public static BigInteger operator ^(BigInteger left, BigInteger right)
-        {
-            if (left._sign == 0)
-                return right;
-
-            if (right._sign == 0)
-                return left;
-
-            var a = left._data;
-            var b = right._data;
-            int ls = left._sign;
-            int rs = right._sign;
-
-            var negRes = (ls == -1) ^ (rs == -1);
-
-            var result = new uint[Math.Max(a.Length, b.Length)];
-
-            ulong ac = 1, bc = 1, borrow = 1;
-
-            int i;
-            for (i = 0; i < result.Length; ++i)
-            {
-                uint va = 0;
-                if (i < a.Length)
-                    va = a[i];
-                if (ls == -1)
-                {
-                    ac = ~va + ac;
-                    va = (uint)ac;
-                    ac = (uint)(ac >> 32);
-                }
-
-                uint vb = 0;
-                if (i < b.Length)
-                    vb = b[i];
-                if (rs == -1)
-                {
-                    bc = ~vb + bc;
-                    vb = (uint)bc;
-                    bc = (uint)(bc >> 32);
-                }
-
-                var word = va ^ vb;
-
-                if (negRes)
-                {
-                    borrow = word - borrow;
-                    word = ~(uint)borrow;
-                    borrow = (uint)(borrow >> 32) & 0x1u;
-                }
-
-                result[i] = word;
-            }
-
-            for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) ;
-            if (i == -1)
-                return Zero;
-
-            if (i < result.Length - 1)
-                Array.Resize(ref result, i + 1);
-
-            return new BigInteger(negRes ? (short)-1 : (short)1, result);
-        }
-
-        /// <summary>
-        /// Returns the bitwise one's complement of a <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="value">An integer value.</param>
-        /// <returns>
-        /// The bitwise one's complement of <paramref name="value"/>.
-        /// </returns>
-        public static BigInteger operator ~(BigInteger value)
-        {
-            if (value._data == null)
-                return MinusOne;
-
-            var data = value._data;
-            int sign = value._sign;
-
-            var negRes = sign == 1;
-
-            var result = new uint[data.Length];
-
-            ulong carry = 1, borrow = 1;
-
-            int i;
-            for (i = 0; i < result.Length; ++i)
-            {
-                var word = data[i];
-                if (sign == -1)
-                {
-                    carry = ~word + carry;
-                    word = (uint)carry;
-                    carry = (uint)(carry >> 32);
-                }
-
-                word = ~word;
-
-                if (negRes)
-                {
-                    borrow = word - borrow;
-                    word = ~(uint)borrow;
-                    borrow = (uint)(borrow >> 32) & 0x1u;
-                }
-
-                result[i] = word;
-            }
-
-            for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) ;
-            if (i == -1)
-                return Zero;
-
-            if (i < result.Length - 1)
-                Array.Resize(ref result, i + 1);
-
-            return new BigInteger(negRes ? (short)-1 : (short)1, result);
-        }
-
-        //returns the 0-based index of the most significant set bit
-        //returns 0 if no bit is set, so extra care when using it
-        static int BitScanBackward(uint word)
-        {
-            for (var i = 31; i >= 0; --i)
-            {
-                var mask = 1u << i;
-                if ((word & mask) == mask)
-                    return i;
-            }
-            return 0;
-        }
-
-        /// <summary>
-        /// Shifts a <see cref="BigInteger"/> value a specified number of bits to the left.
-        /// </summary>
-        /// <param name="value">The value whose bits are to be shifted.</param>
-        /// <param name="shift">The number of bits to shift value to the left.</param>
-        /// <returns>
-        /// A value that has been shifted to the left by the specified number of bits.
-        /// </returns>
-        public static BigInteger operator <<(BigInteger value, int shift)
-        {
-            if (shift == 0 || value._data == null)
-                return value;
-            if (shift < 0)
-                return value >> -shift;
-
-            var data = value._data;
-            int sign = value._sign;
-
-            var topMostIdx = BitScanBackward(data[data.Length - 1]);
-            var bits = shift - (31 - topMostIdx);
-            var extraWords = (bits >> 5) + ((bits & 0x1F) != 0 ? 1 : 0);
-
-            var res = new uint[data.Length + extraWords];
-
-            var idxShift = shift >> 5;
-            var bitShift = shift & 0x1F;
-            var carryShift = 32 - bitShift;
-
-            if (carryShift == 32)
-            {
-                for (var i = 0; i < data.Length; ++i)
-                {
-                    var word = data[i];
-                    res[i + idxShift] |= word << bitShift;
-                }
-            }
-            else
-            {
-                for (var i = 0; i < data.Length; ++i)
-                {
-                    var word = data[i];
-                    res[i + idxShift] |= word << bitShift;
-                    if (i + idxShift + 1 < res.Length)
-                        res[i + idxShift + 1] = word >> carryShift;
-                }
-            }
-
-            return new BigInteger((short)sign, res);
-        }
-
-        /// <summary>
-        /// Shifts a <see cref="BigInteger"/> value a specified number of bits to the right.
-        /// </summary>
-        /// <param name="value">The value whose bits are to be shifted.</param>
-        /// <param name="shift">The number of bits to shift value to the right.</param>
-        /// <returns>
-        /// A value that has been shifted to the right by the specified number of bits.
-        /// </returns>
-        public static BigInteger operator >>(BigInteger value, int shift)
-        {
-            if (shift == 0 || value._sign == 0)
-                return value;
-            if (shift < 0)
-                return value << -shift;
-
-            var data = value._data;
-            int sign = value._sign;
-
-            var topMostIdx = BitScanBackward(data[data.Length - 1]);
-            var idxShift = shift >> 5;
-            var bitShift = shift & 0x1F;
-
-            var extraWords = idxShift;
-            if (bitShift > topMostIdx)
-                ++extraWords;
-            var size = data.Length - extraWords;
-
-            if (size <= 0)
-            {
-                if (sign == 1)
-                    return Zero;
-                return MinusOne;
-            }
-
-            var res = new uint[size];
-            var carryShift = 32 - bitShift;
-
-            if (carryShift == 32)
-            {
-                for (var i = data.Length - 1; i >= idxShift; --i)
-                {
-                    var word = data[i];
-
-                    if (i - idxShift < res.Length)
-                        res[i - idxShift] |= word >> bitShift;
-                }
-            }
-            else
-            {
-                for (var i = data.Length - 1; i >= idxShift; --i)
-                {
-                    var word = data[i];
-
-                    if (i - idxShift < res.Length)
-                        res[i - idxShift] |= word >> bitShift;
-                    if (i - idxShift - 1 >= 0)
-                        res[i - idxShift - 1] = word << carryShift;
-                }
-
-            }
-
-            //Round down instead of toward zero
-            if (sign == -1)
-            {
-                for (var i = 0; i < idxShift; i++)
-                {
-                    if (data[i] != 0u)
-                    {
-                        var tmp = new BigInteger((short)sign, res);
-                        --tmp;
-                        return tmp;
-                    }
-                }
-                if (bitShift > 0 && (data[idxShift] << carryShift) != 0u)
-                {
-                    var tmp = new BigInteger((short)sign, res);
-                    --tmp;
-                    return tmp;
-                }
-            }
-            return new BigInteger((short)sign, res);
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is less than another
-        /// <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> is less than <paramref name="right"/>; otherwise, <c>false</c>.
-        /// </returns>
-        public static bool operator <(BigInteger left, BigInteger right)
-        {
-            return Compare(left, right) < 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is less than a 64-bit signed integer.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if left is <paramref name="left"/> than <paramref name="right"/>; otherwise, <c>false</c>.
-        /// </returns>
-        public static bool operator <(BigInteger left, long right)
-        {
-            return left.CompareTo(right) < 0;
-        }
-
-
-        /// <summary>
-        /// Returns a value that indicates whether a 64-bit signed integer is less than a <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> is less than <paramref name="right"/>;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        public static bool operator <(long left, BigInteger right)
-        {
-            return right.CompareTo(left) > 0;
-        }
-
-
-        /// <summary>
-        /// Returns a value that indicates whether a 64-bit signed integer is less than a <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> is less than <paramref name="right"/>; otherwise, <c>false</c>.
-        /// </returns>
-        [CLSCompliant(false)]
-        public static bool operator <(BigInteger left, ulong right)
-        {
-            return left.CompareTo(right) < 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a 64-bit unsigned integer is less than a <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> is less than <paramref name="right"/>; otherwise, <c>false</c>.
-        /// </returns>
-        [CLSCompliant(false)]
-        public static bool operator <(ulong left, BigInteger right)
-        {
-            return right.CompareTo(left) > 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is less than or equal
-        /// to another <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> is less than or equal to <paramref name="right"/>;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        public static bool operator <=(BigInteger left, BigInteger right)
-        {
-            return Compare(left, right) <= 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is less than or equal
-        /// to a 64-bit signed integer.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> is less than or equal to <paramref name="right"/>;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        public static bool operator <=(BigInteger left, long right)
-        {
-            return left.CompareTo(right) <= 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a 64-bit signed integer is less than or equal to a <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> is less than or equal to <paramref name="right"/>;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        public static bool operator <=(long left, BigInteger right)
-        {
-            return right.CompareTo(left) >= 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is less than or equal to
-        /// a 64-bit unsigned integer.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> is less than or equal to <paramref name="right"/>;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        [CLSCompliant(false)]
-        public static bool operator <=(BigInteger left, ulong right)
-        {
-            return left.CompareTo(right) <= 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a 64-bit unsigned integer is less than or equal to a
-        /// <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> is less than or equal to <paramref name="right"/>;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        [CLSCompliant(false)]
-        public static bool operator <=(ulong left, BigInteger right)
-        {
-            return right.CompareTo(left) >= 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is greater than another
-        /// <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        public static bool operator >(BigInteger left, BigInteger right)
-        {
-            return Compare(left, right) > 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a <see cref="BigInteger"/> is greater than a 64-bit signed integer value.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        public static bool operator >(BigInteger left, long right)
-        {
-            return left.CompareTo(right) > 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a 64-bit signed integer is greater than a <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        public static bool operator >(long left, BigInteger right)
-        {
-            return right.CompareTo(left) < 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is greater than a 64-bit unsigned integer.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        [CLSCompliant(false)]
-        public static bool operator >(BigInteger left, ulong right)
-        {
-            return left.CompareTo(right) > 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a 64-bit unsigned integer is greater than a <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        [CLSCompliant(false)]
-        public static bool operator >(ulong left, BigInteger right)
-        {
-            return right.CompareTo(left) < 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is greater than or equal
-        /// to another <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        public static bool operator >=(BigInteger left, BigInteger right)
-        {
-            return Compare(left, right) >= 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is greater than or equal
-        /// to a 64-bit signed integer value.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        public static bool operator >=(BigInteger left, long right)
-        {
-            return left.CompareTo(right) >= 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a 64-bit signed integer is greater than or equal to a
-        /// <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        public static bool operator >=(long left, BigInteger right)
-        {
-            return right.CompareTo(left) <= 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is greater than or equal to a
-        /// 64-bit unsigned integer value.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        [CLSCompliant(false)]
-        public static bool operator >=(BigInteger left, ulong right)
-        {
-            return left.CompareTo(right) >= 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a 64-bit unsigned integer is greater than or equal to a
-        /// <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        [CLSCompliant(false)]
-        public static bool operator >=(ulong left, BigInteger right)
-        {
-            return right.CompareTo(left) <= 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether the values of two <see cref="BigInteger"/> objects are equal.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same value;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        public static bool operator ==(BigInteger left, BigInteger right)
-        {
-            return Compare(left, right) == 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a <see cref="BigInteger"/> value and a signed long integer value are equal.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same value;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        public static bool operator ==(BigInteger left, long right)
-        {
-            return left.CompareTo(right) == 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a signed long integer value and a <see cref="BigInteger"/> value are equal.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same value;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        public static bool operator ==(long left, BigInteger right)
-        {
-            return right.CompareTo(left) == 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a <see cref="BigInteger"/> value and an unsigned long integer value are equal.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same value;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        [CLSCompliant(false)]
-        public static bool operator ==(BigInteger left, ulong right)
-        {
-            return left.CompareTo(right) == 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether an unsigned long integer value and a <see cref="BigInteger"/> value are equal.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same value;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        [CLSCompliant(false)]
-        public static bool operator ==(ulong left, BigInteger right)
-        {
-            return right.CompareTo(left) == 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether two <see cref="BigInteger"/> objects have different values.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> and <paramref name="right"/> are not equal;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        public static bool operator !=(BigInteger left, BigInteger right)
-        {
-            return Compare(left, right) != 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a <see cref="BigInteger"/> value and a 64-bit signed integer are not equal.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> and <paramref name="right"/> are not equal;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        public static bool operator !=(BigInteger left, long right)
-        {
-            return left.CompareTo(right) != 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a 64-bit signed integer and a <see cref="BigInteger"/> value are not equal.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> and <paramref name="right"/> are not equal;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        public static bool operator !=(long left, BigInteger right)
-        {
-            return right.CompareTo(left) != 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a <see cref="BigInteger"/> value and a 64-bit unsigned integer are not equal.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> and <paramref name="right"/> are not equal;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        [CLSCompliant(false)]
-        public static bool operator !=(BigInteger left, ulong right)
-        {
-            return left.CompareTo(right) != 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether a 64-bit unsigned integer and a <see cref="BigInteger"/> value are not equal.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="left"/> and <paramref name="right"/> are not equal;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        [CLSCompliant(false)]
-        public static bool operator !=(ulong left, BigInteger right)
-        {
-            return right.CompareTo(left) != 0;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether the current instance and a specified object have the same value.
-        /// </summary>
-        /// <param name="obj">The object to compare.</param>
-        /// <returns>
-        /// <c>true</c> if the <paramref name="obj"/> parameter is a <see cref="BigInteger"/> object or a type capable
-        /// of implicit conversion to a <see cref="BigInteger"/> value, and its value is equal to the value of the
-        /// current <see cref="BigInteger"/> object; otherwise, <c>false</c>.
-        /// </returns>
-        public override bool Equals(object obj)
-        {
-            if (!(obj is BigInteger))
-                return false;
-            return Equals((BigInteger)obj);
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether the current instance and a specified <see cref="BigInteger"/> object
-        /// have the same value.
-        /// </summary>
-        /// <param name="other">The object to compare.</param>
-        /// <returns>
-        /// <c>true</c> if this <see cref="BigInteger"/> object and <paramref name="other"/> have the same value;
-        /// otherwise, <c>false</c>.
-        /// </returns>
-        public bool Equals(BigInteger other)
-        {
-            if (_sign != other._sign)
-                return false;
-
-            var alen = _data != null ? _data.Length : 0;
-            var blen = other._data != null ? other._data.Length : 0;
-
-            if (alen != blen)
-                return false;
-            for (var i = 0; i < alen; ++i)
-            {
-                if (_data[i] != other._data[i])
-                    return false;
-            }
-            return true;
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether the current instance and a signed 64-bit integer have the same value.
-        /// </summary>
-        /// <param name="other">The signed 64-bit integer value to compare.</param>
-        /// <returns>
-        /// <c>true</c> if the signed 64-bit integer and the current instance have the same value; otherwise, <c>false</c>.
-        /// </returns>
-        public bool Equals(long other)
-        {
-            return CompareTo(other) == 0;
-        }
-
-        /// <summary>
-        /// Converts the numeric value of the current <see cref="BigInteger"/> object to its equivalent string representation.
-        /// </summary>
-        /// <returns>
-        /// The string representation of the current <see cref="BigInteger"/> value.
-        /// </returns>
-        public override string ToString()
-        {
-            return ToString(10, null);
-        }
-
-        private string ToStringWithPadding(string format, uint radix, IFormatProvider provider)
-        {
-            if (format.Length > 1)
-            {
-                var precision = Convert.ToInt32(format.Substring(1), CultureInfo.InvariantCulture.NumberFormat);
-                var baseStr = ToString(radix, provider);
-                if (baseStr.Length < precision)
-                {
-                    var additional = new string('0', precision - baseStr.Length);
-                    if (baseStr[0] != '-')
-                    {
-                        return additional + baseStr;
-                    }
-                    return "-" + additional + baseStr.Substring(1);
-                }
-                return baseStr;
-            }
-            return ToString(radix, provider);
-        }
-
-        /// <summary>
-        /// Converts the numeric value of the current <see cref="BigInteger"/> object to its equivalent string representation
-        /// by using the specified format.
-        /// </summary>
-        /// <param name="format">A standard or custom numeric format string.</param>
-        /// <returns>
-        /// The string representation of the current <see cref="BigInteger"/> value in the format specified by the
-        /// <paramref name="format"/> parameter.
-        /// </returns>
-        /// <exception cref="FormatException"><paramref name="format"/> is not a valid format string.</exception>
-        public string ToString(string format)
-        {
-            return ToString(format, null);
-        }
-
-        /// <summary>
-        /// Converts the numeric value of the current <see cref="BigInteger"/> object to its equivalent string representation
-        /// by using the specified culture-specific formatting information. 
-        /// </summary>
-        /// <param name="provider">An object that supplies culture-specific formatting information.</param>
-        /// <returns>
-        /// The string representation of the current <see cref="BigInteger"/> value in the format specified by the
-        /// <paramref name="provider"/> parameter.
-        /// </returns>
-        public string ToString(IFormatProvider provider)
-        {
-            return ToString(null, provider);
-        }
-
-        /// <summary>
-        /// Converts the numeric value of the current <see cref="BigInteger"/> object to its equivalent string representation
-        /// by using the specified format and culture-specific format information.
-        /// </summary>
-        /// <param name="format">A standard or custom numeric format string.</param>
-        /// <param name="provider">An object that supplies culture-specific formatting information.</param>
-        /// <returns>
-        /// The string representation of the current <see cref="BigInteger"/> value as specified by the <paramref name="format"/>
-        /// and <paramref name="provider"/> parameters.
-        /// </returns>
-        public string ToString(string format, IFormatProvider provider)
-        {
-            if (string.IsNullOrEmpty(format))
-                return ToString(10, provider);
-
-            switch (format[0])
-            {
-                case 'd':
-                case 'D':
-                case 'g':
-                case 'G':
-                case 'r':
-                case 'R':
-                    return ToStringWithPadding(format, 10, provider);
-                case 'x':
-                case 'X':
-                    return ToStringWithPadding(format, 16, null);
-                default:
-                    throw new FormatException(string.Format("format '{0}' not implemented", format));
-            }
-        }
-
-        private static uint[] MakeTwoComplement(uint[] v)
-        {
-            var res = new uint[v.Length];
-
-            ulong carry = 1;
-            for (var i = 0; i < v.Length; ++i)
-            {
-                var word = v[i];
-                carry = (ulong)~word + carry;
-                word = (uint)carry;
-                carry = (uint)(carry >> 32);
-                res[i] = word;
-            }
-
-            var last = res[res.Length - 1];
-            var idx = FirstNonFfByte(last);
-            uint mask = 0xFF;
-            for (var i = 1; i < idx; ++i)
-                mask = (mask << 8) | 0xFF;
-
-            res[res.Length - 1] = last & mask;
-            return res;
-        }
-
-        private string ToString(uint radix, IFormatProvider provider)
-        {
-            const string characterSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-
-            if (characterSet.Length < radix)
-                throw new ArgumentException("charSet length less than radix", "characterSet");
-            if (radix == 1)
-                throw new ArgumentException("There is no such thing as radix one notation", "radix");
-
-            if (_sign == 0)
-                return "0";
-            if (_data.Length == 1 && _data[0] == 1)
-                return _sign == 1 ? "1" : "-1";
-
-            var digits = new List<char>(1 + _data.Length * 3 / 10);
-
-            BigInteger a;
-            if (_sign == 1)
-                a = this;
-            else
-            {
-                var dt = _data;
-                if (radix > 10)
-                    dt = MakeTwoComplement(dt);
-                a = new BigInteger(1, dt);
-            }
-
-            while (a != 0)
-            {
-                BigInteger rem;
-                a = DivRem(a, radix, out rem);
-                digits.Add(characterSet[(int)rem]);
-            }
-
-            if (_sign == -1 && radix == 10)
-            {
-                NumberFormatInfo info = null;
-                if (provider != null)
-                    info = provider.GetFormat(typeof(NumberFormatInfo)) as NumberFormatInfo;
-                if (info != null)
-                {
-                    var str = info.NegativeSign;
-                    for (var i = str.Length - 1; i >= 0; --i)
-                        digits.Add(str[i]);
-                }
-                else
-                {
-                    digits.Add('-');
-                }
-            }
-
-            var last = digits[digits.Count - 1];
-            if (_sign == 1 && radix > 10 && (last < '0' || last > '9'))
-                digits.Add('0');
-
-            digits.Reverse();
-
-            return new string(digits.ToArray());
-        }
-
-        /// <summary>
-        /// Converts the string representation of a number to its <see cref="BigInteger"/> equivalent.
-        /// </summary>
-        /// <param name="value">A string that contains the number to convert.</param>
-        /// <returns>
-        /// A value that is equivalent to the number specified in the <paramref name="value"/> parameter.
-        /// </returns>
-        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c>.</exception>
-        /// <exception cref="FormatException"><paramref name="value"/> is not in the correct format.</exception>
-        public static BigInteger Parse(string value)
-        {
-            Exception ex;
-            BigInteger result;
-
-            if (!Parse(value, false, out result, out ex))
-                throw ex;
-            return result;
-        }
-
-        /// <summary>
-        /// Converts the string representation of a number in a specified style to its <see cref="BigInteger"/> equivalent.
-        /// </summary>
-        /// <param name="value">A string that contains a number to convert.</param>
-        /// <param name="style">A bitwise combination of the enumeration values that specify the permitted format of <paramref name="value"/>.</param>
-        /// <returns>
-        /// A value that is equivalent to the number specified in the <paramref name="value"/> parameter.
-        /// </returns>
-        /// <exception cref="ArgumentException">
-        /// <para><paramref name="style"/> is not a <see cref="NumberStyles"/> value.</para>
-        /// <para>-or-</para>
-        /// <para><paramref name="style"/> includes the <see cref="NumberStyles.AllowHexSpecifier"/> or <see cref="NumberStyles.HexNumber"/> flag along with another value.</para>
-        /// </exception>
-        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c>.</exception>
-        /// <exception cref="FormatException"><paramref name="value"/> does not comply with the input pattern specified by <see cref="NumberStyles"/>.</exception>
-        public static BigInteger Parse(string value, NumberStyles style)
-        {
-            return Parse(value, style, null);
-        }
-
-        /// <summary>
-        /// Converts the string representation of a number in a specified style to its <see cref="BigInteger"/> equivalent.
-        /// </summary>
-        /// <param name="value">A string that contains a number to convert.</param>
-        /// <param name="provider">An object that provides culture-specific formatting information about <paramref name="value"/>.</param>
-        /// <returns>
-        /// A value that is equivalent to the number specified in the <paramref name="value"/> parameter.
-        /// </returns>
-        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c>.</exception>
-        /// <exception cref="FormatException"><paramref name="value"/> is not in the correct format.</exception>
-        public static BigInteger Parse(string value, IFormatProvider provider)
-        {
-            return Parse(value, NumberStyles.Integer, provider);
-        }
-
-        /// <summary>
-        /// Converts the string representation of a number in a specified style and culture-specific format to its <see cref="BigInteger"/> equivalent.
-        /// </summary>
-        /// <param name="value">A string that contains a number to convert.</param>
-        /// <param name="style">A bitwise combination of the enumeration values that specify the permitted format of <paramref name="value"/>.</param>
-        /// <param name="provider">An object that provides culture-specific formatting information about <paramref name="value"/>.</param>
-        /// <returns>
-        /// A value that is equivalent to the number specified in the <paramref name="value"/> parameter.
-        /// </returns>
-        /// <exception cref="ArgumentException">
-        /// <para><paramref name="style"/> is not a <see cref="NumberStyles"/> value.</para>
-        /// <para>-or-</para>
-        /// <para><paramref name="style"/> includes the <see cref="NumberStyles.AllowHexSpecifier"/> or <see cref="NumberStyles.HexNumber"/> flag along with another value.</para>
-        /// </exception>
-        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c>.</exception>
-        /// <exception cref="FormatException"><paramref name="value"/> does not comply with the input pattern specified by <see cref="NumberStyles"/>.</exception>
-        public static BigInteger Parse(string value, NumberStyles style, IFormatProvider provider)
-        {
-            Exception exc;
-            BigInteger res;
-
-            if (!Parse(value, style, provider, false, out res, out exc))
-                throw exc;
-
-            return res;
-        }
-
-        /// <summary>
-        /// Tries to convert the string representation of a number to its <see cref="BigInteger"/> equivalent, and
-        /// returns a value that indicates whether the conversion succeeded.
-        /// </summary>
-        /// <param name="value">The string representation of a number.</param>
-        /// <param name="result">When this method returns, contains the <see cref="BigInteger"/> equivalent to the number that is contained in value, or zero (0) if the conversion fails. The conversion fails if the <paramref name="value"/> parameter is <c>null</c> or is not of the correct format. This parameter is passed uninitialized.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="value"/> was converted successfully; otherwise, <c>false</c>.
-        /// </returns>
-        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c>.</exception>
-        public static bool TryParse(string value, out BigInteger result)
-        {
-            Exception ex;
-            return Parse(value, true, out result, out ex);
-        }
-
-        /// <summary>
-        /// Tries to convert the string representation of a number in a specified style and culture-specific format to its
-        /// <see cref="BigInteger"/> equivalent, and returns a value that indicates whether the conversion succeeded.
-        /// </summary>
-        /// <param name="value">The string representation of a number.</param>
-        /// <param name="style">A bitwise combination of enumeration values that indicates the style elements that can be present in <paramref name="value"/>.</param>
-        /// <param name="provider">An object that supplies culture-specific formatting information about <paramref name="value"/>.</param>
-        /// <param name="result">When this method returns, contains the <see cref="BigInteger"/> equivalent to the number that is contained in value, or <see cref="Zero"/> if the conversion fails. The conversion fails if the <paramref name="value"/> parameter is <c>null</c> or is not of the correct format. This parameter is passed uninitialized.</param>
-        /// <returns>
-        /// <c>true</c> if <paramref name="value"/> was converted successfully; otherwise, <c>false</c>.
-        /// </returns>
-        /// <exception cref="ArgumentException">
-        /// <para><paramref name="style"/> is not a <see cref="NumberStyles"/> value.</para>
-        /// <para>-or-</para>
-        /// <para><paramref name="style"/> includes the <see cref="NumberStyles.AllowHexSpecifier"/> or <see cref="NumberStyles.HexNumber"/> flag along with another value.</para>
-        /// </exception>
-        public static bool TryParse(string value, NumberStyles style, IFormatProvider provider, out BigInteger result)
-        {
-            Exception exc;
-            if (!Parse(value, style, provider, true, out result, out exc))
-            {
-                result = Zero;
-                return false;
-            }
-
-            return true;
-        }
-
-        private static bool Parse(string value, NumberStyles style, IFormatProvider fp, bool tryParse, out BigInteger result, out Exception exc)
-        {
-            result = Zero;
-            exc = null;
-
-            if (value == null)
-            {
-                if (!tryParse)
-                    exc = new ArgumentNullException("value");
-                return false;
-            }
-
-            if (value.Length == 0)
-            {
-                if (!tryParse)
-                    exc = GetFormatException();
-                return false;
-            }
-
-            NumberFormatInfo nfi = null;
-            if (fp != null)
-            {
-                var typeNfi = typeof(NumberFormatInfo);
-                nfi = (NumberFormatInfo) fp.GetFormat(typeNfi);
-            }
-            if (nfi == null)
-                nfi = NumberFormatInfo.CurrentInfo;
-
-            if (!CheckStyle(style, tryParse, ref exc))
-                return false;
-
-            var allowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
-            var allowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0;
-            var allowThousands = (style & NumberStyles.AllowThousands) != 0;
-            var allowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0;
-            var allowParentheses = (style & NumberStyles.AllowParentheses) != 0;
-            var allowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0;
-            var allowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
-            var allowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
-            var allowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
-            var allowExponent = (style & NumberStyles.AllowExponent) != 0;
-
-            var pos = 0;
-
-            if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc))
-                return false;
-
-            var foundOpenParentheses = false;
-            var negative = false;
-            var foundSign = false;
-            var foundCurrency = false;
-
-            // Pre-number stuff
-            if (allowParentheses && value[pos] == '(')
-            {
-                foundOpenParentheses = true;
-                foundSign = true;
-                negative = true; // MS always make the number negative when there parentheses
-                                 // even when NumberFormatInfo.NumberNegativePattern != 0!!!
-                pos++;
-                if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc))
-                    return false;
-
-                if (value.Substring(pos, nfi.NegativeSign.Length) == nfi.NegativeSign)
-                {
-                    if (!tryParse)
-                        exc = GetFormatException();
-                    return false;
-                }
-
-                if (value.Substring(pos, nfi.PositiveSign.Length) == nfi.PositiveSign)
-                {
-                    if (!tryParse)
-                        exc = GetFormatException();
-                    return false;
-                }
-            }
-
-            if (allowLeadingSign && !foundSign)
-            {
-                // Sign + Currency
-                FindSign(ref pos, value, nfi, ref foundSign, ref negative);
-                if (foundSign)
-                {
-                    if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc))
-                        return false;
-                    if (allowCurrencySymbol)
-                    {
-                        FindCurrency(ref pos, value, nfi,
-                                  ref foundCurrency);
-                        if (foundCurrency && allowLeadingWhite &&
-                            !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc))
-                            return false;
-                    }
-                }
-            }
-
-            if (allowCurrencySymbol && !foundCurrency)
-            {
-                // Currency + sign
-                FindCurrency(ref pos, value, nfi, ref foundCurrency);
-                if (foundCurrency)
-                {
-                    if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc))
-                        return false;
-                    if (foundCurrency)
-                    {
-                        if (!foundSign && allowLeadingSign)
-                        {
-                            FindSign(ref pos, value, nfi, ref foundSign,
-                                  ref negative);
-                            if (foundSign && allowLeadingWhite &&
-                                !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc))
-                                return false;
-                        }
-                    }
-                }
-            }
-
-            var number = Zero;
-            var nDigits = 0;
-            var decimalPointPos = -1;
-            var firstHexDigit = true;
-
-            // Number stuff
-            while (pos < value.Length)
-            {
-
-                if (!ValidDigit(value[pos], allowHexSpecifier))
-                {
-                    if (allowThousands &&
-                        (FindOther(ref pos, value, nfi.NumberGroupSeparator)
-                        || FindOther(ref pos, value, nfi.CurrencyGroupSeparator)))
-                        continue;
-
-                    if (allowDecimalPoint && decimalPointPos < 0 &&
-                        (FindOther(ref pos, value, nfi.NumberDecimalSeparator)
-                        || FindOther(ref pos, value, nfi.CurrencyDecimalSeparator)))
-                    {
-                        decimalPointPos = nDigits;
-                        continue;
-                    }
-
-                    break;
-                }
-
-                nDigits++;
-
-                if (allowHexSpecifier)
-                {
-                    var hexDigit = value[pos++];
-                    byte digitValue;
-                    if (char.IsDigit(hexDigit))
-                        digitValue = (byte)(hexDigit - '0');
-                    else if (char.IsLower(hexDigit))
-                        digitValue = (byte)(hexDigit - 'a' + 10);
-                    else
-                        digitValue = (byte)(hexDigit - 'A' + 10);
-
-                    if (firstHexDigit && digitValue >= 8)
-                        negative = true;
-
-                    number = number * 16 + digitValue;
-                    firstHexDigit = false;
-                    continue;
-                }
-
-                number = number * 10 + (byte)(value[pos++] - '0');
-            }
-
-            // Post number stuff
-            if (nDigits == 0)
-            {
-                if (!tryParse)
-                    exc = GetFormatException();
-                return false;
-            }
-
-            //Signed hex value (Two's Complement)
-            if (allowHexSpecifier && negative)
-            {
-                var mask = Pow(16, nDigits) - 1;
-                number = (number ^ mask) + 1;
-            }
-
-            var exponent = 0;
-            if (allowExponent)
-                if (FindExponent(ref pos, value, ref exponent, tryParse, ref exc) && exc != null)
-                    return false;
-
-            if (allowTrailingSign && !foundSign)
-            {
-                // Sign + Currency
-                FindSign(ref pos, value, nfi, ref foundSign, ref negative);
-                if (foundSign && pos < value.Length)
-                {
-                    if (allowTrailingWhite && !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc))
-                        return false;
-                }
-            }
-
-            if (allowCurrencySymbol && !foundCurrency)
-            {
-                if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, false, tryParse, ref exc))
-                    return false;
-
-                // Currency + sign
-                FindCurrency(ref pos, value, nfi, ref foundCurrency);
-                if (foundCurrency && pos < value.Length)
-                {
-                    if (allowTrailingWhite && !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc))
-                        return false;
-                    if (!foundSign && allowTrailingSign)
-                        FindSign(ref pos, value, nfi, ref foundSign,
-                              ref negative);
-                }
-            }
-
-            if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, false, tryParse, ref exc))
-                return false;
-
-            if (foundOpenParentheses)
-            {
-                if (pos >= value.Length || value[pos++] != ')')
-                {
-                    if (!tryParse)
-                        exc = GetFormatException();
-                    return false;
-                }
-                if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, false, tryParse, ref exc))
-                    return false;
-            }
-
-            if (pos < value.Length && value[pos] != '\u0000')
-            {
-                if (!tryParse)
-                    exc = GetFormatException();
-                return false;
-            }
-
-            if (decimalPointPos >= 0)
-                exponent = exponent - nDigits + decimalPointPos;
-
-            if (exponent < 0)
-            {
-                //
-                // Any non-zero values after decimal point are not allowed
-                //
-                BigInteger remainder;
-                number = DivRem(number, Pow(10, -exponent), out remainder);
-
-                if (!remainder.IsZero)
-                {
-                    if (!tryParse)
-                        exc = new OverflowException("Value too large or too small. exp=" + exponent + " rem = " + remainder + " pow = " + Pow(10, -exponent));
-                    return false;
-                }
-            }
-            else if (exponent > 0)
-            {
-                number = Pow(10, exponent) * number;
-            }
-
-            if (number._sign == 0)
-                result = number;
-            else if (negative)
-                result = new BigInteger(-1, number._data);
-            else
-                result = new BigInteger(1, number._data);
-
-            return true;
-        }
-
-        private static bool CheckStyle(NumberStyles style, bool tryParse, ref Exception exc)
-        {
-            if ((style & NumberStyles.AllowHexSpecifier) != 0)
-            {
-                var ne = style ^ NumberStyles.AllowHexSpecifier;
-                if ((ne & NumberStyles.AllowLeadingWhite) != 0)
-                    ne ^= NumberStyles.AllowLeadingWhite;
-                if ((ne & NumberStyles.AllowTrailingWhite) != 0)
-                    ne ^= NumberStyles.AllowTrailingWhite;
-                if (ne != 0)
-                {
-                    if (!tryParse)
-                        exc = new ArgumentException(
-                            "With AllowHexSpecifier only " +
-                            "AllowLeadingWhite and AllowTrailingWhite " +
-                            "are permitted.");
-                    return false;
-                }
-            }
-            else if ((uint)style > (uint)NumberStyles.Any)
-            {
-                if (!tryParse)
-                    exc = new ArgumentException("Not a valid number style");
-                return false;
-            }
-
-            return true;
-        }
-
-        private static bool JumpOverWhitespace(ref int pos, string s, bool reportError, bool tryParse, ref Exception exc)
-        {
-            while (pos < s.Length && char.IsWhiteSpace(s[pos]))
-                pos++;
-
-            if (reportError && pos >= s.Length)
-            {
-                if (!tryParse)
-                    exc = GetFormatException();
-                return false;
-            }
-
-            return true;
-        }
-
-        private static void FindSign(ref int pos, string s, NumberFormatInfo nfi, ref bool foundSign, ref bool negative)
-        {
-            if ((pos + nfi.NegativeSign.Length) <= s.Length &&
-                string.CompareOrdinal(s, pos, nfi.NegativeSign, 0, nfi.NegativeSign.Length) == 0)
-            {
-                negative = true;
-                foundSign = true;
-                pos += nfi.NegativeSign.Length;
-            }
-            else if ((pos + nfi.PositiveSign.Length) <= s.Length &&
-              string.CompareOrdinal(s, pos, nfi.PositiveSign, 0, nfi.PositiveSign.Length) == 0)
-            {
-                negative = false;
-                pos += nfi.PositiveSign.Length;
-                foundSign = true;
-            }
-        }
-
-        private static void FindCurrency(ref int pos, string s, NumberFormatInfo nfi, ref bool foundCurrency)
-        {
-            if ((pos + nfi.CurrencySymbol.Length) <= s.Length &&
-                 s.Substring(pos, nfi.CurrencySymbol.Length) == nfi.CurrencySymbol)
-            {
-                foundCurrency = true;
-                pos += nfi.CurrencySymbol.Length;
-            }
-        }
-
-        private static bool FindExponent(ref int pos, string s, ref int exponent, bool tryParse, ref Exception exc)
-        {
-            exponent = 0;
-
-            if (pos >= s.Length || (s[pos] != 'e' && s[pos] != 'E'))
-            {
-                exc = null;
-                return false;
-            }
-
-            var i = pos + 1;
-            if (i == s.Length)
-            {
-                exc = tryParse ? null : GetFormatException();
-                return true;
-            }
-
-            var negative = false;
-            if (s[i] == '-')
-            {
-                negative = true;
-                if (++i == s.Length)
-                {
-                    exc = tryParse ? null : GetFormatException();
-                    return true;
-                }
-            }
-
-            if (s[i] == '+' && ++i == s.Length)
-            {
-                exc = tryParse ? null : GetFormatException();
-                return true;
-            }
-
-            long exp = 0; // temp long value
-            for (; i < s.Length; i++)
-            {
-                if (!char.IsDigit(s[i]))
-                {
-                    exc = tryParse ? null : GetFormatException();
-                    return true;
-                }
-
-                // Reduce the risk of throwing an overflow exc
-                exp = checked(exp * 10 - (int)(s[i] - '0'));
-                if (exp < int.MinValue || exp > int.MaxValue)
-                {
-                    exc = tryParse ? null : new OverflowException("Value too large or too small.");
-                    return true;
-                }
-            }
-
-            // exp value saved as negative
-            if (!negative)
-                exp = -exp;
-
-            exc = null;
-            exponent = (int) exp;
-            pos = i;
-            return true;
-        }
-
-        private static bool FindOther(ref int pos, string s, string other)
-        {
-            if ((pos + other.Length) <= s.Length &&
-                 s.Substring(pos, other.Length) == other)
-            {
-                pos += other.Length;
-                return true;
-            }
-
-            return false;
-        }
-
-        private static bool ValidDigit(char e, bool allowHex)
-        {
-            if (allowHex)
-                return char.IsDigit(e) || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f');
-
-            return char.IsDigit(e);
-        }
-
-        private static Exception GetFormatException()
-        {
-            return new FormatException("Input string was not in the correct format");
-        }
-
-        private static bool ProcessTrailingWhitespace(bool tryParse, string s, int position, ref Exception exc)
-        {
-            var len = s.Length;
-
-            for (var i = position; i < len; i++)
-            {
-                var c = s[i];
-
-                if (c != 0 && !char.IsWhiteSpace(c))
-                {
-                    if (!tryParse)
-                        exc = GetFormatException();
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        private static bool Parse(string value, bool tryParse, out BigInteger result, out Exception exc)
-        {
-            int i, sign = 1;
-            var digitsSeen = false;
-
-            result = Zero;
-            exc = null;
-
-            if (value == null)
-            {
-                if (!tryParse)
-                    exc = new ArgumentNullException("value");
-                return false;
-            }
-
-            var len = value.Length;
-
-            char c;
-            for (i = 0; i < len; i++)
-            {
-                c = value[i];
-                if (!char.IsWhiteSpace(c))
-                    break;
-            }
-
-            if (i == len)
-            {
-                if (!tryParse)
-                    exc = GetFormatException();
-                return false;
-            }
-
-            var info = NumberFormatInfo.CurrentInfo;
-
-            var negative = info.NegativeSign;
-            var positive = info.PositiveSign;
-
-            if (string.CompareOrdinal(value, i, positive, 0, positive.Length) == 0)
-                i += positive.Length;
-            else if (string.CompareOrdinal(value, i, negative, 0, negative.Length) == 0)
-            {
-                sign = -1;
-                i += negative.Length;
-            }
-
-            var val = Zero;
-            for (; i < len; i++)
-            {
-                c = value[i];
-
-                if (c == '\0')
-                {
-                    i = len;
-                    continue;
-                }
-
-                if (c >= '0' && c <= '9')
-                {
-                    var d = (byte)(c - '0');
-
-                    val = val * 10 + d;
-
-                    digitsSeen = true;
-                }
-                else if (!ProcessTrailingWhitespace(tryParse, value, i, ref exc))
-                    return false;
-            }
-
-            if (!digitsSeen)
-            {
-                if (!tryParse)
-                    exc = GetFormatException();
-                return false;
-            }
-
-            if (val._sign == 0)
-                result = val;
-            else if (sign == -1)
-                result = new BigInteger(-1, val._data);
-            else
-                result = new BigInteger(1, val._data);
-
-            return true;
-        }
-
-        /// <summary>
-        /// Returns the smaller of two <see cref="BigInteger"/> values.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// The <paramref name="left"/> or <paramref name="right"/> parameter, whichever is smaller.
-        /// </returns>
-        public static BigInteger Min(BigInteger left, BigInteger right)
-        {
-            int ls = left._sign;
-            int rs = right._sign;
-
-            if (ls < rs)
-                return left;
-            if (rs < ls)
-                return right;
-
-            var r = CoreCompare(left._data, right._data);
-            if (ls == -1)
-                r = -r;
-
-            if (r <= 0)
-                return left;
-            return right;
-        }
-
-        /// <summary>
-        /// Returns the larger of two <see cref="BigInteger"/> values.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// The <paramref name="left"/> or <paramref name="right"/> parameter, whichever is larger.
-        /// </returns>
-        public static BigInteger Max(BigInteger left, BigInteger right)
-        {
-            int ls = left._sign;
-            int rs = right._sign;
-
-            if (ls > rs)
-                return left;
-            if (rs > ls)
-                return right;
-
-            var r = CoreCompare(left._data, right._data);
-            if (ls == -1)
-                r = -r;
-
-            if (r >= 0)
-                return left;
-            return right;
-        }
-
-        /// <summary>
-        /// Gets the absolute value of a <see cref="BigInteger"/> object.
-        /// </summary>
-        /// <param name="value">A number.</param>
-        /// <returns>
-        /// The absolute value of <paramref name="value"/>.
-        /// </returns>
-        public static BigInteger Abs(BigInteger value)
-        {
-            return new BigInteger((short)Math.Abs(value._sign), value._data);
-        }
-
-        /// <summary>
-        /// Divides one <see cref="BigInteger"/> value by another, returns the result, and returns the remainder in
-        /// an output parameter.
-        /// </summary>
-        /// <param name="dividend">The value to be divided.</param>
-        /// <param name="divisor">The value to divide by.</param>
-        /// <param name="remainder">When this method returns, contains a <see cref="BigInteger"/> value that represents the remainder from the division. This parameter is passed uninitialized.</param>
-        /// <returns>
-        /// The quotient of the division.
-        /// </returns>
-        public static BigInteger DivRem(BigInteger dividend, BigInteger divisor, out BigInteger remainder)
-        {
-            if (divisor._sign == 0)
-                throw new DivideByZeroException();
-
-            if (dividend._sign == 0)
-            {
-                remainder = dividend;
-                return dividend;
-            }
-
-            uint[] quotient;
-            uint[] remainderValue;
-
-            DivModUnsigned(dividend._data, divisor._data, out quotient, out remainderValue);
-
-            int i;
-            for (i = remainderValue.Length - 1; i >= 0 && remainderValue[i] == 0; --i) ;
-            if (i == -1)
-            {
-                remainder = Zero;
-            }
-            else
-            {
-                if (i < remainderValue.Length - 1)
-                    Array.Resize(ref remainderValue, i + 1);
-                remainder = new BigInteger(dividend._sign, remainderValue);
-            }
-
-            for (i = quotient.Length - 1; i >= 0 && quotient[i] == 0; --i) ;
-            if (i == -1)
-                return Zero;
-            if (i < quotient.Length - 1)
-                Array.Resize(ref quotient, i + 1);
-
-            return new BigInteger((short)(dividend._sign * divisor._sign), quotient);
-        }
-
-        /// <summary>
-        /// Raises a <see cref="BigInteger"/> value to the power of a specified value.
-        /// </summary>
-        /// <param name="value">The number to raise to the <paramref name="exponent"/> power.</param>
-        /// <param name="exponent">The exponent to raise <paramref name="value"/> by.</param>
-        /// <returns>
-        /// The result of raising <paramref name="value"/> to the <paramref name="exponent"/> power.
-        /// </returns>
-        public static BigInteger Pow(BigInteger value, int exponent)
-        {
-            if (exponent < 0)
-                throw new ArgumentOutOfRangeException("exponent", "exp must be >= 0");
-            if (exponent == 0)
-                return One;
-            if (exponent == 1)
-                return value;
-
-            var result = One;
-            while (exponent != 0)
-            {
-                if ((exponent & 1) != 0)
-                    result = result * value;
-                if (exponent == 1)
-                    break;
-
-                value = value * value;
-                exponent >>= 1;
-            }
-            return result;
-        }
-
-        /// <summary>
-        /// Performs modulus division on a number raised to the power of another number.
-        /// </summary>
-        /// <param name="value">The number to raise to the <paramref name="exponent"/> power.</param>
-        /// <param name="exponent">The exponent to raise <paramref name="value"/> by.</param>
-        /// <param name="modulus">The number by which to divide <paramref name="value"/> raised to the <paramref name="exponent"/> power.</param>
-        /// <returns>
-        /// The remainder after dividing <paramref name="value"/> raised by <paramref name="exponent"/> by
-        /// <paramref name="modulus"/>.
-        /// </returns>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="exponent"/> is negative.</exception>
-        public static BigInteger ModPow(BigInteger value, BigInteger exponent, BigInteger modulus)
-        {
-            if (exponent._sign == -1)
-                throw new ArgumentOutOfRangeException("exponent", "power must be >= 0");
-            if (modulus._sign == 0)
-                throw new DivideByZeroException();
-
-            var result = One % modulus;
-            while (exponent._sign != 0)
-            {
-                if (!exponent.IsEven)
-                {
-                    result = result * value;
-                    result = result % modulus;
-                }
-                if (exponent.IsOne)
-                    break;
-                value = value * value;
-                value = value % modulus;
-                exponent >>= 1;
-            }
-            return result;
-        }
-
-        /// <summary>
-        /// Finds the greatest common divisor of two <see cref="BigInteger"/> values.
-        /// </summary>
-        /// <param name="left">The first value.</param>
-        /// <param name="right">The second value.</param>
-        /// <returns>
-        /// The greatest common divisor of <paramref name="left"/> and <paramref name="right"/>.
-        /// </returns>
-        public static BigInteger GreatestCommonDivisor(BigInteger left, BigInteger right)
-        {
-            if (left._sign != 0 && left._data.Length == 1 && left._data[0] == 1)
-                return One;
-            if (right._sign != 0 && right._data.Length == 1 && right._data[0] == 1)
-                return One;
-            if (left.IsZero)
-                return Abs(right);
-            if (right.IsZero)
-                return Abs(left);
-
-            var x = new BigInteger(1, left._data);
-            var y = new BigInteger(1, right._data);
-
-            var g = y;
-
-            while (x._data.Length > 1)
-            {
-                g = x;
-                x = y % x;
-                y = g;
-
-            }
-            if (x.IsZero) return g;
-
-            // TODO: should we have something here if we can convert to long?
-
-            //
-            // Now we can just do it with single precision. I am using the binary gcd method,
-            // as it should be faster.
-            //
-
-            var yy = x._data[0];
-            var xx = (uint)(y % yy);
-
-            var t = 0;
-
-            while (((xx | yy) & 1) == 0)
-            {
-                xx >>= 1; yy >>= 1; t++;
-            }
-            while (xx != 0)
-            {
-                while ((xx & 1) == 0) xx >>= 1;
-                while ((yy & 1) == 0) yy >>= 1;
-                if (xx >= yy)
-                    xx = (xx - yy) >> 1;
-                else
-                    yy = (yy - xx) >> 1;
-            }
-
-            return yy << t;
-        }
-
-        /*LAMESPEC Log doesn't specify to how many ulp is has to be precise
-		We are equilavent to MS with about 2 ULP
-		*/
-
-        /// <summary>
-        /// Returns the logarithm of a specified number in a specified base.
-        /// </summary>
-        /// <param name="value">A number whose logarithm is to be found.</param>
-        /// <param name="baseValue">The base of the logarithm.</param>
-        /// <returns>
-        /// The base <paramref name="baseValue"/> logarithm of value, 
-        /// </returns>
-        /// <exception cref="ArgumentOutOfRangeException">The log of <paramref name="value"/> is out of range of the <see cref="double"/> data type.</exception>
-        public static double Log(BigInteger value, double baseValue)
-        {
-            if (value._sign == -1 || baseValue == 1.0d || baseValue == -1.0d ||
-                    baseValue == double.NegativeInfinity || double.IsNaN(baseValue))
-                return double.NaN;
-
-            if (baseValue == 0.0d || baseValue == double.PositiveInfinity)
-                return value.IsOne ? 0 : double.NaN;
-
-            if (value._data == null)
-                return double.NegativeInfinity;
-
-            var length = value._data.Length - 1;
-            var bitCount = -1;
-            for (var curBit = 31; curBit >= 0; curBit--)
-            {
-                if ((value._data[length] & (1 << curBit)) != 0)
-                {
-                    bitCount = curBit + length * 32;
-                    break;
-                }
-            }
-
-            long bitlen = bitCount;
-            double c = 0, d = 1;
-
-            var testBit = One;
-            var tempBitlen = bitlen;
-            while (tempBitlen > int.MaxValue)
-            {
-                testBit = testBit << int.MaxValue;
-                tempBitlen -= int.MaxValue;
-            }
-            testBit = testBit << (int)tempBitlen;
-
-            for (var curbit = bitlen; curbit >= 0; --curbit)
-            {
-                if ((value & testBit)._sign != 0)
-                    c += d;
-                d *= 0.5;
-                testBit = testBit >> 1;
-            }
-            return (Math.Log(c) + Math.Log(2) * bitlen) / Math.Log(baseValue);
-        }
-
-        /// <summary>
-        /// Returns the natural (base <c>e</c>) logarithm of a specified number.
-        /// </summary>
-        /// <param name="value">The number whose logarithm is to be found.</param>
-        /// <returns>
-        /// The natural (base <c>e</c>) logarithm of <paramref name="value"/>.
-        /// </returns>
-        /// <exception cref="ArgumentOutOfRangeException">The base 10 log of value is out of range of the <see cref="double"/> data type.</exception>
-        public static double Log(BigInteger value)
-        {
-            return Log(value, Math.E);
-        }
-
-        /// <summary>
-        /// Returns the base 10 logarithm of a specified number.
-        /// </summary>
-        /// <param name="value">A number whose logarithm is to be found.</param>
-        /// <returns>
-        /// The base 10 logarithm of <paramref name="value"/>.
-        /// </returns>
-        /// <exception cref="ArgumentOutOfRangeException">The base 10 log of value is out of range of the <see cref="double"/> data type.</exception>
-        public static double Log10(BigInteger value)
-        {
-            return Log(value, 10);
-        }
-
-        /// <summary>
-        /// Returns a value that indicates whether the current instance and an unsigned 64-bit integer have the same value.
-        /// </summary>
-        /// <param name="other">The unsigned 64-bit integer to compare.</param>
-        /// <returns>
-        /// <c>true</c> if the current instance and the unsigned 64-bit integer have the same value; otherwise, <c>false</c>.
-        /// </returns>
-        [CLSCompliant(false)]
-        public bool Equals(ulong other)
-        {
-            return CompareTo(other) == 0;
-        }
-
-        /// <summary>
-        /// Returns the hash code for the current <see cref="BigInteger"/> object.
-        /// </summary>
-        /// <returns>
-        /// A 32-bit signed integer hash code.
-        /// </returns>
-        public override int GetHashCode()
-        {
-            var hash = (uint)(_sign * 0x01010101u);
-            if (_data != null)
-            {
-                foreach (var bit in _data)
-                    hash ^= bit;
-            }
-
-            return (int)hash;
-        }
-
-        /// <summary>
-        /// Adds two <see cref="BigInteger"/> values and returns the result.
-        /// </summary>
-        /// <param name="left">The first value to add.</param>
-        /// <param name="right">The second value to add.</param>
-        /// <returns>
-        /// The sum of <paramref name="left"/> and <paramref name="right"/>.
-        /// </returns>
-        public static BigInteger Add(BigInteger left, BigInteger right)
-        {
-            return left + right;
-        }
-
-        /// <summary>
-        /// Subtracts one <see cref="BigInteger"/> value from another and returns the result.
-        /// </summary>
-        /// <param name="left">The value to subtract from (the minuend).</param>
-        /// <param name="right">The value to subtract (the subtrahend).</param>
-        /// <returns>
-        /// The result of subtracting <paramref name="right"/> from <paramref name="left"/>.
-        /// </returns>
-        public static BigInteger Subtract(BigInteger left, BigInteger right)
-        {
-            return left - right;
-        }
-
-        /// <summary>
-        /// Returns the product of two <see cref="BigInteger"/> values.
-        /// </summary>
-        /// <param name="left">The first number to multiply.</param>
-        /// <param name="right">The second number to multiply.</param>
-        /// <returns>
-        /// The product of the <paramref name="left"/> and <paramref name="right"/> parameters.
-        /// </returns>
-        public static BigInteger Multiply(BigInteger left, BigInteger right)
-        {
-            return left * right;
-        }
-
-        /// <summary>
-        /// Divides one <see cref="BigInteger"/> value by another and returns the result.
-        /// </summary>
-        /// <param name="dividend">The value to be divided.</param>
-        /// <param name="divisor">The value to divide by.</param>
-        /// <returns>
-        /// The quotient of the division.
-        /// </returns>
-        public static BigInteger Divide(BigInteger dividend, BigInteger divisor)
-        {
-            return dividend / divisor;
-        }
-
-        /// <summary>
-        /// Performs integer division on two <see cref="BigInteger"/> values and returns the remainder.
-        /// </summary>
-        /// <param name="dividend">The value to be divided.</param>
-        /// <param name="divisor">The value to divide by.</param>
-        /// <returns>
-        /// The remainder after dividing <paramref name="dividend"/> by <paramref name="divisor"/>.
-        /// </returns>
-        public static BigInteger Remainder(BigInteger dividend, BigInteger divisor)
-        {
-            return dividend % divisor;
-        }
-
-        /// <summary>
-        /// Negates a specified <see cref="BigInteger"/> value.
-        /// </summary>
-        /// <param name="value">The value to negate.</param>
-        /// <returns>
-        /// The result of the <paramref name="value"/> parameter multiplied by negative one (-1).
-        /// </returns>
-        public static BigInteger Negate(BigInteger value)
-        {
-            return -value;
-        }
-
-        /// <summary>
-        /// Compares this instance to a specified object and returns an integer that indicates whether the value of
-        /// this instance is less than, equal to, or greater than the value of the specified object.
-        /// </summary>
-        /// <param name="obj">The object to compare.</param>
-        /// <returns>
-        /// A signed integer that indicates the relationship of the current instance to the <paramref name="obj"/> parameter,
-        /// as shown in the following table.
-        /// <list type="table">
-        ///     <listheader>
-        ///         <term>Value</term>
-        ///         <description>Condition</description>
-        ///     </listheader>
-        ///     <item>
-        ///         <term>Less than zero</term>
-        ///         <description>The current instance is less than <paramref name="obj"/>.</description>
-        ///     </item>
-        ///     <item>
-        ///         <term>Zero</term>
-        ///         <description>The current instance equals <paramref name="obj"/>.</description>
-        ///     </item>
-        ///     <item>
-        ///         <term>Greater than zero</term>
-        ///         <description>The current instance is greater than <paramref name="obj"/>.</description>
-        ///     </item>
-        /// </list>
-        /// </returns>
-        /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="BigInteger"/>.</exception>
-        public int CompareTo(object obj)
-        {
-            if (obj == null)
-                return 1;
-
-            if (!(obj is BigInteger))
-                return -1;
-
-            return Compare(this, (BigInteger)obj);
-        }
-
-        /// <summary>
-        /// Compares this instance to a second <see cref="BigInteger"/> and returns an integer that indicates whether the
-        /// value of this instance is less than, equal to, or greater than the value of the specified object.
-        /// </summary>
-        /// <param name="other">The object to compare.</param>
-        /// <returns>
-        /// A signed integer value that indicates the relationship of this instance to <paramref name="other"/>, as
-        /// shown in the following table.
-        /// <list type="table">
-        ///     <listheader>
-        ///         <term>Value</term>
-        ///         <description>Condition</description>
-        ///     </listheader>
-        ///     <item>
-        ///         <term>Less than zero</term>
-        ///         <description>The current instance is less than <paramref name="other"/>.</description>
-        ///     </item>
-        ///     <item>
-        ///         <term>Zero</term>
-        ///         <description>The current instance equals <paramref name="other"/>.</description>
-        ///     </item>
-        ///     <item>
-        ///         <term>Greater than zero</term>
-        ///         <description>The current instance is greater than <paramref name="other"/>.</description>
-        ///     </item>
-        /// </list>
-        /// </returns>
-        public int CompareTo(BigInteger other)
-        {
-            return Compare(this, other);
-        }
-
-        /// <summary>
-        /// Compares this instance to an unsigned 64-bit integer and returns an integer that indicates whether the value of this
-        /// instance is less than, equal to, or greater than the value of the unsigned 64-bit integer.
-        /// </summary>
-        /// <param name="other">The unsigned 64-bit integer to compare.</param>
-        /// <returns>
-        /// A signed integer that indicates the relative value of this instance and <paramref name="other"/>, as shown
-        /// in the following table.
-        /// <list type="table">
-        ///     <listheader>
-        ///         <term>Value</term>
-        ///         <description>Condition</description>
-        ///     </listheader>
-        ///     <item>
-        ///         <term>Less than zero</term>
-        ///         <description>The current instance is less than <paramref name="other"/>.</description>
-        ///     </item>
-        ///     <item>
-        ///         <term>Zero</term>
-        ///         <description>The current instance equals <paramref name="other"/>.</description>
-        ///     </item>
-        ///     <item>
-        ///         <term>Greater than zero</term>
-        ///         <description>The current instance is greater than <paramref name="other"/>.</description>
-        ///     </item>
-        /// </list>
-        /// </returns>
-        [CLSCompliant(false)]
-        public int CompareTo(ulong other)
-        {
-            if (_sign < 0)
-                return -1;
-            if (_sign == 0)
-                return other == 0 ? 0 : -1;
-
-            if (_data.Length > 2)
-                return 1;
-
-            var high = (uint)(other >> 32);
-            var low = (uint)other;
-
-            return LongCompare(low, high);
-        }
-
-        private int LongCompare(uint low, uint high)
-        {
-            uint h = 0;
-            if (_data.Length > 1)
-                h = _data[1];
-
-            if (h > high)
-                return 1;
-            if (h < high)
-                return -1;
-
-            var l = _data[0];
-
-            if (l > low)
-                return 1;
-            if (l < low)
-                return -1;
-
-            return 0;
-        }
-
-        /// <summary>
-        /// Compares this instance to a signed 64-bit integer and returns an integer that indicates whether the value of this
-        /// instance is less than, equal to, or greater than the value of the signed 64-bit integer.
-        /// </summary>
-        /// <param name="other">The signed 64-bit integer to compare.</param>
-        /// <returns>
-        /// A signed integer that indicates the relative value of this instance and <paramref name="other"/>, as shown
-        /// in the following table.
-        /// <list type="table">
-        ///     <listheader>
-        ///         <term>Value</term>
-        ///         <description>Condition</description>
-        ///     </listheader>
-        ///     <item>
-        ///         <term>Less than zero</term>
-        ///         <description>The current instance is less than <paramref name="other"/>.</description>
-        ///     </item>
-        ///     <item>
-        ///         <term>Zero</term>
-        ///         <description>The current instance equals <paramref name="other"/>.</description>
-        ///     </item>
-        ///     <item>
-        ///         <term>Greater than zero</term>
-        ///         <description>The current instance is greater than <paramref name="other"/>.</description>
-        ///     </item>
-        /// </list>
-        /// </returns>
-        public int CompareTo(long other)
-        {
-            int ls = _sign;
-            var rs = Math.Sign(other);
-
-            if (ls != rs)
-                return ls > rs ? 1 : -1;
-
-            if (ls == 0)
-                return 0;
-
-            if (_data.Length > 2)
-                return _sign;
-
-            if (other < 0)
-                other = -other;
-            var low = (uint)other;
-            var high = (uint)((ulong)other >> 32);
-
-            var r = LongCompare(low, high);
-            if (ls == -1)
-                r = -r;
-
-            return r;
-        }
-
-        /// <summary>
-        /// Compares two <see cref="BigInteger"/> values and returns an integer that indicates whether the first value is less than, equal to, or greater than the second value.
-        /// </summary>
-        /// <param name="left">The first value to compare.</param>
-        /// <param name="right">The second value to compare.</param>
-        /// <returns>
-        /// A signed integer that indicates the relative values of left and right, as shown in the following table.
-        /// <list type="table">
-        ///     <listheader>
-        ///         <term>Value</term>
-        ///         <description>Condition</description>
-        ///     </listheader>
-        ///     <item>
-        ///         <term>Less than zero</term>
-        ///         <description><paramref name="left"/> is less than <paramref name="right"/>.</description>
-        ///     </item>
-        ///     <item>
-        ///         <term>Zero</term>
-        ///         <description><paramref name="left"/> equals <paramref name="right"/>.</description>
-        ///     </item>
-        ///     <item>
-        ///         <term>Greater than zero</term>
-        ///         <description><paramref name="left"/> is greater than <paramref name="right"/>.</description>
-        ///     </item>
-        /// </list>
-        /// </returns>
-        public static int Compare(BigInteger left, BigInteger right)
-        {
-            int ls = left._sign;
-            int rs = right._sign;
-
-            if (ls != rs)
-                return ls > rs ? 1 : -1;
-
-            var r = CoreCompare(left._data, right._data);
-            if (ls < 0)
-                r = -r;
-            return r;
-        }
-
-        private static int TopByte(uint x)
-        {
-            if ((x & 0xFFFF0000u) != 0)
-            {
-                if ((x & 0xFF000000u) != 0)
-                    return 4;
-                return 3;
-            }
-            if ((x & 0xFF00u) != 0)
-                return 2;
-            return 1;
-        }
-
-        private static int FirstNonFfByte(uint word)
-        {
-            if ((word & 0xFF000000u) != 0xFF000000u)
-                return 4;
-            if ((word & 0xFF0000u) != 0xFF0000u)
-                return 3;
-            if ((word & 0xFF00u) != 0xFF00u)
-                return 2;
-            return 1;
-        }
-
-        /// <summary>
-        /// Converts a <see cref="BigInteger"/> value to a byte array.
-        /// </summary>
-        /// <returns>
-        /// The value of the current <see cref="BigInteger"/> object converted to an array of bytes.
-        /// </returns>
-        public byte[] ToByteArray()
-        {
-            if (_sign == 0)
-                return new byte[1];
-
-            //number of bytes not counting upper word
-            var bytes = (_data.Length - 1) * 4;
-            var needExtraZero = false;
-
-            var topWord = _data[_data.Length - 1];
-            int extra;
-
-            //if the topmost bit is set we need an extra 
-            if (_sign == 1)
-            {
-                extra = TopByte(topWord);
-                var mask = 0x80u << ((extra - 1) * 8);
-                if ((topWord & mask) != 0)
-                {
-                    needExtraZero = true;
-                }
-            }
-            else
-            {
-                extra = TopByte(topWord);
-            }
-
-            var res = new byte[bytes + extra + (needExtraZero ? 1 : 0)];
-            if (_sign == 1)
-            {
-                var j = 0;
-                var end = _data.Length - 1;
-                for (var i = 0; i < end; ++i)
-                {
-                    var word = _data[i];
-
-                    res[j++] = (byte)word;
-                    res[j++] = (byte)(word >> 8);
-                    res[j++] = (byte)(word >> 16);
-                    res[j++] = (byte)(word >> 24);
-                }
-                while (extra-- > 0)
-                {
-                    res[j++] = (byte)topWord;
-                    topWord >>= 8;
-                }
-            }
-            else
-            {
-                var j = 0;
-                var end = _data.Length - 1;
-
-                uint carry = 1, word;
-                ulong add;
-                for (var i = 0; i < end; ++i)
-                {
-                    word = _data[i];
-                    add = (ulong)~word + carry;
-                    word = (uint)add;
-                    carry = (uint)(add >> 32);
-
-                    res[j++] = (byte)word;
-                    res[j++] = (byte)(word >> 8);
-                    res[j++] = (byte)(word >> 16);
-                    res[j++] = (byte)(word >> 24);
-                }
-
-                add = (ulong)~topWord + (carry);
-                word = (uint)add;
-                carry = (uint)(add >> 32);
-                if (carry == 0)
-                {
-                    var ex = FirstNonFfByte(word);
-                    var needExtra = (word & (1 << (ex * 8 - 1))) == 0;
-                    var to = ex + (needExtra ? 1 : 0);
-
-                    if (to != extra)
-                        Array.Resize(ref res, bytes + to);
-
-                    while (ex-- > 0)
-                    {
-                        res[j++] = (byte)word;
-                        word >>= 8;
-                    }
-                    if (needExtra)
-                        res[j++] = 0xFF;
-                }
-                else
-                {
-                    Array.Resize(ref res, bytes + 5);
-                    res[j++] = (byte)word;
-                    res[j++] = (byte)(word >> 8);
-                    res[j++] = (byte)(word >> 16);
-                    res[j++] = (byte)(word >> 24);
-                    res[j++] = 0xFF;
-                }
-            }
-
-            return res;
-        }
-
-        private static uint[] CoreAdd(uint[] a, uint[] b)
-        {
-            if (a.Length < b.Length)
-            {
-                var tmp = a;
-                a = b;
-                b = tmp;
-            }
-
-            var bl = a.Length;
-            var sl = b.Length;
-
-            var res = new uint[bl];
-
-            ulong sum = 0;
-
-            var i = 0;
-            for (; i < sl; i++)
-            {
-                sum = sum + a[i] + b[i];
-                res[i] = (uint)sum;
-                sum >>= 32;
-            }
-
-            for (; i < bl; i++)
-            {
-                sum = sum + a[i];
-                res[i] = (uint)sum;
-                sum >>= 32;
-            }
-
-            if (sum != 0)
-            {
-                Array.Resize(ref res, bl + 1);
-                res[i] = (uint)sum;
-            }
-
-            return res;
-        }
-
-        /*invariant a > b*/
-        private static uint[] CoreSub(uint[] a, uint[] b)
-        {
-            var bl = a.Length;
-            var sl = b.Length;
-
-            var res = new uint[bl];
-
-            ulong borrow = 0;
-            int i;
-            for (i = 0; i < sl; ++i)
-            {
-                borrow = (ulong)a[i] - b[i] - borrow;
-
-                res[i] = (uint)borrow;
-                borrow = (borrow >> 32) & 0x1;
-            }
-
-            for (; i < bl; i++)
-            {
-                borrow = (ulong)a[i] - borrow;
-                res[i] = (uint)borrow;
-                borrow = (borrow >> 32) & 0x1;
-            }
-
-            //remove extra zeroes
-            for (i = bl - 1; i >= 0 && res[i] == 0; --i) ;
-            if (i < bl - 1)
-                Array.Resize(ref res, i + 1);
-
-            return res;
-        }
-
-        private static uint[] CoreAdd(uint[] a, uint b)
-        {
-            var len = a.Length;
-            var res = new uint[len];
-
-            ulong sum = b;
-            int i;
-            for (i = 0; i < len; i++)
-            {
-                sum = sum + a[i];
-                res[i] = (uint)sum;
-                sum >>= 32;
-            }
-
-            if (sum != 0)
-            {
-                Array.Resize(ref res, len + 1);
-                res[i] = (uint)sum;
-            }
-
-            return res;
-        }
-
-        private static uint[] CoreSub(uint[] a, uint b)
-        {
-            var len = a.Length;
-            var res = new uint[len];
-
-            ulong borrow = b;
-            int i;
-            for (i = 0; i < len; i++)
-            {
-                borrow = (ulong)a[i] - borrow;
-                res[i] = (uint)borrow;
-                borrow = (borrow >> 32) & 0x1;
-            }
-
-            //remove extra zeroes
-            for (i = len - 1; i >= 0 && res[i] == 0; --i) ;
-            if (i < len - 1)
-                Array.Resize(ref res, i + 1);
-
-            return res;
-        }
-
-        private static int CoreCompare(uint[] a, uint[] b)
-        {
-            var al = a != null ? a.Length : 0;
-            var bl = b != null ? b.Length : 0;
-
-            if (al > bl)
-                return 1;
-            if (bl > al)
-                return -1;
-
-            for (var i = al - 1; i >= 0; --i)
-            {
-                var ai = a[i];
-                var bi = b[i];
-                if (ai > bi)
-                    return 1;
-                if (ai < bi)
-                    return -1;
-            }
-            return 0;
-        }
-
-        private static int GetNormalizeShift(uint value)
-        {
-            var shift = 0;
-
-            if ((value & 0xFFFF0000) == 0) { value <<= 16; shift += 16; }
-            if ((value & 0xFF000000) == 0) { value <<= 8; shift += 8; }
-            if ((value & 0xF0000000) == 0) { value <<= 4; shift += 4; }
-            if ((value & 0xC0000000) == 0) { value <<= 2; shift += 2; }
-            if ((value & 0x80000000) == 0) { value <<= 1; shift += 1; }
-
-            return shift;
-        }
-
-        private static void Normalize(uint[] u, int l, uint[] un, int shift)
-        {
-            uint carry = 0;
-            int i;
-            if (shift > 0)
-            {
-                var rshift = 32 - shift;
-                for (i = 0; i < l; i++)
-                {
-                    var ui = u[i];
-                    un[i] = (ui << shift) | carry;
-                    carry = ui >> rshift;
-                }
-            }
-            else
-            {
-                for (i = 0; i < l; i++)
-                {
-                    un[i] = u[i];
-                }
-            }
-
-            while (i < un.Length)
-            {
-                un[i++] = 0;
-            }
-
-            if (carry != 0)
-            {
-                un[l] = carry;
-            }
-        }
-
-        private static void Unnormalize(uint[] un, out uint[] r, int shift)
-        {
-            var length = un.Length;
-            r = new uint[length];
-
-            if (shift > 0)
-            {
-                var lshift = 32 - shift;
-                uint carry = 0;
-                for (var i = length - 1; i >= 0; i--)
-                {
-                    var uni = un[i];
-                    r[i] = (uni >> shift) | carry;
-                    carry = (uni << lshift);
-                }
-            }
-            else
-            {
-                for (var i = 0; i < length; i++)
-                {
-                    r[i] = un[i];
-                }
-            }
-        }
-
-        private static void DivModUnsigned(uint[] u, uint[] v, out uint[] q, out uint[] r)
-        {
-            var m = u.Length;
-            var n = v.Length;
-
-            if (n <= 1)
-            {
-                //  Divide by single digit
-                //
-                ulong rem = 0;
-                var v0 = v[0];
-                q = new uint[m];
-                r = new uint[1];
-
-                for (var j = m - 1; j >= 0; j--)
-                {
-                    rem *= Base;
-                    rem += u[j];
-
-                    var div = rem / v0;
-                    rem -= div * v0;
-                    q[j] = (uint)div;
-                }
-                r[0] = (uint)rem;
-            }
-            else if (m >= n)
-            {
-                var shift = GetNormalizeShift(v[n - 1]);
-
-                var un = new uint[m + 1];
-                var vn = new uint[n];
-
-                Normalize(u, m, un, shift);
-                Normalize(v, n, vn, shift);
-
-                q = new uint[m - n + 1];
-                r = null;
-
-                //  Main division loop
-                //
-                for (var j = m - n; j >= 0; j--)
-                {
-                    int i;
-
-                    var rr = Base * un[j + n] + un[j + n - 1];
-                    var qq = rr / vn[n - 1];
-                    rr -= qq * vn[n - 1];
-
-                    for (;;)
-                    {
-                        // Estimate too big ?
-                        //
-                        if ((qq >= Base) || (qq * vn[n - 2] > (rr * Base + un[j + n - 2])))
-                        {
-                            qq--;
-                            rr += (ulong)vn[n - 1];
-                            if (rr < Base)
-                                continue;
-                        }
-                        break;
-                    }
-
-
-                    //  Multiply and subtract
-                    //
-                    long b = 0;
-                    long t = 0;
-                    for (i = 0; i < n; i++)
-                    {
-                        var p = vn[i] * qq;
-                        t = (long)un[i + j] - (long)(uint)p - b;
-                        un[i + j] = (uint)t;
-                        p >>= 32;
-                        t >>= 32;
-                        b = (long)p - t;
-                    }
-                    t = (long)un[j + n] - b;
-                    un[j + n] = (uint)t;
-
-                    //  Store the calculated value
-                    //
-                    q[j] = (uint)qq;
-
-                    //  Add back vn[0..n] to un[j..j+n]
-                    //
-                    if (t < 0)
-                    {
-                        q[j]--;
-                        ulong c = 0;
-                        for (i = 0; i < n; i++)
-                        {
-                            c = (ulong)vn[i] + un[j + i] + c;
-                            un[j + i] = (uint)c;
-                            c >>= 32;
-                        }
-                        c += (ulong)un[j + n];
-                        un[j + n] = (uint)c;
-                    }
-                }
-
-                Unnormalize(un, out r, shift);
-            }
-            else
-            {
-                q = new uint[] { 0 };
-                r = u;
-            }
-        }
-    }
-}
+//
+// System.Numerics.BigInteger
+//
+// Authors:
+//	Rodrigo Kumpera (rkumpera@novell.com)
+//	Marek Safar  <marek.safar@gmail.com>
+//
+// Copyright (C) 2010 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2014 Xamarin Inc (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// A big chuck of code comes the DLR (as hosted in http://ironpython.codeplex.com), 
+// which has the following License:
+//
+/* ****************************************************************************
+*
+* Copyright (c) Microsoft Corporation.
+*
+* This source code is subject to terms and conditions of the Microsoft Public License. A
+* copy of the license can be found in the License.html file at the root of this distribution. If
+* you cannot locate the Microsoft Public License, please send an email to
+* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+* by the terms of the Microsoft Public License.
+*
+* You must not remove this notice, or any other, from this software.
+*
+*
+* ***************************************************************************/
+//
+// slashdocs based on MSDN
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using Renci.SshNet.Security.Cryptography;
+
+/*
+Optimization
+	Have proper popcount function for IsPowerOfTwo
+	Use unsafe ops to avoid bounds check
+	CoreAdd could avoid some resizes by checking for equal sized array that top overflow
+	For bitwise operators, hoist the conditionals out of their main loop
+	Optimize BitScanBackward
+	Use a carry variable to make shift opts do half the number of array ops.
+	Schoolbook multiply is O(n^2), use Karatsuba /Toom-3 for large numbers
+*/
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Represents an arbitrarily large signed integer.
+    /// </summary>
+    [SuppressMessage("ReSharper", "EmptyEmbeddedStatement")]
+    [SuppressMessage("ReSharper", "RedundantCast")]
+    [SuppressMessage("ReSharper", "RedundantAssignment")]
+    [SuppressMessage("ReSharper", "SuggestBaseTypeForParameter")]
+    [SuppressMessage("ReSharper", "MergeConditionalExpression")]
+    public struct BigInteger : IComparable, IFormattable, IComparable<BigInteger>, IEquatable<BigInteger>
+    {
+        private static readonly BigInteger ZeroSingleton = new BigInteger(0);
+        private static readonly BigInteger OneSingleton = new BigInteger(1);
+        private static readonly BigInteger MinusOneSingleton = new BigInteger(-1);
+
+        private const ulong Base = 0x100000000;
+        private const int Bias = 1075;
+        private const int DecimalSignMask = unchecked((int) 0x80000000);
+
+        //LSB on [0]
+        private readonly uint[] _data;
+        private readonly short _sign;
+
+        #region SSH.NET additions
+
+        /// <summary>
+        /// Gets number of bits used by the number.
+        /// </summary>
+        /// <value>
+        /// The number of the bit used.
+        /// </value>
+        public int BitLength
+        {
+            get
+            {
+                if (_sign == 0)
+                    return 0;
+
+                var msbIndex = _data.Length - 1;
+
+                while (_data[msbIndex] == 0)
+                    msbIndex--;
+
+                var msbBitCount = BitScanBackward(_data[msbIndex]) + 1;
+
+                return msbIndex * 4 * 8 + msbBitCount + ((_sign > 0) ? 0 : 1);
+            }
+        }
+
+        /// <summary>
+        /// Mods the inverse.
+        /// </summary>
+        /// <param name="bi">The bi.</param>
+        /// <param name="modulus">The modulus.</param>
+        /// <returns>
+        /// Modulus inverted number.
+        /// </returns>
+        public static BigInteger ModInverse(BigInteger bi, BigInteger modulus)
+        {
+            BigInteger a = modulus, b = bi % modulus;
+            BigInteger p0 = 0, p1 = 1;
+
+            while (!b.IsZero)
+            {
+                if (b.IsOne)
+                    return p1;
+
+                p0 += (a / b) * p1;
+                a %= b;
+
+                if (a.IsZero)
+                    break;
+
+                if (a.IsOne)
+                    return modulus - p0;
+
+                p1 += (b / a) * p0;
+                b %= a;
+
+            }
+            return 0;
+        }
+
+        /// <summary>
+        /// Returns positive remainder that results from division with two specified <see cref="BigInteger"/> values.
+        /// </summary>
+        /// <param name="dividend">The value to be divided.</param>
+        /// <param name="divisor">The value to divide by.</param>
+        /// <returns>
+        /// Positive remainder that results from the division.
+        /// </returns>
+        public static BigInteger PositiveMod(BigInteger dividend, BigInteger divisor)
+        {
+            var result = dividend % divisor;
+            if (result < 0)
+                result += divisor;
+
+            return result;
+        }
+
+        /// <summary>
+        /// Generates random <see cref="BigInteger"/> number.
+        /// </summary>
+        /// <param name="bitLength">Length of random number in bits.</param>
+        /// <returns>
+        /// A random number.
+        /// </returns>
+        public static BigInteger Random(int bitLength)
+        {
+            var bytesArray = new byte[bitLength / 8 + (((bitLength % 8) > 0) ? 1 : 0)];
+            HashAlgorithmFactory.GenerateRandom(bytesArray);
+            bytesArray[bytesArray.Length - 1] = (byte)(bytesArray[bytesArray.Length - 1] & 0x7F);   //  Ensure not a negative value
+            return new BigInteger(bytesArray);
+        }
+
+        #endregion SSH.NET additions
+
+        private BigInteger(short sign, uint[] data)
+        {
+            _sign = sign;
+            _data = data;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BigInteger"/> structure using a 32-bit signed integer value.
+        /// </summary>
+        /// <param name="value">A 32-bit signed integer.</param>
+        public BigInteger(int value)
+        {
+            if (value == 0)
+            {
+                _sign = 0;
+                _data = null;
+            }
+            else if (value > 0)
+            {
+                _sign = 1;
+                _data = new[] {(uint) value};
+            }
+            else
+            {
+                _sign = -1;
+                _data = new[] {(uint) -value};
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BigInteger"/> structure using an unsigned 32-bit integer value.
+        /// </summary>
+        /// <param name="value">An unsigned 32-bit integer value.</param>
+        [CLSCompliant(false)]
+        public BigInteger(uint value)
+        {
+            if (value == 0)
+            {
+                _sign = 0;
+                _data = null;
+            }
+            else
+            {
+                _sign = 1;
+                _data = new[] { value };
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BigInteger"/> structure using a 64-bit signed integer value.
+        /// </summary>
+        /// <param name="value">A 64-bit signed integer.</param>
+        public BigInteger(long value)
+        {
+            if (value == 0)
+            {
+                _sign = 0;
+                _data = null;
+            }
+            else if (value > 0)
+            {
+                _sign = 1;
+                var low = (uint)value;
+                var high = (uint)(value >> 32);
+
+                _data = new uint[high != 0 ? 2 : 1];
+                _data[0] = low;
+                if (high != 0)
+                    _data[1] = high;
+            }
+            else
+            {
+                _sign = -1;
+                value = -value;
+                var low = (uint)value;
+                var high = (uint)((ulong)value >> 32);
+
+                _data = new uint[high != 0 ? 2 : 1];
+                _data[0] = low;
+                if (high != 0)
+                    _data[1] = high;
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BigInteger"/> structure with an unsigned 64-bit integer value.
+        /// </summary>
+        /// <param name="value">An unsigned 64-bit integer.</param>
+        [CLSCompliant(false)]
+        public BigInteger(ulong value)
+        {
+            if (value == 0)
+            {
+                _sign = 0;
+                _data = null;
+            }
+            else
+            {
+                _sign = 1;
+                var low = (uint)value;
+                var high = (uint)(value >> 32);
+
+                _data = new uint[high != 0 ? 2 : 1];
+                _data[0] = low;
+                if (high != 0)
+                    _data[1] = high;
+            }
+        }
+
+        private static bool Negative(byte[] v)
+        {
+            return ((v[7] & 0x80) != 0);
+        }
+
+        private static ushort Exponent(byte[] v)
+        {
+            return (ushort)((((ushort)(v[7] & 0x7F)) << (ushort)4) | (((ushort)(v[6] & 0xF0)) >> 4));
+        }
+
+        private static ulong Mantissa(byte[] v)
+        {
+            var i1 = ((uint)v[0] | ((uint)v[1] << 8) | ((uint)v[2] << 16) | ((uint)v[3] << 24));
+            var i2 = ((uint)v[4] | ((uint)v[5] << 8) | ((uint)(v[6] & 0xF) << 16));
+
+            return (ulong)((ulong)i1 | ((ulong)i2 << 32));
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BigInteger"/> structure using a double-precision floating-point value.
+        /// </summary>
+        /// <param name="value">A double-precision floating-point value.</param>
+        public BigInteger(double value)
+        {
+            if (double.IsNaN(value) || double.IsInfinity(value))
+                throw new OverflowException();
+
+            var bytes = BitConverter.GetBytes(value);
+            var mantissa = Mantissa(bytes);
+            if (mantissa == 0)
+            {
+                // 1.0 * 2**exp, we have a power of 2
+                int exponent = Exponent(bytes);
+                if (exponent == 0)
+                {
+                    _sign = 0;
+                    _data = null;
+                    return;
+                }
+
+                var res = Negative(bytes) ? MinusOne : One;
+                res = res << (exponent - 0x3ff);
+                _sign = res._sign;
+                _data = res._data;
+            }
+            else
+            {
+                // 1.mantissa * 2**exp
+                int exponent = Exponent(bytes);
+                mantissa |= 0x10000000000000ul;
+                BigInteger res = mantissa;
+                res = exponent > Bias ? res << (exponent - Bias) : res >> (Bias - exponent);
+
+                _sign = (short)(Negative(bytes) ? -1 : 1);
+                _data = res._data;
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BigInteger"/> structure using a single-precision floating-point value.
+        /// </summary>
+        /// <param name="value">A single-precision floating-point value.</param>
+        public BigInteger(float value) : this((double)value)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BigInteger"/> structure using a <see cref="decimal"/> value.
+        /// </summary>
+        /// <param name="value">A decimal number.</param>
+        public BigInteger(decimal value)
+        {
+            // First truncate to get scale to 0 and extract bits
+            var bits = decimal.GetBits(decimal.Truncate(value));
+
+            var size = 3;
+            while (size > 0 && bits[size - 1] == 0) size--;
+
+            if (size == 0)
+            {
+                _sign = 0;
+                _data = null;
+                return;
+            }
+
+            _sign = (short)((bits[3] & DecimalSignMask) != 0 ? -1 : 1);
+
+            _data = new uint[size];
+            _data[0] = (uint)bits[0];
+            if (size > 1)
+                _data[1] = (uint)bits[1];
+            if (size > 2)
+                _data[2] = (uint)bits[2];
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BigInteger"/> structure using the values in a byte array.
+        /// </summary>
+        /// <param name="value">An array of <see cref="byte"/> values in little-endian order.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c>.</exception>
+        [CLSCompliant(false)]
+        public BigInteger(byte[] value)
+        {
+            if (value == null)
+                throw new ArgumentNullException("value");
+
+            var len = value.Length;
+
+            if (len == 0 || (len == 1 && value[0] == 0))
+            {
+                _sign = 0;
+                _data = null;
+                return;
+            }
+
+            if ((value[len - 1] & 0x80) != 0)
+                _sign = -1;
+            else
+                _sign = 1;
+
+            if (_sign == 1)
+            {
+                while (value[len - 1] == 0)
+                {
+                    if (--len == 0)
+                    {
+                        _sign = 0;
+                        _data = null;
+                        return;
+                    }
+                }
+
+                int size;
+                var fullWords = size = len / 4;
+                if ((len & 0x3) != 0)
+                    ++size;
+
+                _data = new uint[size];
+                var j = 0;
+                for (var i = 0; i < fullWords; ++i)
+                {
+                    _data[i] = (uint) value[j++] |
+                               (uint) (value[j++] << 8) |
+                               (uint) (value[j++] << 16) |
+                               (uint) (value[j++] << 24);
+                }
+                size = len & 0x3;
+                if (size > 0)
+                {
+                    var idx = _data.Length - 1;
+                    for (var i = 0; i < size; ++i)
+                        _data[idx] |= (uint)(value[j++] << (i * 8));
+                }
+            }
+            else
+            {
+                int size;
+                var fullWords = size = len / 4;
+                if ((len & 0x3) != 0)
+                    ++size;
+
+                _data = new uint[size];
+
+                uint word, borrow = 1;
+                ulong sub;
+                var j = 0;
+
+                for (var i = 0; i < fullWords; ++i)
+                {
+                    word = (uint) value[j++] |
+                           (uint) (value[j++] << 8) |
+                           (uint) (value[j++] << 16) |
+                           (uint) (value[j++] << 24);
+
+                    sub = (ulong)word - borrow;
+                    word = (uint)sub;
+                    borrow = (uint)(sub >> 32) & 0x1u;
+                    _data[i] = ~word;
+                }
+                size = len & 0x3;
+
+                if (size > 0)
+                {
+                    word = 0;
+                    uint storeMask = 0;
+                    for (var i = 0; i < size; ++i)
+                    {
+                        word |= (uint)(value[j++] << (i * 8));
+                        storeMask = (storeMask << 8) | 0xFF;
+                    }
+
+                    sub = word - borrow;
+                    word = (uint)sub;
+                    borrow = (uint)(sub >> 32) & 0x1u;
+
+                    if ((~word & storeMask) == 0)
+                        Array.Resize(ref _data, _data.Length - 1);
+                    else
+                        _data[_data.Length - 1] = ~word & storeMask;
+                }
+                if (borrow != 0) //FIXME I believe this can't happen, can someone write a test for it?
+                    throw new Exception("non zero final carry");
+            }
+        }
+
+        /// <summary>
+        /// Indicates whether the value of the current <see cref="BigInteger"/> object is an even number.
+        /// </summary>
+        /// <value>
+        /// <c>true</c> if the value of the BigInteger object is an even number; otherwise, <c>false</c>.
+        /// </value>
+        public bool IsEven
+        {
+            get { return _sign == 0 || (_data[0] & 0x1) == 0; }
+        }
+
+        /// <summary>
+        /// Indicates whether the value of the current <see cref="BigInteger"/> object is <see cref="One"/>.
+        /// </summary>
+        /// <value>
+        /// <c>true</c> if the value of the <see cref="BigInteger"/> object is <see cref="One"/>;
+        /// otherwise, <c>false</c>.
+        /// </value>
+        public bool IsOne
+        {
+            get { return _sign == 1 && _data.Length == 1 && _data[0] == 1; }
+        }
+
+
+        //Gem from Hacker's Delight
+        //Returns the number of bits set in @x
+        static int PopulationCount(uint x)
+        {
+            x = x - ((x >> 1) & 0x55555555);
+            x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
+            x = (x + (x >> 4)) & 0x0F0F0F0F;
+            x = x + (x >> 8);
+            x = x + (x >> 16);
+            return (int)(x & 0x0000003F);
+        }
+
+        //Based on code by Zilong Tan on Ulib released under MIT license
+        //Returns the number of bits set in @x
+        static int PopulationCount(ulong x)
+        {
+            x -= (x >> 1) & 0x5555555555555555UL;
+            x = (x & 0x3333333333333333UL) + ((x >> 2) & 0x3333333333333333UL);
+            x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0fUL;
+            return (int)((x * 0x0101010101010101UL) >> 56);
+        }
+
+        static int LeadingZeroCount(uint value)
+        {
+            value |= value >> 1;
+            value |= value >> 2;
+            value |= value >> 4;
+            value |= value >> 8;
+            value |= value >> 16;
+            return 32 - PopulationCount(value); // 32 = bits in uint
+        }
+
+        static int LeadingZeroCount(ulong value)
+        {
+            value |= value >> 1;
+            value |= value >> 2;
+            value |= value >> 4;
+            value |= value >> 8;
+            value |= value >> 16;
+            value |= value >> 32;
+            return 64 - PopulationCount(value); // 64 = bits in ulong
+        }
+
+        static double BuildDouble(int sign, ulong mantissa, int exponent)
+        {
+            const int exponentBias = 1023;
+            const int mantissaLength = 52;
+            const int exponentLength = 11;
+            const int maxExponent = 2046;
+            const long mantissaMask = 0xfffffffffffffL;
+            const long exponentMask = 0x7ffL;
+            const ulong negativeMark = 0x8000000000000000uL;
+
+            if (sign == 0 || mantissa == 0)
+            {
+                return 0.0;
+            }
+
+            exponent += exponentBias + mantissaLength;
+            var offset = LeadingZeroCount(mantissa) - exponentLength;
+            if (exponent - offset > maxExponent)
+            {
+                return sign > 0 ? double.PositiveInfinity : double.NegativeInfinity;
+            }
+            if (offset < 0)
+            {
+                mantissa >>= -offset;
+                exponent += -offset;
+            }
+            else if (offset >= exponent)
+            {
+                mantissa <<= exponent - 1;
+                exponent = 0;
+            }
+            else
+            {
+                mantissa <<= offset;
+                exponent -= offset;
+            }
+            mantissa = mantissa & mantissaMask;
+            if ((exponent & exponentMask) == exponent)
+            {
+                unchecked
+                {
+                    var bits = mantissa | ((ulong)exponent << mantissaLength);
+                    if (sign < 0)
+                    {
+                        bits |= negativeMark;
+                    }
+                    return BitConverter.Int64BitsToDouble((long)bits);
+                }
+            }
+            return sign > 0 ? double.PositiveInfinity : double.NegativeInfinity;
+        }
+
+        /// <summary>
+        /// Indicates whether the value of the current <see cref="BigInteger"/> object is a power of two.
+        /// </summary>
+        /// <value>
+        /// <c>true</c> if the value of the <see cref="BigInteger"/> object is a power of two;
+        /// otherwise, <c>false</c>.
+        /// </value>
+        public bool IsPowerOfTwo
+        {
+            get
+            {
+                var foundBit = false;
+                if (_sign != 1)
+                    return false;
+                //This function is pop count == 1 for positive numbers
+                foreach (var bit in _data)
+                {
+                    var p = PopulationCount(bit);
+                    if (p > 0)
+                    {
+                        if (p > 1 || foundBit)
+                            return false;
+                        foundBit = true;
+                    }
+                }
+                return foundBit;
+            }
+        }
+
+        /// <summary>
+        /// Indicates whether the value of the current <see cref="BigInteger"/> object is <see cref="Zero"/>.
+        /// </summary>
+        /// <value>
+        /// <c>true</c> if the value of the <see cref="BigInteger"/> object is <see cref="Zero"/>;
+        /// otherwise, <c>false</c>.
+        /// </value>
+        public bool IsZero
+        {
+            get { return _sign == 0; }
+        }
+
+        /// <summary>
+        /// Gets a number that indicates the sign (negative, positive, or zero) of the current <see cref="BigInteger"/> object.
+        /// </summary>
+        /// <value>
+        /// A number that indicates the sign of the <see cref="BigInteger"/> object.
+        /// </value>
+        public int Sign
+        {
+            get { return _sign; }
+        }
+
+        /// <summary>
+        /// Gets a value that represents the number negative one (-1).
+        /// </summary>
+        /// <value>
+        /// An integer whose value is negative one (-1).
+        /// </value>
+        public static BigInteger MinusOne
+        {
+            get { return MinusOneSingleton; }
+        }
+
+        /// <summary>
+        /// Gets a value that represents the number one (1).
+        /// </summary>
+        /// <value>
+        /// An object whose value is one (1).
+        /// </value>
+        public static BigInteger One
+        {
+            get { return OneSingleton; }
+        }
+
+        /// <summary>
+        /// Gets a value that represents the number 0 (zero).
+        /// </summary>
+        /// <value>
+        /// An integer whose value is 0 (zero).
+        /// </value>
+        public static BigInteger Zero
+        {
+            get { return ZeroSingleton; }
+        }
+
+        /// <summary>
+        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a 32-bit signed integer value.
+        /// </summary>
+        /// <param name="value">The value to convert to a 32-bit signed integer.</param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        public static explicit operator int(BigInteger value)
+        {
+            if (value._data == null)
+                return 0;
+            if (value._data.Length > 1)
+                throw new OverflowException();
+            var data = value._data[0];
+
+            if (value._sign == 1)
+            {
+                if (data > (uint)int.MaxValue)
+                    throw new OverflowException();
+                return (int)data;
+            }
+            if (value._sign == -1)
+            {
+                if (data > 0x80000000u)
+                    throw new OverflowException();
+                return -(int)data;
+            }
+
+            return 0;
+        }
+
+        /// <summary>
+        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to an unsigned 32-bit integer value.
+        /// </summary>
+        /// <param name="value">The value to convert to an unsigned 32-bit integer.</param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        [CLSCompliant(false)]
+        public static explicit operator uint(BigInteger value)
+        {
+            if (value._data == null)
+                return 0;
+            if (value._data.Length > 1 || value._sign == -1)
+                throw new OverflowException();
+            return value._data[0];
+        }
+
+        /// <summary>
+        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a 16-bit signed integer value.
+        /// </summary>
+        /// <param name="value">The value to convert to a 16-bit signed integer.</param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        public static explicit operator short(BigInteger value)
+        {
+            var val = (int)value;
+            if (val < short.MinValue || val > short.MaxValue)
+                throw new OverflowException();
+            return (short)val;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="value"></param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        [CLSCompliantAttribute(false)]
+        public static explicit operator ushort(BigInteger value)
+        {
+            var val = (uint)value;
+            if (val > ushort.MaxValue)
+                throw new OverflowException();
+            return (ushort)val;
+        }
+
+        /// <summary>
+        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to an unsigned byte value.
+        /// </summary>
+        /// <param name="value">The value to convert to a <see cref="byte"/>.</param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        public static explicit operator byte(BigInteger value)
+        {
+            var val = (uint)value;
+            if (val > byte.MaxValue)
+                throw new OverflowException();
+            return (byte)val;
+        }
+
+        /// <summary>
+        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a signed 8-bit value.
+        /// </summary>
+        /// <param name="value">The value to convert to a signed 8-bit value.</param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        [CLSCompliant(false)]
+        public static explicit operator sbyte(BigInteger value)
+        {
+            var val = (int)value;
+            if (val < sbyte.MinValue || val > sbyte.MaxValue)
+                throw new OverflowException();
+            return (sbyte)val;
+        }
+
+        /// <summary>
+        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a 64-bit signed integer value.
+        /// </summary>
+        /// <param name="value">The value to convert to a 64-bit signed integer.</param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        public static explicit operator long(BigInteger value)
+        {
+            if (value._data == null)
+                return 0;
+
+            if (value._data.Length > 2)
+                throw new OverflowException();
+
+            var low = value._data[0];
+
+            if (value._data.Length == 1)
+            {
+                if (value._sign == 1)
+                    return (long)low;
+                var res = (long)low;
+                return -res;
+            }
+
+            var high = value._data[1];
+
+            if (value._sign == 1)
+            {
+                if (high >= 0x80000000u)
+                    throw new OverflowException();
+                return (((long)high) << 32) | low;
+            }
+
+            /*
+            We cannot represent negative numbers smaller than long.MinValue.
+            Those values are encoded into what look negative numbers, so negating
+            them produces a positive value, that's why it's safe to check for that
+            condition.
+
+            long.MinValue works fine since it's bigint encoding looks like a negative
+            number, but since long.MinValue == -long.MinValue, we're good.
+            */
+
+            var result = -((((long)high) << 32) | (long)low);
+            if (result > 0)
+                throw new OverflowException();
+            return result;
+        }
+
+        /// <summary>
+        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to an unsigned 64-bit integer value.
+        /// </summary>
+        /// <param name="value">The value to convert to an unsigned 64-bit integer.</param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        [CLSCompliant(false)]
+        public static explicit operator ulong(BigInteger value)
+        {
+            if (value._data == null)
+                return 0;
+            if (value._data.Length > 2 || value._sign == -1)
+                throw new OverflowException();
+
+            var low = value._data[0];
+            if (value._data.Length == 1)
+                return low;
+
+            var high = value._data[1];
+            return (((ulong)high) << 32) | low;
+        }
+
+        /// <summary>
+        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a <see cref="double"/> value.
+        /// </summary>
+        /// <param name="value">The value to convert to a <see cref="double"/>.</param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        public static explicit operator double(BigInteger value)
+        {
+            if (value._data == null)
+                return 0.0;
+
+            switch (value._data.Length)
+            {
+                case 1:
+                    return BuildDouble(value._sign, value._data[0], 0);
+                case 2:
+                    return BuildDouble(value._sign, (ulong)value._data[1] << 32 | (ulong)value._data[0], 0);
+                default:
+                    var index = value._data.Length - 1;
+                    var word = value._data[index];
+                    var mantissa = ((ulong)word << 32) | value._data[index - 1];
+                    var missing = LeadingZeroCount(word) - 11; // 11 = bits in exponent
+                    if (missing > 0)
+                    {
+                        // add the missing bits from the next word
+                        mantissa = (mantissa << missing) | (value._data[index - 2] >> (32 - missing));
+                    }
+                    else
+                    {
+                        mantissa >>= -missing;
+                    }
+                    return BuildDouble(value._sign, mantissa, ((value._data.Length - 2) * 32) - missing);
+            }
+        }
+
+        /// <summary>
+        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a single-precision floating-point value.
+        /// </summary>
+        /// <param name="value">The value to convert to a single-precision floating-point value.</param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        public static explicit operator float(BigInteger value)
+        {
+            return (float)(double)value;
+        }
+
+        /// <summary>
+        /// Defines an explicit conversion of a <see cref="BigInteger"/> object to a <see cref="decimal"/> value.
+        /// </summary>
+        /// <param name="value">The value to convert to a <see cref="decimal"/>.</param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        public static explicit operator decimal(BigInteger value)
+        {
+            if (value._data == null)
+                return decimal.Zero;
+
+            var data = value._data;
+            if (data.Length > 3)
+                throw new OverflowException();
+
+            int lo = 0, mi = 0, hi = 0;
+            if (data.Length > 2)
+                hi = (int)data[2];
+            if (data.Length > 1)
+                mi = (int)data[1];
+            if (data.Length > 0)
+                lo = (int)data[0];
+
+            return new decimal(lo, mi, hi, value._sign < 0, 0);
+        }
+
+        /// <summary>
+        /// Defines an implicit conversion of a signed 32-bit integer to a <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        public static implicit operator BigInteger(int value)
+        {
+            return new BigInteger(value);
+        }
+
+        /// <summary>
+        /// Defines an implicit conversion of a 32-bit unsigned integer to a <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        [CLSCompliant(false)]
+        public static implicit operator BigInteger(uint value)
+        {
+            return new BigInteger(value);
+        }
+
+        /// <summary>
+        /// Defines an implicit conversion of a signed 16-bit integer to a BigInteger value.
+        /// </summary>
+        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        public static implicit operator BigInteger(short value)
+        {
+            return new BigInteger(value);
+        }
+
+        /// <summary>
+        /// Defines an implicit conversion of a 16-bit unsigned integer to a <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        [CLSCompliantAttribute(false)]
+        public static implicit operator BigInteger(ushort value)
+        {
+            return new BigInteger(value);
+        }
+
+        /// <summary>
+        /// Defines an implicit conversion of an unsigned byte to a <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        public static implicit operator BigInteger(byte value)
+        {
+            return new BigInteger(value);
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        [CLSCompliant(false)]
+        public static implicit operator BigInteger(sbyte value)
+        {
+            return new BigInteger(value);
+        }
+
+        /// <summary>
+        /// Defines an implicit conversion of a signed 64-bit integer to a <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        public static implicit operator BigInteger(long value)
+        {
+            return new BigInteger(value);
+        }
+
+        /// <summary>
+        /// Defines an implicit conversion of a 64-bit unsigned integer to a <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        [CLSCompliant(false)]
+        public static implicit operator BigInteger(ulong value)
+        {
+            return new BigInteger(value);
+        }
+
+        /// <summary>
+        /// Defines an explicit conversion of a <see cref="double"/> value to a <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        public static explicit operator BigInteger(double value)
+        {
+            return new BigInteger(value);
+        }
+
+        /// <summary>
+        /// Defines an explicit conversion of a <see cref="float"/> object to a <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        public static explicit operator BigInteger(float value)
+        {
+            return new BigInteger(value);
+        }
+
+        /// <summary>
+        /// Defines an explicit conversion of a <see cref="decimal"/> object to a <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
+        /// <returns>
+        /// An object that contains the value of the <paramref name="value"/> parameter.
+        /// </returns>
+        public static explicit operator BigInteger(decimal value)
+        {
+            return new BigInteger(value);
+        }
+
+        /// <summary>
+        /// Adds the values of two specified <see cref="BigInteger"/> objects.
+        /// </summary>
+        /// <param name="left">The first value to add.</param>
+        /// <param name="right">The second value to add.</param>
+        /// <returns>
+        /// The sum of <paramref name="left"/> and <paramref name="right"/>.
+        /// </returns>
+        public static BigInteger operator +(BigInteger left, BigInteger right)
+        {
+            if (left._sign == 0)
+                return right;
+            if (right._sign == 0)
+                return left;
+
+            if (left._sign == right._sign)
+                return new BigInteger(left._sign, CoreAdd(left._data, right._data));
+
+            var r = CoreCompare(left._data, right._data);
+
+            if (r == 0)
+                return Zero;
+
+            if (r > 0) //left > right
+                return new BigInteger(left._sign, CoreSub(left._data, right._data));
+
+            return new BigInteger(right._sign, CoreSub(right._data, left._data));
+        }
+
+        /// <summary>
+        /// Subtracts a <see cref="BigInteger"/> value from another <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="left">The value to subtract from (the minuend).</param>
+        /// <param name="right">The value to subtract (the subtrahend).</param>
+        /// <returns>
+        /// The result of subtracting <paramref name="right"/> from <paramref name="left"/>.
+        /// </returns>
+        public static BigInteger operator -(BigInteger left, BigInteger right)
+        {
+            if (right._sign == 0)
+                return left;
+            if (left._sign == 0)
+                return new BigInteger((short)-right._sign, right._data);
+
+            if (left._sign == right._sign)
+            {
+                var r = CoreCompare(left._data, right._data);
+
+                if (r == 0)
+                    return Zero;
+
+                if (r > 0) //left > right
+                    return new BigInteger(left._sign, CoreSub(left._data, right._data));
+
+                return new BigInteger((short)-right._sign, CoreSub(right._data, left._data));
+            }
+
+            return new BigInteger(left._sign, CoreAdd(left._data, right._data));
+        }
+
+        /// <summary>
+        /// Multiplies two specified <see cref="BigInteger"/> values.
+        /// </summary>
+        /// <param name="left">The first value to multiply.</param>
+        /// <param name="right">The second value to multiply.</param>
+        /// <returns>
+        /// The product of left and right.
+        /// </returns>
+        public static BigInteger operator *(BigInteger left, BigInteger right)
+        {
+            if (left._sign == 0 || right._sign == 0)
+                return Zero;
+
+            if (left._data[0] == 1 && left._data.Length == 1)
+            {
+                if (left._sign == 1)
+                    return right;
+                return new BigInteger((short)-right._sign, right._data);
+            }
+
+            if (right._data[0] == 1 && right._data.Length == 1)
+            {
+                if (right._sign == 1)
+                    return left;
+                return new BigInteger((short)-left._sign, left._data);
+            }
+
+            var a = left._data;
+            var b = right._data;
+
+            var res = new uint[a.Length + b.Length];
+
+            for (var i = 0; i < a.Length; ++i)
+            {
+                var ai = a[i];
+                var k = i;
+
+                ulong carry = 0;
+                for (var j = 0; j < b.Length; ++j)
+                {
+                    carry = carry + ((ulong)ai) * b[j] + res[k];
+                    res[k++] = (uint)carry;
+                    carry >>= 32;
+                }
+
+                while (carry != 0)
+                {
+                    carry += res[k];
+                    res[k++] = (uint)carry;
+                    carry >>= 32;
+                }
+            }
+
+            int m;
+            for (m = res.Length - 1; m >= 0 && res[m] == 0; --m) ;
+            if (m < res.Length - 1)
+                Array.Resize(ref res, m + 1);
+
+            return new BigInteger((short) (left._sign*right._sign), res);
+        }
+
+        /// <summary>
+        /// Divides a specified <see cref="BigInteger"/> value by another specified <see cref="BigInteger"/> value by using
+        /// integer division.
+        /// </summary>
+        /// <param name="dividend">The value to be divided.</param>
+        /// <param name="divisor">The value to divide by.</param>
+        /// <returns>
+        /// The integral result of the division.
+        /// </returns>
+        public static BigInteger operator /(BigInteger dividend, BigInteger divisor)
+        {
+            if (divisor._sign == 0)
+                throw new DivideByZeroException();
+
+            if (dividend._sign == 0)
+                return dividend;
+
+            uint[] quotient;
+            uint[] remainderValue;
+
+            DivModUnsigned(dividend._data, divisor._data, out quotient, out remainderValue);
+
+            int i;
+            for (i = quotient.Length - 1; i >= 0 && quotient[i] == 0; --i) ;
+            if (i == -1)
+                return Zero;
+            if (i < quotient.Length - 1)
+                Array.Resize(ref quotient, i + 1);
+
+            return new BigInteger((short)(dividend._sign * divisor._sign), quotient);
+        }
+
+        /// <summary>
+        /// Returns the remainder that results from division with two specified <see cref="BigInteger"/> values.
+        /// </summary>
+        /// <param name="dividend">The value to be divided.</param>
+        /// <param name="divisor">The value to divide by.</param>
+        /// <returns>
+        /// The remainder that results from the division.
+        /// </returns>
+        public static BigInteger operator %(BigInteger dividend, BigInteger divisor)
+        {
+            if (divisor._sign == 0)
+                throw new DivideByZeroException();
+
+            if (dividend._sign == 0)
+                return dividend;
+
+            uint[] quotient;
+            uint[] remainderValue;
+
+            DivModUnsigned(dividend._data, divisor._data, out quotient, out remainderValue);
+
+            int i;
+            for (i = remainderValue.Length - 1; i >= 0 && remainderValue[i] == 0; --i) ;
+            if (i == -1)
+                return Zero;
+
+            if (i < remainderValue.Length - 1)
+                Array.Resize(ref remainderValue, i + 1);
+            return new BigInteger(dividend._sign, remainderValue);
+        }
+
+        /// <summary>
+        /// Negates a specified <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="value">The value to negate.</param>
+        ///  <returns>
+        /// The result of the <paramref name="value"/> parameter multiplied by negative one (-1).
+        /// </returns>
+        public static BigInteger operator -(BigInteger value)
+        {
+            if (value._data == null)
+                return value;
+            return new BigInteger((short)-value._sign, value._data);
+        }
+
+        /// <summary>
+        /// Returns the value of the <see cref="BigInteger"/> operand.
+        /// </summary>
+        /// <param name="value">An integer value.</param>
+        /// <returns>
+        /// The value of the <paramref name="value"/> operand.
+        /// </returns>
+        /// <remarks>
+        /// The sign of the operand is unchanged.
+        /// </remarks>
+        public static BigInteger operator +(BigInteger value)
+        {
+            return value;
+        }
+
+        /// <summary>
+        /// Increments a <see cref="BigInteger"/> value by 1.
+        /// </summary>
+        /// <param name="value">The value to increment.</param>
+        /// <returns>
+        /// The value of the <paramref name="value"/> parameter incremented by 1.
+        /// </returns>
+        public static BigInteger operator ++(BigInteger value)
+        {
+            if (value._data == null)
+                return One;
+
+            var sign = value._sign;
+            var data = value._data;
+            if (data.Length == 1)
+            {
+                if (sign == -1 && data[0] == 1)
+                    return Zero;
+                if (sign == 0)
+                    return One;
+            }
+
+            data = sign == -1 ? CoreSub(data, 1) : CoreAdd(data, 1);
+
+            return new BigInteger(sign, data);
+        }
+
+        /// <summary>
+        /// Decrements a <see cref="BigInteger"/> value by 1.
+        /// </summary>
+        /// <param name="value">The value to decrement.</param>
+        /// <returns>
+        /// The value of the <paramref name="value"/> parameter decremented by 1.
+        /// </returns>
+        public static BigInteger operator --(BigInteger value)
+        {
+            if (value._data == null)
+                return MinusOne;
+
+            var sign = value._sign;
+            var data = value._data;
+            if (data.Length == 1)
+            {
+                if (sign == 1 && data[0] == 1)
+                    return Zero;
+                if (sign == 0)
+                    return MinusOne;
+            }
+
+            data = sign == -1 ? CoreAdd(data, 1) : CoreSub(data, 1);
+
+            return new BigInteger(sign, data);
+        }
+
+        /// <summary>
+        /// Performs a bitwise <c>And</c> operation on two <see cref="BigInteger"/> values.
+        /// </summary>
+        /// <param name="left">The first value.</param>
+        /// <param name="right">The second value.</param>
+        /// <returns>
+        /// The result of the bitwise <c>And</c> operation.
+        /// </returns>
+        public static BigInteger operator &(BigInteger left, BigInteger right)
+        {
+            if (left._sign == 0)
+                return left;
+
+            if (right._sign == 0)
+                return right;
+
+            var a = left._data;
+            var b = right._data;
+            int ls = left._sign;
+            int rs = right._sign;
+
+            var negRes = (ls == rs) && (ls == -1);
+
+            var result = new uint[Math.Max(a.Length, b.Length)];
+
+            ulong ac = 1, bc = 1, borrow = 1;
+
+            int i;
+            for (i = 0; i < result.Length; ++i)
+            {
+                uint va = 0;
+                if (i < a.Length)
+                    va = a[i];
+                if (ls == -1)
+                {
+                    ac = ~va + ac;
+                    va = (uint)ac;
+                    ac = (uint)(ac >> 32);
+                }
+
+                uint vb = 0;
+                if (i < b.Length)
+                    vb = b[i];
+                if (rs == -1)
+                {
+                    bc = ~vb + bc;
+                    vb = (uint)bc;
+                    bc = (uint)(bc >> 32);
+                }
+
+                var word = va & vb;
+
+                if (negRes)
+                {
+                    borrow = word - borrow;
+                    word = ~(uint)borrow;
+                    borrow = (uint)(borrow >> 32) & 0x1u;
+                }
+
+                result[i] = word;
+            }
+
+            for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) ;
+            if (i == -1)
+                return Zero;
+
+            if (i < result.Length - 1)
+                Array.Resize(ref result, i + 1);
+
+            return new BigInteger(negRes ? (short)-1 : (short)1, result);
+        }
+
+        /// <summary>
+        /// Performs a bitwise <c>Or</c> operation on two <see cref="BigInteger"/> values.
+        /// </summary>
+        /// <param name="left">The first value.</param>
+        /// <param name="right">The second value.</param>
+        /// <returns>
+        /// The result of the bitwise <c>Or</c> operation.
+        /// </returns>
+        public static BigInteger operator |(BigInteger left, BigInteger right)
+        {
+            if (left._sign == 0)
+                return right;
+
+            if (right._sign == 0)
+                return left;
+
+            var a = left._data;
+            var b = right._data;
+            int ls = left._sign;
+            int rs = right._sign;
+
+            var negRes = (ls == -1) || (rs == -1);
+
+            var result = new uint[Math.Max(a.Length, b.Length)];
+
+            ulong ac = 1, bc = 1, borrow = 1;
+
+            int i;
+            for (i = 0; i < result.Length; ++i)
+            {
+                uint va = 0;
+                if (i < a.Length)
+                    va = a[i];
+                if (ls == -1)
+                {
+                    ac = ~va + ac;
+                    va = (uint)ac;
+                    ac = (uint)(ac >> 32);
+                }
+
+                uint vb = 0;
+                if (i < b.Length)
+                    vb = b[i];
+                if (rs == -1)
+                {
+                    bc = ~vb + bc;
+                    vb = (uint)bc;
+                    bc = (uint)(bc >> 32);
+                }
+
+                var word = va | vb;
+
+                if (negRes)
+                {
+                    borrow = word - borrow;
+                    word = ~(uint)borrow;
+                    borrow = (uint)(borrow >> 32) & 0x1u;
+                }
+
+                result[i] = word;
+            }
+
+            for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) ;
+            if (i == -1)
+                return Zero;
+
+            if (i < result.Length - 1)
+                Array.Resize(ref result, i + 1);
+
+            return new BigInteger(negRes ? (short)-1 : (short)1, result);
+        }
+
+        /// <summary>
+        /// Performs a bitwise exclusive <c>Or</c> (<c>XOr</c>) operation on two <see cref="BigInteger"/> values.
+        /// </summary>
+        /// <param name="left">The first value.</param>
+        /// <param name="right">The second value.</param>
+        /// <returns>
+        /// The result of the bitwise <c>Or</c> operation.
+        /// </returns>
+        public static BigInteger operator ^(BigInteger left, BigInteger right)
+        {
+            if (left._sign == 0)
+                return right;
+
+            if (right._sign == 0)
+                return left;
+
+            var a = left._data;
+            var b = right._data;
+            int ls = left._sign;
+            int rs = right._sign;
+
+            var negRes = (ls == -1) ^ (rs == -1);
+
+            var result = new uint[Math.Max(a.Length, b.Length)];
+
+            ulong ac = 1, bc = 1, borrow = 1;
+
+            int i;
+            for (i = 0; i < result.Length; ++i)
+            {
+                uint va = 0;
+                if (i < a.Length)
+                    va = a[i];
+                if (ls == -1)
+                {
+                    ac = ~va + ac;
+                    va = (uint)ac;
+                    ac = (uint)(ac >> 32);
+                }
+
+                uint vb = 0;
+                if (i < b.Length)
+                    vb = b[i];
+                if (rs == -1)
+                {
+                    bc = ~vb + bc;
+                    vb = (uint)bc;
+                    bc = (uint)(bc >> 32);
+                }
+
+                var word = va ^ vb;
+
+                if (negRes)
+                {
+                    borrow = word - borrow;
+                    word = ~(uint)borrow;
+                    borrow = (uint)(borrow >> 32) & 0x1u;
+                }
+
+                result[i] = word;
+            }
+
+            for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) ;
+            if (i == -1)
+                return Zero;
+
+            if (i < result.Length - 1)
+                Array.Resize(ref result, i + 1);
+
+            return new BigInteger(negRes ? (short)-1 : (short)1, result);
+        }
+
+        /// <summary>
+        /// Returns the bitwise one's complement of a <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="value">An integer value.</param>
+        /// <returns>
+        /// The bitwise one's complement of <paramref name="value"/>.
+        /// </returns>
+        public static BigInteger operator ~(BigInteger value)
+        {
+            if (value._data == null)
+                return MinusOne;
+
+            var data = value._data;
+            int sign = value._sign;
+
+            var negRes = sign == 1;
+
+            var result = new uint[data.Length];
+
+            ulong carry = 1, borrow = 1;
+
+            int i;
+            for (i = 0; i < result.Length; ++i)
+            {
+                var word = data[i];
+                if (sign == -1)
+                {
+                    carry = ~word + carry;
+                    word = (uint)carry;
+                    carry = (uint)(carry >> 32);
+                }
+
+                word = ~word;
+
+                if (negRes)
+                {
+                    borrow = word - borrow;
+                    word = ~(uint)borrow;
+                    borrow = (uint)(borrow >> 32) & 0x1u;
+                }
+
+                result[i] = word;
+            }
+
+            for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) ;
+            if (i == -1)
+                return Zero;
+
+            if (i < result.Length - 1)
+                Array.Resize(ref result, i + 1);
+
+            return new BigInteger(negRes ? (short)-1 : (short)1, result);
+        }
+
+        //returns the 0-based index of the most significant set bit
+        //returns 0 if no bit is set, so extra care when using it
+        static int BitScanBackward(uint word)
+        {
+            for (var i = 31; i >= 0; --i)
+            {
+                var mask = 1u << i;
+                if ((word & mask) == mask)
+                    return i;
+            }
+            return 0;
+        }
+
+        /// <summary>
+        /// Shifts a <see cref="BigInteger"/> value a specified number of bits to the left.
+        /// </summary>
+        /// <param name="value">The value whose bits are to be shifted.</param>
+        /// <param name="shift">The number of bits to shift value to the left.</param>
+        /// <returns>
+        /// A value that has been shifted to the left by the specified number of bits.
+        /// </returns>
+        public static BigInteger operator <<(BigInteger value, int shift)
+        {
+            if (shift == 0 || value._data == null)
+                return value;
+            if (shift < 0)
+                return value >> -shift;
+
+            var data = value._data;
+            int sign = value._sign;
+
+            var topMostIdx = BitScanBackward(data[data.Length - 1]);
+            var bits = shift - (31 - topMostIdx);
+            var extraWords = (bits >> 5) + ((bits & 0x1F) != 0 ? 1 : 0);
+
+            var res = new uint[data.Length + extraWords];
+
+            var idxShift = shift >> 5;
+            var bitShift = shift & 0x1F;
+            var carryShift = 32 - bitShift;
+
+            if (carryShift == 32)
+            {
+                for (var i = 0; i < data.Length; ++i)
+                {
+                    var word = data[i];
+                    res[i + idxShift] |= word << bitShift;
+                }
+            }
+            else
+            {
+                for (var i = 0; i < data.Length; ++i)
+                {
+                    var word = data[i];
+                    res[i + idxShift] |= word << bitShift;
+                    if (i + idxShift + 1 < res.Length)
+                        res[i + idxShift + 1] = word >> carryShift;
+                }
+            }
+
+            return new BigInteger((short)sign, res);
+        }
+
+        /// <summary>
+        /// Shifts a <see cref="BigInteger"/> value a specified number of bits to the right.
+        /// </summary>
+        /// <param name="value">The value whose bits are to be shifted.</param>
+        /// <param name="shift">The number of bits to shift value to the right.</param>
+        /// <returns>
+        /// A value that has been shifted to the right by the specified number of bits.
+        /// </returns>
+        public static BigInteger operator >>(BigInteger value, int shift)
+        {
+            if (shift == 0 || value._sign == 0)
+                return value;
+            if (shift < 0)
+                return value << -shift;
+
+            var data = value._data;
+            int sign = value._sign;
+
+            var topMostIdx = BitScanBackward(data[data.Length - 1]);
+            var idxShift = shift >> 5;
+            var bitShift = shift & 0x1F;
+
+            var extraWords = idxShift;
+            if (bitShift > topMostIdx)
+                ++extraWords;
+            var size = data.Length - extraWords;
+
+            if (size <= 0)
+            {
+                if (sign == 1)
+                    return Zero;
+                return MinusOne;
+            }
+
+            var res = new uint[size];
+            var carryShift = 32 - bitShift;
+
+            if (carryShift == 32)
+            {
+                for (var i = data.Length - 1; i >= idxShift; --i)
+                {
+                    var word = data[i];
+
+                    if (i - idxShift < res.Length)
+                        res[i - idxShift] |= word >> bitShift;
+                }
+            }
+            else
+            {
+                for (var i = data.Length - 1; i >= idxShift; --i)
+                {
+                    var word = data[i];
+
+                    if (i - idxShift < res.Length)
+                        res[i - idxShift] |= word >> bitShift;
+                    if (i - idxShift - 1 >= 0)
+                        res[i - idxShift - 1] = word << carryShift;
+                }
+
+            }
+
+            //Round down instead of toward zero
+            if (sign == -1)
+            {
+                for (var i = 0; i < idxShift; i++)
+                {
+                    if (data[i] != 0u)
+                    {
+                        var tmp = new BigInteger((short)sign, res);
+                        --tmp;
+                        return tmp;
+                    }
+                }
+                if (bitShift > 0 && (data[idxShift] << carryShift) != 0u)
+                {
+                    var tmp = new BigInteger((short)sign, res);
+                    --tmp;
+                    return tmp;
+                }
+            }
+            return new BigInteger((short)sign, res);
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is less than another
+        /// <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> is less than <paramref name="right"/>; otherwise, <c>false</c>.
+        /// </returns>
+        public static bool operator <(BigInteger left, BigInteger right)
+        {
+            return Compare(left, right) < 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is less than a 64-bit signed integer.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if left is <paramref name="left"/> than <paramref name="right"/>; otherwise, <c>false</c>.
+        /// </returns>
+        public static bool operator <(BigInteger left, long right)
+        {
+            return left.CompareTo(right) < 0;
+        }
+
+
+        /// <summary>
+        /// Returns a value that indicates whether a 64-bit signed integer is less than a <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> is less than <paramref name="right"/>;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        public static bool operator <(long left, BigInteger right)
+        {
+            return right.CompareTo(left) > 0;
+        }
+
+
+        /// <summary>
+        /// Returns a value that indicates whether a 64-bit signed integer is less than a <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> is less than <paramref name="right"/>; otherwise, <c>false</c>.
+        /// </returns>
+        [CLSCompliant(false)]
+        public static bool operator <(BigInteger left, ulong right)
+        {
+            return left.CompareTo(right) < 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a 64-bit unsigned integer is less than a <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> is less than <paramref name="right"/>; otherwise, <c>false</c>.
+        /// </returns>
+        [CLSCompliant(false)]
+        public static bool operator <(ulong left, BigInteger right)
+        {
+            return right.CompareTo(left) > 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is less than or equal
+        /// to another <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> is less than or equal to <paramref name="right"/>;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        public static bool operator <=(BigInteger left, BigInteger right)
+        {
+            return Compare(left, right) <= 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is less than or equal
+        /// to a 64-bit signed integer.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> is less than or equal to <paramref name="right"/>;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        public static bool operator <=(BigInteger left, long right)
+        {
+            return left.CompareTo(right) <= 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a 64-bit signed integer is less than or equal to a <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> is less than or equal to <paramref name="right"/>;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        public static bool operator <=(long left, BigInteger right)
+        {
+            return right.CompareTo(left) >= 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is less than or equal to
+        /// a 64-bit unsigned integer.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> is less than or equal to <paramref name="right"/>;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        [CLSCompliant(false)]
+        public static bool operator <=(BigInteger left, ulong right)
+        {
+            return left.CompareTo(right) <= 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a 64-bit unsigned integer is less than or equal to a
+        /// <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> is less than or equal to <paramref name="right"/>;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        [CLSCompliant(false)]
+        public static bool operator <=(ulong left, BigInteger right)
+        {
+            return right.CompareTo(left) >= 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is greater than another
+        /// <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        public static bool operator >(BigInteger left, BigInteger right)
+        {
+            return Compare(left, right) > 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a <see cref="BigInteger"/> is greater than a 64-bit signed integer value.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        public static bool operator >(BigInteger left, long right)
+        {
+            return left.CompareTo(right) > 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a 64-bit signed integer is greater than a <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        public static bool operator >(long left, BigInteger right)
+        {
+            return right.CompareTo(left) < 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is greater than a 64-bit unsigned integer.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        [CLSCompliant(false)]
+        public static bool operator >(BigInteger left, ulong right)
+        {
+            return left.CompareTo(right) > 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a 64-bit unsigned integer is greater than a <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        [CLSCompliant(false)]
+        public static bool operator >(ulong left, BigInteger right)
+        {
+            return right.CompareTo(left) < 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is greater than or equal
+        /// to another <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        public static bool operator >=(BigInteger left, BigInteger right)
+        {
+            return Compare(left, right) >= 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is greater than or equal
+        /// to a 64-bit signed integer value.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        public static bool operator >=(BigInteger left, long right)
+        {
+            return left.CompareTo(right) >= 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a 64-bit signed integer is greater than or equal to a
+        /// <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        public static bool operator >=(long left, BigInteger right)
+        {
+            return right.CompareTo(left) <= 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a <see cref="BigInteger"/> value is greater than or equal to a
+        /// 64-bit unsigned integer value.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        [CLSCompliant(false)]
+        public static bool operator >=(BigInteger left, ulong right)
+        {
+            return left.CompareTo(right) >= 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a 64-bit unsigned integer is greater than or equal to a
+        /// <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> is greater than <paramref name="right"/>;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        [CLSCompliant(false)]
+        public static bool operator >=(ulong left, BigInteger right)
+        {
+            return right.CompareTo(left) <= 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether the values of two <see cref="BigInteger"/> objects are equal.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same value;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        public static bool operator ==(BigInteger left, BigInteger right)
+        {
+            return Compare(left, right) == 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a <see cref="BigInteger"/> value and a signed long integer value are equal.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same value;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        public static bool operator ==(BigInteger left, long right)
+        {
+            return left.CompareTo(right) == 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a signed long integer value and a <see cref="BigInteger"/> value are equal.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same value;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        public static bool operator ==(long left, BigInteger right)
+        {
+            return right.CompareTo(left) == 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a <see cref="BigInteger"/> value and an unsigned long integer value are equal.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same value;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        [CLSCompliant(false)]
+        public static bool operator ==(BigInteger left, ulong right)
+        {
+            return left.CompareTo(right) == 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether an unsigned long integer value and a <see cref="BigInteger"/> value are equal.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if the <paramref name="left"/> and <paramref name="right"/> parameters have the same value;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        [CLSCompliant(false)]
+        public static bool operator ==(ulong left, BigInteger right)
+        {
+            return right.CompareTo(left) == 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether two <see cref="BigInteger"/> objects have different values.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> and <paramref name="right"/> are not equal;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        public static bool operator !=(BigInteger left, BigInteger right)
+        {
+            return Compare(left, right) != 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a <see cref="BigInteger"/> value and a 64-bit signed integer are not equal.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> and <paramref name="right"/> are not equal;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        public static bool operator !=(BigInteger left, long right)
+        {
+            return left.CompareTo(right) != 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a 64-bit signed integer and a <see cref="BigInteger"/> value are not equal.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> and <paramref name="right"/> are not equal;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        public static bool operator !=(long left, BigInteger right)
+        {
+            return right.CompareTo(left) != 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a <see cref="BigInteger"/> value and a 64-bit unsigned integer are not equal.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> and <paramref name="right"/> are not equal;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        [CLSCompliant(false)]
+        public static bool operator !=(BigInteger left, ulong right)
+        {
+            return left.CompareTo(right) != 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether a 64-bit unsigned integer and a <see cref="BigInteger"/> value are not equal.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="left"/> and <paramref name="right"/> are not equal;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        [CLSCompliant(false)]
+        public static bool operator !=(ulong left, BigInteger right)
+        {
+            return right.CompareTo(left) != 0;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether the current instance and a specified object have the same value.
+        /// </summary>
+        /// <param name="obj">The object to compare.</param>
+        /// <returns>
+        /// <c>true</c> if the <paramref name="obj"/> parameter is a <see cref="BigInteger"/> object or a type capable
+        /// of implicit conversion to a <see cref="BigInteger"/> value, and its value is equal to the value of the
+        /// current <see cref="BigInteger"/> object; otherwise, <c>false</c>.
+        /// </returns>
+        public override bool Equals(object obj)
+        {
+            if (!(obj is BigInteger))
+                return false;
+            return Equals((BigInteger)obj);
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether the current instance and a specified <see cref="BigInteger"/> object
+        /// have the same value.
+        /// </summary>
+        /// <param name="other">The object to compare.</param>
+        /// <returns>
+        /// <c>true</c> if this <see cref="BigInteger"/> object and <paramref name="other"/> have the same value;
+        /// otherwise, <c>false</c>.
+        /// </returns>
+        public bool Equals(BigInteger other)
+        {
+            if (_sign != other._sign)
+                return false;
+
+            var alen = _data != null ? _data.Length : 0;
+            var blen = other._data != null ? other._data.Length : 0;
+
+            if (alen != blen)
+                return false;
+            for (var i = 0; i < alen; ++i)
+            {
+                if (_data[i] != other._data[i])
+                    return false;
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether the current instance and a signed 64-bit integer have the same value.
+        /// </summary>
+        /// <param name="other">The signed 64-bit integer value to compare.</param>
+        /// <returns>
+        /// <c>true</c> if the signed 64-bit integer and the current instance have the same value; otherwise, <c>false</c>.
+        /// </returns>
+        public bool Equals(long other)
+        {
+            return CompareTo(other) == 0;
+        }
+
+        /// <summary>
+        /// Converts the numeric value of the current <see cref="BigInteger"/> object to its equivalent string representation.
+        /// </summary>
+        /// <returns>
+        /// The string representation of the current <see cref="BigInteger"/> value.
+        /// </returns>
+        public override string ToString()
+        {
+            return ToString(10, null);
+        }
+
+        private string ToStringWithPadding(string format, uint radix, IFormatProvider provider)
+        {
+            if (format.Length > 1)
+            {
+                var precision = Convert.ToInt32(format.Substring(1), CultureInfo.InvariantCulture.NumberFormat);
+                var baseStr = ToString(radix, provider);
+                if (baseStr.Length < precision)
+                {
+                    var additional = new string('0', precision - baseStr.Length);
+                    if (baseStr[0] != '-')
+                    {
+                        return additional + baseStr;
+                    }
+                    return "-" + additional + baseStr.Substring(1);
+                }
+                return baseStr;
+            }
+            return ToString(radix, provider);
+        }
+
+        /// <summary>
+        /// Converts the numeric value of the current <see cref="BigInteger"/> object to its equivalent string representation
+        /// by using the specified format.
+        /// </summary>
+        /// <param name="format">A standard or custom numeric format string.</param>
+        /// <returns>
+        /// The string representation of the current <see cref="BigInteger"/> value in the format specified by the
+        /// <paramref name="format"/> parameter.
+        /// </returns>
+        /// <exception cref="FormatException"><paramref name="format"/> is not a valid format string.</exception>
+        public string ToString(string format)
+        {
+            return ToString(format, null);
+        }
+
+        /// <summary>
+        /// Converts the numeric value of the current <see cref="BigInteger"/> object to its equivalent string representation
+        /// by using the specified culture-specific formatting information. 
+        /// </summary>
+        /// <param name="provider">An object that supplies culture-specific formatting information.</param>
+        /// <returns>
+        /// The string representation of the current <see cref="BigInteger"/> value in the format specified by the
+        /// <paramref name="provider"/> parameter.
+        /// </returns>
+        public string ToString(IFormatProvider provider)
+        {
+            return ToString(null, provider);
+        }
+
+        /// <summary>
+        /// Converts the numeric value of the current <see cref="BigInteger"/> object to its equivalent string representation
+        /// by using the specified format and culture-specific format information.
+        /// </summary>
+        /// <param name="format">A standard or custom numeric format string.</param>
+        /// <param name="provider">An object that supplies culture-specific formatting information.</param>
+        /// <returns>
+        /// The string representation of the current <see cref="BigInteger"/> value as specified by the <paramref name="format"/>
+        /// and <paramref name="provider"/> parameters.
+        /// </returns>
+        public string ToString(string format, IFormatProvider provider)
+        {
+            if (string.IsNullOrEmpty(format))
+                return ToString(10, provider);
+
+            switch (format[0])
+            {
+                case 'd':
+                case 'D':
+                case 'g':
+                case 'G':
+                case 'r':
+                case 'R':
+                    return ToStringWithPadding(format, 10, provider);
+                case 'x':
+                case 'X':
+                    return ToStringWithPadding(format, 16, null);
+                default:
+                    throw new FormatException(string.Format("format '{0}' not implemented", format));
+            }
+        }
+
+        private static uint[] MakeTwoComplement(uint[] v)
+        {
+            var res = new uint[v.Length];
+
+            ulong carry = 1;
+            for (var i = 0; i < v.Length; ++i)
+            {
+                var word = v[i];
+                carry = (ulong)~word + carry;
+                word = (uint)carry;
+                carry = (uint)(carry >> 32);
+                res[i] = word;
+            }
+
+            var last = res[res.Length - 1];
+            var idx = FirstNonFfByte(last);
+            uint mask = 0xFF;
+            for (var i = 1; i < idx; ++i)
+                mask = (mask << 8) | 0xFF;
+
+            res[res.Length - 1] = last & mask;
+            return res;
+        }
+
+        private string ToString(uint radix, IFormatProvider provider)
+        {
+            const string characterSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+            if (characterSet.Length < radix)
+                throw new ArgumentException("charSet length less than radix", "characterSet");
+            if (radix == 1)
+                throw new ArgumentException("There is no such thing as radix one notation", "radix");
+
+            if (_sign == 0)
+                return "0";
+            if (_data.Length == 1 && _data[0] == 1)
+                return _sign == 1 ? "1" : "-1";
+
+            var digits = new List<char>(1 + _data.Length * 3 / 10);
+
+            BigInteger a;
+            if (_sign == 1)
+                a = this;
+            else
+            {
+                var dt = _data;
+                if (radix > 10)
+                    dt = MakeTwoComplement(dt);
+                a = new BigInteger(1, dt);
+            }
+
+            while (a != 0)
+            {
+                BigInteger rem;
+                a = DivRem(a, radix, out rem);
+                digits.Add(characterSet[(int)rem]);
+            }
+
+            if (_sign == -1 && radix == 10)
+            {
+                NumberFormatInfo info = null;
+                if (provider != null)
+                    info = provider.GetFormat(typeof(NumberFormatInfo)) as NumberFormatInfo;
+                if (info != null)
+                {
+                    var str = info.NegativeSign;
+                    for (var i = str.Length - 1; i >= 0; --i)
+                        digits.Add(str[i]);
+                }
+                else
+                {
+                    digits.Add('-');
+                }
+            }
+
+            var last = digits[digits.Count - 1];
+            if (_sign == 1 && radix > 10 && (last < '0' || last > '9'))
+                digits.Add('0');
+
+            digits.Reverse();
+
+            return new string(digits.ToArray());
+        }
+
+        /// <summary>
+        /// Converts the string representation of a number to its <see cref="BigInteger"/> equivalent.
+        /// </summary>
+        /// <param name="value">A string that contains the number to convert.</param>
+        /// <returns>
+        /// A value that is equivalent to the number specified in the <paramref name="value"/> parameter.
+        /// </returns>
+        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c>.</exception>
+        /// <exception cref="FormatException"><paramref name="value"/> is not in the correct format.</exception>
+        public static BigInteger Parse(string value)
+        {
+            Exception ex;
+            BigInteger result;
+
+            if (!Parse(value, false, out result, out ex))
+                throw ex;
+            return result;
+        }
+
+        /// <summary>
+        /// Converts the string representation of a number in a specified style to its <see cref="BigInteger"/> equivalent.
+        /// </summary>
+        /// <param name="value">A string that contains a number to convert.</param>
+        /// <param name="style">A bitwise combination of the enumeration values that specify the permitted format of <paramref name="value"/>.</param>
+        /// <returns>
+        /// A value that is equivalent to the number specified in the <paramref name="value"/> parameter.
+        /// </returns>
+        /// <exception cref="ArgumentException">
+        /// <para><paramref name="style"/> is not a <see cref="NumberStyles"/> value.</para>
+        /// <para>-or-</para>
+        /// <para><paramref name="style"/> includes the <see cref="NumberStyles.AllowHexSpecifier"/> or <see cref="NumberStyles.HexNumber"/> flag along with another value.</para>
+        /// </exception>
+        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c>.</exception>
+        /// <exception cref="FormatException"><paramref name="value"/> does not comply with the input pattern specified by <see cref="NumberStyles"/>.</exception>
+        public static BigInteger Parse(string value, NumberStyles style)
+        {
+            return Parse(value, style, null);
+        }
+
+        /// <summary>
+        /// Converts the string representation of a number in a specified style to its <see cref="BigInteger"/> equivalent.
+        /// </summary>
+        /// <param name="value">A string that contains a number to convert.</param>
+        /// <param name="provider">An object that provides culture-specific formatting information about <paramref name="value"/>.</param>
+        /// <returns>
+        /// A value that is equivalent to the number specified in the <paramref name="value"/> parameter.
+        /// </returns>
+        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c>.</exception>
+        /// <exception cref="FormatException"><paramref name="value"/> is not in the correct format.</exception>
+        public static BigInteger Parse(string value, IFormatProvider provider)
+        {
+            return Parse(value, NumberStyles.Integer, provider);
+        }
+
+        /// <summary>
+        /// Converts the string representation of a number in a specified style and culture-specific format to its <see cref="BigInteger"/> equivalent.
+        /// </summary>
+        /// <param name="value">A string that contains a number to convert.</param>
+        /// <param name="style">A bitwise combination of the enumeration values that specify the permitted format of <paramref name="value"/>.</param>
+        /// <param name="provider">An object that provides culture-specific formatting information about <paramref name="value"/>.</param>
+        /// <returns>
+        /// A value that is equivalent to the number specified in the <paramref name="value"/> parameter.
+        /// </returns>
+        /// <exception cref="ArgumentException">
+        /// <para><paramref name="style"/> is not a <see cref="NumberStyles"/> value.</para>
+        /// <para>-or-</para>
+        /// <para><paramref name="style"/> includes the <see cref="NumberStyles.AllowHexSpecifier"/> or <see cref="NumberStyles.HexNumber"/> flag along with another value.</para>
+        /// </exception>
+        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c>.</exception>
+        /// <exception cref="FormatException"><paramref name="value"/> does not comply with the input pattern specified by <see cref="NumberStyles"/>.</exception>
+        public static BigInteger Parse(string value, NumberStyles style, IFormatProvider provider)
+        {
+            Exception exc;
+            BigInteger res;
+
+            if (!Parse(value, style, provider, false, out res, out exc))
+                throw exc;
+
+            return res;
+        }
+
+        /// <summary>
+        /// Tries to convert the string representation of a number to its <see cref="BigInteger"/> equivalent, and
+        /// returns a value that indicates whether the conversion succeeded.
+        /// </summary>
+        /// <param name="value">The string representation of a number.</param>
+        /// <param name="result">When this method returns, contains the <see cref="BigInteger"/> equivalent to the number that is contained in value, or zero (0) if the conversion fails. The conversion fails if the <paramref name="value"/> parameter is <c>null</c> or is not of the correct format. This parameter is passed uninitialized.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="value"/> was converted successfully; otherwise, <c>false</c>.
+        /// </returns>
+        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c>.</exception>
+        public static bool TryParse(string value, out BigInteger result)
+        {
+            Exception ex;
+            return Parse(value, true, out result, out ex);
+        }
+
+        /// <summary>
+        /// Tries to convert the string representation of a number in a specified style and culture-specific format to its
+        /// <see cref="BigInteger"/> equivalent, and returns a value that indicates whether the conversion succeeded.
+        /// </summary>
+        /// <param name="value">The string representation of a number.</param>
+        /// <param name="style">A bitwise combination of enumeration values that indicates the style elements that can be present in <paramref name="value"/>.</param>
+        /// <param name="provider">An object that supplies culture-specific formatting information about <paramref name="value"/>.</param>
+        /// <param name="result">When this method returns, contains the <see cref="BigInteger"/> equivalent to the number that is contained in value, or <see cref="Zero"/> if the conversion fails. The conversion fails if the <paramref name="value"/> parameter is <c>null</c> or is not of the correct format. This parameter is passed uninitialized.</param>
+        /// <returns>
+        /// <c>true</c> if <paramref name="value"/> was converted successfully; otherwise, <c>false</c>.
+        /// </returns>
+        /// <exception cref="ArgumentException">
+        /// <para><paramref name="style"/> is not a <see cref="NumberStyles"/> value.</para>
+        /// <para>-or-</para>
+        /// <para><paramref name="style"/> includes the <see cref="NumberStyles.AllowHexSpecifier"/> or <see cref="NumberStyles.HexNumber"/> flag along with another value.</para>
+        /// </exception>
+        public static bool TryParse(string value, NumberStyles style, IFormatProvider provider, out BigInteger result)
+        {
+            Exception exc;
+            if (!Parse(value, style, provider, true, out result, out exc))
+            {
+                result = Zero;
+                return false;
+            }
+
+            return true;
+        }
+
+        private static bool Parse(string value, NumberStyles style, IFormatProvider fp, bool tryParse, out BigInteger result, out Exception exc)
+        {
+            result = Zero;
+            exc = null;
+
+            if (value == null)
+            {
+                if (!tryParse)
+                    exc = new ArgumentNullException("value");
+                return false;
+            }
+
+            if (value.Length == 0)
+            {
+                if (!tryParse)
+                    exc = GetFormatException();
+                return false;
+            }
+
+            NumberFormatInfo nfi = null;
+            if (fp != null)
+            {
+                var typeNfi = typeof(NumberFormatInfo);
+                nfi = (NumberFormatInfo) fp.GetFormat(typeNfi);
+            }
+            if (nfi == null)
+                nfi = NumberFormatInfo.CurrentInfo;
+
+            if (!CheckStyle(style, tryParse, ref exc))
+                return false;
+
+            var allowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
+            var allowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0;
+            var allowThousands = (style & NumberStyles.AllowThousands) != 0;
+            var allowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0;
+            var allowParentheses = (style & NumberStyles.AllowParentheses) != 0;
+            var allowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0;
+            var allowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
+            var allowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
+            var allowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
+            var allowExponent = (style & NumberStyles.AllowExponent) != 0;
+
+            var pos = 0;
+
+            if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc))
+                return false;
+
+            var foundOpenParentheses = false;
+            var negative = false;
+            var foundSign = false;
+            var foundCurrency = false;
+
+            // Pre-number stuff
+            if (allowParentheses && value[pos] == '(')
+            {
+                foundOpenParentheses = true;
+                foundSign = true;
+                negative = true; // MS always make the number negative when there parentheses
+                                 // even when NumberFormatInfo.NumberNegativePattern != 0!!!
+                pos++;
+                if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc))
+                    return false;
+
+                if (value.Substring(pos, nfi.NegativeSign.Length) == nfi.NegativeSign)
+                {
+                    if (!tryParse)
+                        exc = GetFormatException();
+                    return false;
+                }
+
+                if (value.Substring(pos, nfi.PositiveSign.Length) == nfi.PositiveSign)
+                {
+                    if (!tryParse)
+                        exc = GetFormatException();
+                    return false;
+                }
+            }
+
+            if (allowLeadingSign && !foundSign)
+            {
+                // Sign + Currency
+                FindSign(ref pos, value, nfi, ref foundSign, ref negative);
+                if (foundSign)
+                {
+                    if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc))
+                        return false;
+                    if (allowCurrencySymbol)
+                    {
+                        FindCurrency(ref pos, value, nfi,
+                                  ref foundCurrency);
+                        if (foundCurrency && allowLeadingWhite &&
+                            !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc))
+                            return false;
+                    }
+                }
+            }
+
+            if (allowCurrencySymbol && !foundCurrency)
+            {
+                // Currency + sign
+                FindCurrency(ref pos, value, nfi, ref foundCurrency);
+                if (foundCurrency)
+                {
+                    if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc))
+                        return false;
+                    if (foundCurrency)
+                    {
+                        if (!foundSign && allowLeadingSign)
+                        {
+                            FindSign(ref pos, value, nfi, ref foundSign,
+                                  ref negative);
+                            if (foundSign && allowLeadingWhite &&
+                                !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc))
+                                return false;
+                        }
+                    }
+                }
+            }
+
+            var number = Zero;
+            var nDigits = 0;
+            var decimalPointPos = -1;
+            var firstHexDigit = true;
+
+            // Number stuff
+            while (pos < value.Length)
+            {
+
+                if (!ValidDigit(value[pos], allowHexSpecifier))
+                {
+                    if (allowThousands &&
+                        (FindOther(ref pos, value, nfi.NumberGroupSeparator)
+                        || FindOther(ref pos, value, nfi.CurrencyGroupSeparator)))
+                        continue;
+
+                    if (allowDecimalPoint && decimalPointPos < 0 &&
+                        (FindOther(ref pos, value, nfi.NumberDecimalSeparator)
+                        || FindOther(ref pos, value, nfi.CurrencyDecimalSeparator)))
+                    {
+                        decimalPointPos = nDigits;
+                        continue;
+                    }
+
+                    break;
+                }
+
+                nDigits++;
+
+                if (allowHexSpecifier)
+                {
+                    var hexDigit = value[pos++];
+                    byte digitValue;
+                    if (char.IsDigit(hexDigit))
+                        digitValue = (byte)(hexDigit - '0');
+                    else if (char.IsLower(hexDigit))
+                        digitValue = (byte)(hexDigit - 'a' + 10);
+                    else
+                        digitValue = (byte)(hexDigit - 'A' + 10);
+
+                    if (firstHexDigit && digitValue >= 8)
+                        negative = true;
+
+                    number = number * 16 + digitValue;
+                    firstHexDigit = false;
+                    continue;
+                }
+
+                number = number * 10 + (byte)(value[pos++] - '0');
+            }
+
+            // Post number stuff
+            if (nDigits == 0)
+            {
+                if (!tryParse)
+                    exc = GetFormatException();
+                return false;
+            }
+
+            //Signed hex value (Two's Complement)
+            if (allowHexSpecifier && negative)
+            {
+                var mask = Pow(16, nDigits) - 1;
+                number = (number ^ mask) + 1;
+            }
+
+            var exponent = 0;
+            if (allowExponent)
+                if (FindExponent(ref pos, value, ref exponent, tryParse, ref exc) && exc != null)
+                    return false;
+
+            if (allowTrailingSign && !foundSign)
+            {
+                // Sign + Currency
+                FindSign(ref pos, value, nfi, ref foundSign, ref negative);
+                if (foundSign && pos < value.Length)
+                {
+                    if (allowTrailingWhite && !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc))
+                        return false;
+                }
+            }
+
+            if (allowCurrencySymbol && !foundCurrency)
+            {
+                if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, false, tryParse, ref exc))
+                    return false;
+
+                // Currency + sign
+                FindCurrency(ref pos, value, nfi, ref foundCurrency);
+                if (foundCurrency && pos < value.Length)
+                {
+                    if (allowTrailingWhite && !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc))
+                        return false;
+                    if (!foundSign && allowTrailingSign)
+                        FindSign(ref pos, value, nfi, ref foundSign,
+                              ref negative);
+                }
+            }
+
+            if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, false, tryParse, ref exc))
+                return false;
+
+            if (foundOpenParentheses)
+            {
+                if (pos >= value.Length || value[pos++] != ')')
+                {
+                    if (!tryParse)
+                        exc = GetFormatException();
+                    return false;
+                }
+                if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, false, tryParse, ref exc))
+                    return false;
+            }
+
+            if (pos < value.Length && value[pos] != '\u0000')
+            {
+                if (!tryParse)
+                    exc = GetFormatException();
+                return false;
+            }
+
+            if (decimalPointPos >= 0)
+                exponent = exponent - nDigits + decimalPointPos;
+
+            if (exponent < 0)
+            {
+                //
+                // Any non-zero values after decimal point are not allowed
+                //
+                BigInteger remainder;
+                number = DivRem(number, Pow(10, -exponent), out remainder);
+
+                if (!remainder.IsZero)
+                {
+                    if (!tryParse)
+                        exc = new OverflowException("Value too large or too small. exp=" + exponent + " rem = " + remainder + " pow = " + Pow(10, -exponent));
+                    return false;
+                }
+            }
+            else if (exponent > 0)
+            {
+                number = Pow(10, exponent) * number;
+            }
+
+            if (number._sign == 0)
+                result = number;
+            else if (negative)
+                result = new BigInteger(-1, number._data);
+            else
+                result = new BigInteger(1, number._data);
+
+            return true;
+        }
+
+        private static bool CheckStyle(NumberStyles style, bool tryParse, ref Exception exc)
+        {
+            if ((style & NumberStyles.AllowHexSpecifier) != 0)
+            {
+                var ne = style ^ NumberStyles.AllowHexSpecifier;
+                if ((ne & NumberStyles.AllowLeadingWhite) != 0)
+                    ne ^= NumberStyles.AllowLeadingWhite;
+                if ((ne & NumberStyles.AllowTrailingWhite) != 0)
+                    ne ^= NumberStyles.AllowTrailingWhite;
+                if (ne != 0)
+                {
+                    if (!tryParse)
+                        exc = new ArgumentException(
+                            "With AllowHexSpecifier only " +
+                            "AllowLeadingWhite and AllowTrailingWhite " +
+                            "are permitted.");
+                    return false;
+                }
+            }
+            else if ((uint)style > (uint)NumberStyles.Any)
+            {
+                if (!tryParse)
+                    exc = new ArgumentException("Not a valid number style");
+                return false;
+            }
+
+            return true;
+        }
+
+        private static bool JumpOverWhitespace(ref int pos, string s, bool reportError, bool tryParse, ref Exception exc)
+        {
+            while (pos < s.Length && char.IsWhiteSpace(s[pos]))
+                pos++;
+
+            if (reportError && pos >= s.Length)
+            {
+                if (!tryParse)
+                    exc = GetFormatException();
+                return false;
+            }
+
+            return true;
+        }
+
+        private static void FindSign(ref int pos, string s, NumberFormatInfo nfi, ref bool foundSign, ref bool negative)
+        {
+            if ((pos + nfi.NegativeSign.Length) <= s.Length &&
+                string.CompareOrdinal(s, pos, nfi.NegativeSign, 0, nfi.NegativeSign.Length) == 0)
+            {
+                negative = true;
+                foundSign = true;
+                pos += nfi.NegativeSign.Length;
+            }
+            else if ((pos + nfi.PositiveSign.Length) <= s.Length &&
+              string.CompareOrdinal(s, pos, nfi.PositiveSign, 0, nfi.PositiveSign.Length) == 0)
+            {
+                negative = false;
+                pos += nfi.PositiveSign.Length;
+                foundSign = true;
+            }
+        }
+
+        private static void FindCurrency(ref int pos, string s, NumberFormatInfo nfi, ref bool foundCurrency)
+        {
+            if ((pos + nfi.CurrencySymbol.Length) <= s.Length &&
+                 s.Substring(pos, nfi.CurrencySymbol.Length) == nfi.CurrencySymbol)
+            {
+                foundCurrency = true;
+                pos += nfi.CurrencySymbol.Length;
+            }
+        }
+
+        private static bool FindExponent(ref int pos, string s, ref int exponent, bool tryParse, ref Exception exc)
+        {
+            exponent = 0;
+
+            if (pos >= s.Length || (s[pos] != 'e' && s[pos] != 'E'))
+            {
+                exc = null;
+                return false;
+            }
+
+            var i = pos + 1;
+            if (i == s.Length)
+            {
+                exc = tryParse ? null : GetFormatException();
+                return true;
+            }
+
+            var negative = false;
+            if (s[i] == '-')
+            {
+                negative = true;
+                if (++i == s.Length)
+                {
+                    exc = tryParse ? null : GetFormatException();
+                    return true;
+                }
+            }
+
+            if (s[i] == '+' && ++i == s.Length)
+            {
+                exc = tryParse ? null : GetFormatException();
+                return true;
+            }
+
+            long exp = 0; // temp long value
+            for (; i < s.Length; i++)
+            {
+                if (!char.IsDigit(s[i]))
+                {
+                    exc = tryParse ? null : GetFormatException();
+                    return true;
+                }
+
+                // Reduce the risk of throwing an overflow exc
+                exp = checked(exp * 10 - (int)(s[i] - '0'));
+                if (exp < int.MinValue || exp > int.MaxValue)
+                {
+                    exc = tryParse ? null : new OverflowException("Value too large or too small.");
+                    return true;
+                }
+            }
+
+            // exp value saved as negative
+            if (!negative)
+                exp = -exp;
+
+            exc = null;
+            exponent = (int) exp;
+            pos = i;
+            return true;
+        }
+
+        private static bool FindOther(ref int pos, string s, string other)
+        {
+            if ((pos + other.Length) <= s.Length &&
+                 s.Substring(pos, other.Length) == other)
+            {
+                pos += other.Length;
+                return true;
+            }
+
+            return false;
+        }
+
+        private static bool ValidDigit(char e, bool allowHex)
+        {
+            if (allowHex)
+                return char.IsDigit(e) || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f');
+
+            return char.IsDigit(e);
+        }
+
+        private static Exception GetFormatException()
+        {
+            return new FormatException("Input string was not in the correct format");
+        }
+
+        private static bool ProcessTrailingWhitespace(bool tryParse, string s, int position, ref Exception exc)
+        {
+            var len = s.Length;
+
+            for (var i = position; i < len; i++)
+            {
+                var c = s[i];
+
+                if (c != 0 && !char.IsWhiteSpace(c))
+                {
+                    if (!tryParse)
+                        exc = GetFormatException();
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        private static bool Parse(string value, bool tryParse, out BigInteger result, out Exception exc)
+        {
+            int i, sign = 1;
+            var digitsSeen = false;
+
+            result = Zero;
+            exc = null;
+
+            if (value == null)
+            {
+                if (!tryParse)
+                    exc = new ArgumentNullException("value");
+                return false;
+            }
+
+            var len = value.Length;
+
+            char c;
+            for (i = 0; i < len; i++)
+            {
+                c = value[i];
+                if (!char.IsWhiteSpace(c))
+                    break;
+            }
+
+            if (i == len)
+            {
+                if (!tryParse)
+                    exc = GetFormatException();
+                return false;
+            }
+
+            var info = NumberFormatInfo.CurrentInfo;
+
+            var negative = info.NegativeSign;
+            var positive = info.PositiveSign;
+
+            if (string.CompareOrdinal(value, i, positive, 0, positive.Length) == 0)
+                i += positive.Length;
+            else if (string.CompareOrdinal(value, i, negative, 0, negative.Length) == 0)
+            {
+                sign = -1;
+                i += negative.Length;
+            }
+
+            var val = Zero;
+            for (; i < len; i++)
+            {
+                c = value[i];
+
+                if (c == '\0')
+                {
+                    i = len;
+                    continue;
+                }
+
+                if (c >= '0' && c <= '9')
+                {
+                    var d = (byte)(c - '0');
+
+                    val = val * 10 + d;
+
+                    digitsSeen = true;
+                }
+                else if (!ProcessTrailingWhitespace(tryParse, value, i, ref exc))
+                    return false;
+            }
+
+            if (!digitsSeen)
+            {
+                if (!tryParse)
+                    exc = GetFormatException();
+                return false;
+            }
+
+            if (val._sign == 0)
+                result = val;
+            else if (sign == -1)
+                result = new BigInteger(-1, val._data);
+            else
+                result = new BigInteger(1, val._data);
+
+            return true;
+        }
+
+        /// <summary>
+        /// Returns the smaller of two <see cref="BigInteger"/> values.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// The <paramref name="left"/> or <paramref name="right"/> parameter, whichever is smaller.
+        /// </returns>
+        public static BigInteger Min(BigInteger left, BigInteger right)
+        {
+            int ls = left._sign;
+            int rs = right._sign;
+
+            if (ls < rs)
+                return left;
+            if (rs < ls)
+                return right;
+
+            var r = CoreCompare(left._data, right._data);
+            if (ls == -1)
+                r = -r;
+
+            if (r <= 0)
+                return left;
+            return right;
+        }
+
+        /// <summary>
+        /// Returns the larger of two <see cref="BigInteger"/> values.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// The <paramref name="left"/> or <paramref name="right"/> parameter, whichever is larger.
+        /// </returns>
+        public static BigInteger Max(BigInteger left, BigInteger right)
+        {
+            int ls = left._sign;
+            int rs = right._sign;
+
+            if (ls > rs)
+                return left;
+            if (rs > ls)
+                return right;
+
+            var r = CoreCompare(left._data, right._data);
+            if (ls == -1)
+                r = -r;
+
+            if (r >= 0)
+                return left;
+            return right;
+        }
+
+        /// <summary>
+        /// Gets the absolute value of a <see cref="BigInteger"/> object.
+        /// </summary>
+        /// <param name="value">A number.</param>
+        /// <returns>
+        /// The absolute value of <paramref name="value"/>.
+        /// </returns>
+        public static BigInteger Abs(BigInteger value)
+        {
+            return new BigInteger((short)Math.Abs(value._sign), value._data);
+        }
+
+        /// <summary>
+        /// Divides one <see cref="BigInteger"/> value by another, returns the result, and returns the remainder in
+        /// an output parameter.
+        /// </summary>
+        /// <param name="dividend">The value to be divided.</param>
+        /// <param name="divisor">The value to divide by.</param>
+        /// <param name="remainder">When this method returns, contains a <see cref="BigInteger"/> value that represents the remainder from the division. This parameter is passed uninitialized.</param>
+        /// <returns>
+        /// The quotient of the division.
+        /// </returns>
+        public static BigInteger DivRem(BigInteger dividend, BigInteger divisor, out BigInteger remainder)
+        {
+            if (divisor._sign == 0)
+                throw new DivideByZeroException();
+
+            if (dividend._sign == 0)
+            {
+                remainder = dividend;
+                return dividend;
+            }
+
+            uint[] quotient;
+            uint[] remainderValue;
+
+            DivModUnsigned(dividend._data, divisor._data, out quotient, out remainderValue);
+
+            int i;
+            for (i = remainderValue.Length - 1; i >= 0 && remainderValue[i] == 0; --i) ;
+            if (i == -1)
+            {
+                remainder = Zero;
+            }
+            else
+            {
+                if (i < remainderValue.Length - 1)
+                    Array.Resize(ref remainderValue, i + 1);
+                remainder = new BigInteger(dividend._sign, remainderValue);
+            }
+
+            for (i = quotient.Length - 1; i >= 0 && quotient[i] == 0; --i) ;
+            if (i == -1)
+                return Zero;
+            if (i < quotient.Length - 1)
+                Array.Resize(ref quotient, i + 1);
+
+            return new BigInteger((short)(dividend._sign * divisor._sign), quotient);
+        }
+
+        /// <summary>
+        /// Raises a <see cref="BigInteger"/> value to the power of a specified value.
+        /// </summary>
+        /// <param name="value">The number to raise to the <paramref name="exponent"/> power.</param>
+        /// <param name="exponent">The exponent to raise <paramref name="value"/> by.</param>
+        /// <returns>
+        /// The result of raising <paramref name="value"/> to the <paramref name="exponent"/> power.
+        /// </returns>
+        public static BigInteger Pow(BigInteger value, int exponent)
+        {
+            if (exponent < 0)
+                throw new ArgumentOutOfRangeException("exponent", "exp must be >= 0");
+            if (exponent == 0)
+                return One;
+            if (exponent == 1)
+                return value;
+
+            var result = One;
+            while (exponent != 0)
+            {
+                if ((exponent & 1) != 0)
+                    result = result * value;
+                if (exponent == 1)
+                    break;
+
+                value = value * value;
+                exponent >>= 1;
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// Performs modulus division on a number raised to the power of another number.
+        /// </summary>
+        /// <param name="value">The number to raise to the <paramref name="exponent"/> power.</param>
+        /// <param name="exponent">The exponent to raise <paramref name="value"/> by.</param>
+        /// <param name="modulus">The number by which to divide <paramref name="value"/> raised to the <paramref name="exponent"/> power.</param>
+        /// <returns>
+        /// The remainder after dividing <paramref name="value"/> raised by <paramref name="exponent"/> by
+        /// <paramref name="modulus"/>.
+        /// </returns>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="exponent"/> is negative.</exception>
+        public static BigInteger ModPow(BigInteger value, BigInteger exponent, BigInteger modulus)
+        {
+            if (exponent._sign == -1)
+                throw new ArgumentOutOfRangeException("exponent", "power must be >= 0");
+            if (modulus._sign == 0)
+                throw new DivideByZeroException();
+
+            var result = One % modulus;
+            while (exponent._sign != 0)
+            {
+                if (!exponent.IsEven)
+                {
+                    result = result * value;
+                    result = result % modulus;
+                }
+                if (exponent.IsOne)
+                    break;
+                value = value * value;
+                value = value % modulus;
+                exponent >>= 1;
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// Finds the greatest common divisor of two <see cref="BigInteger"/> values.
+        /// </summary>
+        /// <param name="left">The first value.</param>
+        /// <param name="right">The second value.</param>
+        /// <returns>
+        /// The greatest common divisor of <paramref name="left"/> and <paramref name="right"/>.
+        /// </returns>
+        public static BigInteger GreatestCommonDivisor(BigInteger left, BigInteger right)
+        {
+            if (left._sign != 0 && left._data.Length == 1 && left._data[0] == 1)
+                return One;
+            if (right._sign != 0 && right._data.Length == 1 && right._data[0] == 1)
+                return One;
+            if (left.IsZero)
+                return Abs(right);
+            if (right.IsZero)
+                return Abs(left);
+
+            var x = new BigInteger(1, left._data);
+            var y = new BigInteger(1, right._data);
+
+            var g = y;
+
+            while (x._data.Length > 1)
+            {
+                g = x;
+                x = y % x;
+                y = g;
+
+            }
+            if (x.IsZero) return g;
+
+            // TODO: should we have something here if we can convert to long?
+
+            //
+            // Now we can just do it with single precision. I am using the binary gcd method,
+            // as it should be faster.
+            //
+
+            var yy = x._data[0];
+            var xx = (uint)(y % yy);
+
+            var t = 0;
+
+            while (((xx | yy) & 1) == 0)
+            {
+                xx >>= 1; yy >>= 1; t++;
+            }
+            while (xx != 0)
+            {
+                while ((xx & 1) == 0) xx >>= 1;
+                while ((yy & 1) == 0) yy >>= 1;
+                if (xx >= yy)
+                    xx = (xx - yy) >> 1;
+                else
+                    yy = (yy - xx) >> 1;
+            }
+
+            return yy << t;
+        }
+
+        /*LAMESPEC Log doesn't specify to how many ulp is has to be precise
+		We are equilavent to MS with about 2 ULP
+		*/
+
+        /// <summary>
+        /// Returns the logarithm of a specified number in a specified base.
+        /// </summary>
+        /// <param name="value">A number whose logarithm is to be found.</param>
+        /// <param name="baseValue">The base of the logarithm.</param>
+        /// <returns>
+        /// The base <paramref name="baseValue"/> logarithm of value, 
+        /// </returns>
+        /// <exception cref="ArgumentOutOfRangeException">The log of <paramref name="value"/> is out of range of the <see cref="double"/> data type.</exception>
+        public static double Log(BigInteger value, double baseValue)
+        {
+            if (value._sign == -1 || baseValue == 1.0d || baseValue == -1.0d ||
+                    baseValue == double.NegativeInfinity || double.IsNaN(baseValue))
+                return double.NaN;
+
+            if (baseValue == 0.0d || baseValue == double.PositiveInfinity)
+                return value.IsOne ? 0 : double.NaN;
+
+            if (value._data == null)
+                return double.NegativeInfinity;
+
+            var length = value._data.Length - 1;
+            var bitCount = -1;
+            for (var curBit = 31; curBit >= 0; curBit--)
+            {
+                if ((value._data[length] & (1 << curBit)) != 0)
+                {
+                    bitCount = curBit + length * 32;
+                    break;
+                }
+            }
+
+            long bitlen = bitCount;
+            double c = 0, d = 1;
+
+            var testBit = One;
+            var tempBitlen = bitlen;
+            while (tempBitlen > int.MaxValue)
+            {
+                testBit = testBit << int.MaxValue;
+                tempBitlen -= int.MaxValue;
+            }
+            testBit = testBit << (int)tempBitlen;
+
+            for (var curbit = bitlen; curbit >= 0; --curbit)
+            {
+                if ((value & testBit)._sign != 0)
+                    c += d;
+                d *= 0.5;
+                testBit = testBit >> 1;
+            }
+            return (Math.Log(c) + Math.Log(2) * bitlen) / Math.Log(baseValue);
+        }
+
+        /// <summary>
+        /// Returns the natural (base <c>e</c>) logarithm of a specified number.
+        /// </summary>
+        /// <param name="value">The number whose logarithm is to be found.</param>
+        /// <returns>
+        /// The natural (base <c>e</c>) logarithm of <paramref name="value"/>.
+        /// </returns>
+        /// <exception cref="ArgumentOutOfRangeException">The base 10 log of value is out of range of the <see cref="double"/> data type.</exception>
+        public static double Log(BigInteger value)
+        {
+            return Log(value, Math.E);
+        }
+
+        /// <summary>
+        /// Returns the base 10 logarithm of a specified number.
+        /// </summary>
+        /// <param name="value">A number whose logarithm is to be found.</param>
+        /// <returns>
+        /// The base 10 logarithm of <paramref name="value"/>.
+        /// </returns>
+        /// <exception cref="ArgumentOutOfRangeException">The base 10 log of value is out of range of the <see cref="double"/> data type.</exception>
+        public static double Log10(BigInteger value)
+        {
+            return Log(value, 10);
+        }
+
+        /// <summary>
+        /// Returns a value that indicates whether the current instance and an unsigned 64-bit integer have the same value.
+        /// </summary>
+        /// <param name="other">The unsigned 64-bit integer to compare.</param>
+        /// <returns>
+        /// <c>true</c> if the current instance and the unsigned 64-bit integer have the same value; otherwise, <c>false</c>.
+        /// </returns>
+        [CLSCompliant(false)]
+        public bool Equals(ulong other)
+        {
+            return CompareTo(other) == 0;
+        }
+
+        /// <summary>
+        /// Returns the hash code for the current <see cref="BigInteger"/> object.
+        /// </summary>
+        /// <returns>
+        /// A 32-bit signed integer hash code.
+        /// </returns>
+        public override int GetHashCode()
+        {
+            var hash = (uint)(_sign * 0x01010101u);
+            if (_data != null)
+            {
+                foreach (var bit in _data)
+                    hash ^= bit;
+            }
+
+            return (int)hash;
+        }
+
+        /// <summary>
+        /// Adds two <see cref="BigInteger"/> values and returns the result.
+        /// </summary>
+        /// <param name="left">The first value to add.</param>
+        /// <param name="right">The second value to add.</param>
+        /// <returns>
+        /// The sum of <paramref name="left"/> and <paramref name="right"/>.
+        /// </returns>
+        public static BigInteger Add(BigInteger left, BigInteger right)
+        {
+            return left + right;
+        }
+
+        /// <summary>
+        /// Subtracts one <see cref="BigInteger"/> value from another and returns the result.
+        /// </summary>
+        /// <param name="left">The value to subtract from (the minuend).</param>
+        /// <param name="right">The value to subtract (the subtrahend).</param>
+        /// <returns>
+        /// The result of subtracting <paramref name="right"/> from <paramref name="left"/>.
+        /// </returns>
+        public static BigInteger Subtract(BigInteger left, BigInteger right)
+        {
+            return left - right;
+        }
+
+        /// <summary>
+        /// Returns the product of two <see cref="BigInteger"/> values.
+        /// </summary>
+        /// <param name="left">The first number to multiply.</param>
+        /// <param name="right">The second number to multiply.</param>
+        /// <returns>
+        /// The product of the <paramref name="left"/> and <paramref name="right"/> parameters.
+        /// </returns>
+        public static BigInteger Multiply(BigInteger left, BigInteger right)
+        {
+            return left * right;
+        }
+
+        /// <summary>
+        /// Divides one <see cref="BigInteger"/> value by another and returns the result.
+        /// </summary>
+        /// <param name="dividend">The value to be divided.</param>
+        /// <param name="divisor">The value to divide by.</param>
+        /// <returns>
+        /// The quotient of the division.
+        /// </returns>
+        public static BigInteger Divide(BigInteger dividend, BigInteger divisor)
+        {
+            return dividend / divisor;
+        }
+
+        /// <summary>
+        /// Performs integer division on two <see cref="BigInteger"/> values and returns the remainder.
+        /// </summary>
+        /// <param name="dividend">The value to be divided.</param>
+        /// <param name="divisor">The value to divide by.</param>
+        /// <returns>
+        /// The remainder after dividing <paramref name="dividend"/> by <paramref name="divisor"/>.
+        /// </returns>
+        public static BigInteger Remainder(BigInteger dividend, BigInteger divisor)
+        {
+            return dividend % divisor;
+        }
+
+        /// <summary>
+        /// Negates a specified <see cref="BigInteger"/> value.
+        /// </summary>
+        /// <param name="value">The value to negate.</param>
+        /// <returns>
+        /// The result of the <paramref name="value"/> parameter multiplied by negative one (-1).
+        /// </returns>
+        public static BigInteger Negate(BigInteger value)
+        {
+            return -value;
+        }
+
+        /// <summary>
+        /// Compares this instance to a specified object and returns an integer that indicates whether the value of
+        /// this instance is less than, equal to, or greater than the value of the specified object.
+        /// </summary>
+        /// <param name="obj">The object to compare.</param>
+        /// <returns>
+        /// A signed integer that indicates the relationship of the current instance to the <paramref name="obj"/> parameter,
+        /// as shown in the following table.
+        /// <list type="table">
+        ///     <listheader>
+        ///         <term>Value</term>
+        ///         <description>Condition</description>
+        ///     </listheader>
+        ///     <item>
+        ///         <term>Less than zero</term>
+        ///         <description>The current instance is less than <paramref name="obj"/>.</description>
+        ///     </item>
+        ///     <item>
+        ///         <term>Zero</term>
+        ///         <description>The current instance equals <paramref name="obj"/>.</description>
+        ///     </item>
+        ///     <item>
+        ///         <term>Greater than zero</term>
+        ///         <description>The current instance is greater than <paramref name="obj"/>.</description>
+        ///     </item>
+        /// </list>
+        /// </returns>
+        /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="BigInteger"/>.</exception>
+        public int CompareTo(object obj)
+        {
+            if (obj == null)
+                return 1;
+
+            if (!(obj is BigInteger))
+                return -1;
+
+            return Compare(this, (BigInteger)obj);
+        }
+
+        /// <summary>
+        /// Compares this instance to a second <see cref="BigInteger"/> and returns an integer that indicates whether the
+        /// value of this instance is less than, equal to, or greater than the value of the specified object.
+        /// </summary>
+        /// <param name="other">The object to compare.</param>
+        /// <returns>
+        /// A signed integer value that indicates the relationship of this instance to <paramref name="other"/>, as
+        /// shown in the following table.
+        /// <list type="table">
+        ///     <listheader>
+        ///         <term>Value</term>
+        ///         <description>Condition</description>
+        ///     </listheader>
+        ///     <item>
+        ///         <term>Less than zero</term>
+        ///         <description>The current instance is less than <paramref name="other"/>.</description>
+        ///     </item>
+        ///     <item>
+        ///         <term>Zero</term>
+        ///         <description>The current instance equals <paramref name="other"/>.</description>
+        ///     </item>
+        ///     <item>
+        ///         <term>Greater than zero</term>
+        ///         <description>The current instance is greater than <paramref name="other"/>.</description>
+        ///     </item>
+        /// </list>
+        /// </returns>
+        public int CompareTo(BigInteger other)
+        {
+            return Compare(this, other);
+        }
+
+        /// <summary>
+        /// Compares this instance to an unsigned 64-bit integer and returns an integer that indicates whether the value of this
+        /// instance is less than, equal to, or greater than the value of the unsigned 64-bit integer.
+        /// </summary>
+        /// <param name="other">The unsigned 64-bit integer to compare.</param>
+        /// <returns>
+        /// A signed integer that indicates the relative value of this instance and <paramref name="other"/>, as shown
+        /// in the following table.
+        /// <list type="table">
+        ///     <listheader>
+        ///         <term>Value</term>
+        ///         <description>Condition</description>
+        ///     </listheader>
+        ///     <item>
+        ///         <term>Less than zero</term>
+        ///         <description>The current instance is less than <paramref name="other"/>.</description>
+        ///     </item>
+        ///     <item>
+        ///         <term>Zero</term>
+        ///         <description>The current instance equals <paramref name="other"/>.</description>
+        ///     </item>
+        ///     <item>
+        ///         <term>Greater than zero</term>
+        ///         <description>The current instance is greater than <paramref name="other"/>.</description>
+        ///     </item>
+        /// </list>
+        /// </returns>
+        [CLSCompliant(false)]
+        public int CompareTo(ulong other)
+        {
+            if (_sign < 0)
+                return -1;
+            if (_sign == 0)
+                return other == 0 ? 0 : -1;
+
+            if (_data.Length > 2)
+                return 1;
+
+            var high = (uint)(other >> 32);
+            var low = (uint)other;
+
+            return LongCompare(low, high);
+        }
+
+        private int LongCompare(uint low, uint high)
+        {
+            uint h = 0;
+            if (_data.Length > 1)
+                h = _data[1];
+
+            if (h > high)
+                return 1;
+            if (h < high)
+                return -1;
+
+            var l = _data[0];
+
+            if (l > low)
+                return 1;
+            if (l < low)
+                return -1;
+
+            return 0;
+        }
+
+        /// <summary>
+        /// Compares this instance to a signed 64-bit integer and returns an integer that indicates whether the value of this
+        /// instance is less than, equal to, or greater than the value of the signed 64-bit integer.
+        /// </summary>
+        /// <param name="other">The signed 64-bit integer to compare.</param>
+        /// <returns>
+        /// A signed integer that indicates the relative value of this instance and <paramref name="other"/>, as shown
+        /// in the following table.
+        /// <list type="table">
+        ///     <listheader>
+        ///         <term>Value</term>
+        ///         <description>Condition</description>
+        ///     </listheader>
+        ///     <item>
+        ///         <term>Less than zero</term>
+        ///         <description>The current instance is less than <paramref name="other"/>.</description>
+        ///     </item>
+        ///     <item>
+        ///         <term>Zero</term>
+        ///         <description>The current instance equals <paramref name="other"/>.</description>
+        ///     </item>
+        ///     <item>
+        ///         <term>Greater than zero</term>
+        ///         <description>The current instance is greater than <paramref name="other"/>.</description>
+        ///     </item>
+        /// </list>
+        /// </returns>
+        public int CompareTo(long other)
+        {
+            int ls = _sign;
+            var rs = Math.Sign(other);
+
+            if (ls != rs)
+                return ls > rs ? 1 : -1;
+
+            if (ls == 0)
+                return 0;
+
+            if (_data.Length > 2)
+                return _sign;
+
+            if (other < 0)
+                other = -other;
+            var low = (uint)other;
+            var high = (uint)((ulong)other >> 32);
+
+            var r = LongCompare(low, high);
+            if (ls == -1)
+                r = -r;
+
+            return r;
+        }
+
+        /// <summary>
+        /// Compares two <see cref="BigInteger"/> values and returns an integer that indicates whether the first value is less than, equal to, or greater than the second value.
+        /// </summary>
+        /// <param name="left">The first value to compare.</param>
+        /// <param name="right">The second value to compare.</param>
+        /// <returns>
+        /// A signed integer that indicates the relative values of left and right, as shown in the following table.
+        /// <list type="table">
+        ///     <listheader>
+        ///         <term>Value</term>
+        ///         <description>Condition</description>
+        ///     </listheader>
+        ///     <item>
+        ///         <term>Less than zero</term>
+        ///         <description><paramref name="left"/> is less than <paramref name="right"/>.</description>
+        ///     </item>
+        ///     <item>
+        ///         <term>Zero</term>
+        ///         <description><paramref name="left"/> equals <paramref name="right"/>.</description>
+        ///     </item>
+        ///     <item>
+        ///         <term>Greater than zero</term>
+        ///         <description><paramref name="left"/> is greater than <paramref name="right"/>.</description>
+        ///     </item>
+        /// </list>
+        /// </returns>
+        public static int Compare(BigInteger left, BigInteger right)
+        {
+            int ls = left._sign;
+            int rs = right._sign;
+
+            if (ls != rs)
+                return ls > rs ? 1 : -1;
+
+            var r = CoreCompare(left._data, right._data);
+            if (ls < 0)
+                r = -r;
+            return r;
+        }
+
+        private static int TopByte(uint x)
+        {
+            if ((x & 0xFFFF0000u) != 0)
+            {
+                if ((x & 0xFF000000u) != 0)
+                    return 4;
+                return 3;
+            }
+            if ((x & 0xFF00u) != 0)
+                return 2;
+            return 1;
+        }
+
+        private static int FirstNonFfByte(uint word)
+        {
+            if ((word & 0xFF000000u) != 0xFF000000u)
+                return 4;
+            if ((word & 0xFF0000u) != 0xFF0000u)
+                return 3;
+            if ((word & 0xFF00u) != 0xFF00u)
+                return 2;
+            return 1;
+        }
+
+        /// <summary>
+        /// Converts a <see cref="BigInteger"/> value to a byte array.
+        /// </summary>
+        /// <returns>
+        /// The value of the current <see cref="BigInteger"/> object converted to an array of bytes.
+        /// </returns>
+        public byte[] ToByteArray()
+        {
+            if (_sign == 0)
+                return new byte[1];
+
+            //number of bytes not counting upper word
+            var bytes = (_data.Length - 1) * 4;
+            var needExtraZero = false;
+
+            var topWord = _data[_data.Length - 1];
+            int extra;
+
+            //if the topmost bit is set we need an extra 
+            if (_sign == 1)
+            {
+                extra = TopByte(topWord);
+                var mask = 0x80u << ((extra - 1) * 8);
+                if ((topWord & mask) != 0)
+                {
+                    needExtraZero = true;
+                }
+            }
+            else
+            {
+                extra = TopByte(topWord);
+            }
+
+            var res = new byte[bytes + extra + (needExtraZero ? 1 : 0)];
+            if (_sign == 1)
+            {
+                var j = 0;
+                var end = _data.Length - 1;
+                for (var i = 0; i < end; ++i)
+                {
+                    var word = _data[i];
+
+                    res[j++] = (byte)word;
+                    res[j++] = (byte)(word >> 8);
+                    res[j++] = (byte)(word >> 16);
+                    res[j++] = (byte)(word >> 24);
+                }
+                while (extra-- > 0)
+                {
+                    res[j++] = (byte)topWord;
+                    topWord >>= 8;
+                }
+            }
+            else
+            {
+                var j = 0;
+                var end = _data.Length - 1;
+
+                uint carry = 1, word;
+                ulong add;
+                for (var i = 0; i < end; ++i)
+                {
+                    word = _data[i];
+                    add = (ulong)~word + carry;
+                    word = (uint)add;
+                    carry = (uint)(add >> 32);
+
+                    res[j++] = (byte)word;
+                    res[j++] = (byte)(word >> 8);
+                    res[j++] = (byte)(word >> 16);
+                    res[j++] = (byte)(word >> 24);
+                }
+
+                add = (ulong)~topWord + (carry);
+                word = (uint)add;
+                carry = (uint)(add >> 32);
+                if (carry == 0)
+                {
+                    var ex = FirstNonFfByte(word);
+                    var needExtra = (word & (1 << (ex * 8 - 1))) == 0;
+                    var to = ex + (needExtra ? 1 : 0);
+
+                    if (to != extra)
+                        Array.Resize(ref res, bytes + to);
+
+                    while (ex-- > 0)
+                    {
+                        res[j++] = (byte)word;
+                        word >>= 8;
+                    }
+                    if (needExtra)
+                        res[j++] = 0xFF;
+                }
+                else
+                {
+                    Array.Resize(ref res, bytes + 5);
+                    res[j++] = (byte)word;
+                    res[j++] = (byte)(word >> 8);
+                    res[j++] = (byte)(word >> 16);
+                    res[j++] = (byte)(word >> 24);
+                    res[j++] = 0xFF;
+                }
+            }
+
+            return res;
+        }
+
+        private static uint[] CoreAdd(uint[] a, uint[] b)
+        {
+            if (a.Length < b.Length)
+            {
+                var tmp = a;
+                a = b;
+                b = tmp;
+            }
+
+            var bl = a.Length;
+            var sl = b.Length;
+
+            var res = new uint[bl];
+
+            ulong sum = 0;
+
+            var i = 0;
+            for (; i < sl; i++)
+            {
+                sum = sum + a[i] + b[i];
+                res[i] = (uint)sum;
+                sum >>= 32;
+            }
+
+            for (; i < bl; i++)
+            {
+                sum = sum + a[i];
+                res[i] = (uint)sum;
+                sum >>= 32;
+            }
+
+            if (sum != 0)
+            {
+                Array.Resize(ref res, bl + 1);
+                res[i] = (uint)sum;
+            }
+
+            return res;
+        }
+
+        /*invariant a > b*/
+        private static uint[] CoreSub(uint[] a, uint[] b)
+        {
+            var bl = a.Length;
+            var sl = b.Length;
+
+            var res = new uint[bl];
+
+            ulong borrow = 0;
+            int i;
+            for (i = 0; i < sl; ++i)
+            {
+                borrow = (ulong)a[i] - b[i] - borrow;
+
+                res[i] = (uint)borrow;
+                borrow = (borrow >> 32) & 0x1;
+            }
+
+            for (; i < bl; i++)
+            {
+                borrow = (ulong)a[i] - borrow;
+                res[i] = (uint)borrow;
+                borrow = (borrow >> 32) & 0x1;
+            }
+
+            //remove extra zeroes
+            for (i = bl - 1; i >= 0 && res[i] == 0; --i) ;
+            if (i < bl - 1)
+                Array.Resize(ref res, i + 1);
+
+            return res;
+        }
+
+        private static uint[] CoreAdd(uint[] a, uint b)
+        {
+            var len = a.Length;
+            var res = new uint[len];
+
+            ulong sum = b;
+            int i;
+            for (i = 0; i < len; i++)
+            {
+                sum = sum + a[i];
+                res[i] = (uint)sum;
+                sum >>= 32;
+            }
+
+            if (sum != 0)
+            {
+                Array.Resize(ref res, len + 1);
+                res[i] = (uint)sum;
+            }
+
+            return res;
+        }
+
+        private static uint[] CoreSub(uint[] a, uint b)
+        {
+            var len = a.Length;
+            var res = new uint[len];
+
+            ulong borrow = b;
+            int i;
+            for (i = 0; i < len; i++)
+            {
+                borrow = (ulong)a[i] - borrow;
+                res[i] = (uint)borrow;
+                borrow = (borrow >> 32) & 0x1;
+            }
+
+            //remove extra zeroes
+            for (i = len - 1; i >= 0 && res[i] == 0; --i) ;
+            if (i < len - 1)
+                Array.Resize(ref res, i + 1);
+
+            return res;
+        }
+
+        private static int CoreCompare(uint[] a, uint[] b)
+        {
+            var al = a != null ? a.Length : 0;
+            var bl = b != null ? b.Length : 0;
+
+            if (al > bl)
+                return 1;
+            if (bl > al)
+                return -1;
+
+            for (var i = al - 1; i >= 0; --i)
+            {
+                var ai = a[i];
+                var bi = b[i];
+                if (ai > bi)
+                    return 1;
+                if (ai < bi)
+                    return -1;
+            }
+            return 0;
+        }
+
+        private static int GetNormalizeShift(uint value)
+        {
+            var shift = 0;
+
+            if ((value & 0xFFFF0000) == 0) { value <<= 16; shift += 16; }
+            if ((value & 0xFF000000) == 0) { value <<= 8; shift += 8; }
+            if ((value & 0xF0000000) == 0) { value <<= 4; shift += 4; }
+            if ((value & 0xC0000000) == 0) { value <<= 2; shift += 2; }
+            if ((value & 0x80000000) == 0) { value <<= 1; shift += 1; }
+
+            return shift;
+        }
+
+        private static void Normalize(uint[] u, int l, uint[] un, int shift)
+        {
+            uint carry = 0;
+            int i;
+            if (shift > 0)
+            {
+                var rshift = 32 - shift;
+                for (i = 0; i < l; i++)
+                {
+                    var ui = u[i];
+                    un[i] = (ui << shift) | carry;
+                    carry = ui >> rshift;
+                }
+            }
+            else
+            {
+                for (i = 0; i < l; i++)
+                {
+                    un[i] = u[i];
+                }
+            }
+
+            while (i < un.Length)
+            {
+                un[i++] = 0;
+            }
+
+            if (carry != 0)
+            {
+                un[l] = carry;
+            }
+        }
+
+        private static void Unnormalize(uint[] un, out uint[] r, int shift)
+        {
+            var length = un.Length;
+            r = new uint[length];
+
+            if (shift > 0)
+            {
+                var lshift = 32 - shift;
+                uint carry = 0;
+                for (var i = length - 1; i >= 0; i--)
+                {
+                    var uni = un[i];
+                    r[i] = (uni >> shift) | carry;
+                    carry = (uni << lshift);
+                }
+            }
+            else
+            {
+                for (var i = 0; i < length; i++)
+                {
+                    r[i] = un[i];
+                }
+            }
+        }
+
+        private static void DivModUnsigned(uint[] u, uint[] v, out uint[] q, out uint[] r)
+        {
+            var m = u.Length;
+            var n = v.Length;
+
+            if (n <= 1)
+            {
+                //  Divide by single digit
+                //
+                ulong rem = 0;
+                var v0 = v[0];
+                q = new uint[m];
+                r = new uint[1];
+
+                for (var j = m - 1; j >= 0; j--)
+                {
+                    rem *= Base;
+                    rem += u[j];
+
+                    var div = rem / v0;
+                    rem -= div * v0;
+                    q[j] = (uint)div;
+                }
+                r[0] = (uint)rem;
+            }
+            else if (m >= n)
+            {
+                var shift = GetNormalizeShift(v[n - 1]);
+
+                var un = new uint[m + 1];
+                var vn = new uint[n];
+
+                Normalize(u, m, un, shift);
+                Normalize(v, n, vn, shift);
+
+                q = new uint[m - n + 1];
+                r = null;
+
+                //  Main division loop
+                //
+                for (var j = m - n; j >= 0; j--)
+                {
+                    int i;
+
+                    var rr = Base * un[j + n] + un[j + n - 1];
+                    var qq = rr / vn[n - 1];
+                    rr -= qq * vn[n - 1];
+
+                    for (;;)
+                    {
+                        // Estimate too big ?
+                        //
+                        if ((qq >= Base) || (qq * vn[n - 2] > (rr * Base + un[j + n - 2])))
+                        {
+                            qq--;
+                            rr += (ulong)vn[n - 1];
+                            if (rr < Base)
+                                continue;
+                        }
+                        break;
+                    }
+
+
+                    //  Multiply and subtract
+                    //
+                    long b = 0;
+                    long t = 0;
+                    for (i = 0; i < n; i++)
+                    {
+                        var p = vn[i] * qq;
+                        t = (long)un[i + j] - (long)(uint)p - b;
+                        un[i + j] = (uint)t;
+                        p >>= 32;
+                        t >>= 32;
+                        b = (long)p - t;
+                    }
+                    t = (long)un[j + n] - b;
+                    un[j + n] = (uint)t;
+
+                    //  Store the calculated value
+                    //
+                    q[j] = (uint)qq;
+
+                    //  Add back vn[0..n] to un[j..j+n]
+                    //
+                    if (t < 0)
+                    {
+                        q[j]--;
+                        ulong c = 0;
+                        for (i = 0; i < n; i++)
+                        {
+                            c = (ulong)vn[i] + un[j + i] + c;
+                            un[j + i] = (uint)c;
+                            c >>= 32;
+                        }
+                        c += (ulong)un[j + n];
+                        un[j + n] = (uint)c;
+                    }
+                }
+
+                Unnormalize(un, out r, shift);
+            }
+            else
+            {
+                q = new uint[] { 0 };
+                r = u;
+            }
+        }
+    }
+}

+ 24 - 24
src/Renci.SshNet/Common/ChannelDataEventArgs.cs

@@ -1,24 +1,24 @@
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Provides data for <see cref="Renci.SshNet.Channels.Channel.DataReceived"/> event.
-    /// </summary>
-    internal class ChannelDataEventArgs : ChannelEventArgs
-    {
-        /// <summary>
-        /// Gets channel data.
-        /// </summary>
-        public byte[] Data { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ChannelDataEventArgs"/> class.
-        /// </summary>
-        /// <param name="channelNumber">Channel number.</param>
-        /// <param name="data">Channel data.</param>
-        public ChannelDataEventArgs(uint channelNumber, byte[] data)
-            : base(channelNumber)
-        {
-            Data = data;
-        }
-    }
-}
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Provides data for <see cref="Renci.SshNet.Channels.Channel.DataReceived"/> event.
+    /// </summary>
+    internal class ChannelDataEventArgs : ChannelEventArgs
+    {
+        /// <summary>
+        /// Gets channel data.
+        /// </summary>
+        public byte[] Data { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ChannelDataEventArgs"/> class.
+        /// </summary>
+        /// <param name="channelNumber">Channel number.</param>
+        /// <param name="data">Channel data.</param>
+        public ChannelDataEventArgs(uint channelNumber, byte[] data)
+            : base(channelNumber)
+        {
+            Data = data;
+        }
+    }
+}

+ 24 - 24
src/Renci.SshNet/Common/ChannelEventArgs.cs

@@ -1,24 +1,24 @@
-using System;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Base class for all channel related events.
-    /// </summary>
-    internal class ChannelEventArgs : EventArgs
-    {
-        /// <summary>
-        /// Gets the channel number.
-        /// </summary>
-        public uint ChannelNumber { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ChannelEventArgs"/> class.
-        /// </summary>
-        /// <param name="channelNumber">The channel number.</param>
-        public ChannelEventArgs(uint channelNumber)
-        {
-            ChannelNumber = channelNumber;
-        }
-    }
-}
+using System;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Base class for all channel related events.
+    /// </summary>
+    internal class ChannelEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Gets the channel number.
+        /// </summary>
+        public uint ChannelNumber { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ChannelEventArgs"/> class.
+        /// </summary>
+        /// <param name="channelNumber">The channel number.</param>
+        public ChannelEventArgs(uint channelNumber)
+        {
+            ChannelNumber = channelNumber;
+        }
+    }
+}

+ 24 - 24
src/Renci.SshNet/Common/ChannelExtendedDataEventArgs.cs

@@ -1,24 +1,24 @@
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Provides data for <see cref="Renci.SshNet.Channels.Channel.ExtendedDataReceived"/> events.
-    /// </summary>
-    internal class ChannelExtendedDataEventArgs : ChannelDataEventArgs
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ChannelExtendedDataEventArgs"/> class.
-        /// </summary>
-        /// <param name="channelNumber">Channel number.</param>
-        /// <param name="data">Channel data.</param>
-        /// <param name="dataTypeCode">Channel data type code.</param>
-        public ChannelExtendedDataEventArgs(uint channelNumber, byte[] data, uint dataTypeCode) : base(channelNumber, data)
-        {
-            DataTypeCode = dataTypeCode;
-        }
-
-        /// <summary>
-        /// Gets the data type code.
-        /// </summary>
-        public uint DataTypeCode { get; private set; }
-    }
-}
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Provides data for <see cref="Renci.SshNet.Channels.Channel.ExtendedDataReceived"/> events.
+    /// </summary>
+    internal class ChannelExtendedDataEventArgs : ChannelDataEventArgs
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ChannelExtendedDataEventArgs"/> class.
+        /// </summary>
+        /// <param name="channelNumber">Channel number.</param>
+        /// <param name="data">Channel data.</param>
+        /// <param name="dataTypeCode">Channel data type code.</param>
+        public ChannelExtendedDataEventArgs(uint channelNumber, byte[] data, uint dataTypeCode) : base(channelNumber, data)
+        {
+            DataTypeCode = dataTypeCode;
+        }
+
+        /// <summary>
+        /// Gets the data type code.
+        /// </summary>
+        public uint DataTypeCode { get; private set; }
+    }
+}

+ 37 - 37
src/Renci.SshNet/Common/ChannelOpenConfirmedEventArgs.cs

@@ -1,37 +1,37 @@
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Provides data for <see cref="Renci.SshNet.Channels.ClientChannel.OpenConfirmed"/> event.
-    /// </summary>
-    internal class ChannelOpenConfirmedEventArgs : ChannelEventArgs
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ChannelOpenConfirmedEventArgs"/> class.
-        /// </summary>
-        /// <param name="remoteChannelNumber">The remote channel number.</param>
-        /// <param name="initialWindowSize">The initial window size.</param>
-        /// <param name="maximumPacketSize">The maximum packet size.</param>
-        public ChannelOpenConfirmedEventArgs(uint remoteChannelNumber, uint initialWindowSize, uint maximumPacketSize)
-            : base(remoteChannelNumber)
-        {
-            InitialWindowSize = initialWindowSize;
-            MaximumPacketSize = maximumPacketSize;
-        }
-
-        /// <summary>
-        /// Gets the initial size of the window.
-        /// </summary>
-        /// <value>
-        /// The initial size of the window.
-        /// </value>
-        public uint InitialWindowSize { get; private set; }
-
-        /// <summary>
-        /// Gets the maximum size of the packet.
-        /// </summary>
-        /// <value>
-        /// The maximum size of the packet.
-        /// </value>
-        public uint MaximumPacketSize { get; private set; }
-    }
-}
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Provides data for <see cref="Renci.SshNet.Channels.ClientChannel.OpenConfirmed"/> event.
+    /// </summary>
+    internal class ChannelOpenConfirmedEventArgs : ChannelEventArgs
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ChannelOpenConfirmedEventArgs"/> class.
+        /// </summary>
+        /// <param name="remoteChannelNumber">The remote channel number.</param>
+        /// <param name="initialWindowSize">The initial window size.</param>
+        /// <param name="maximumPacketSize">The maximum packet size.</param>
+        public ChannelOpenConfirmedEventArgs(uint remoteChannelNumber, uint initialWindowSize, uint maximumPacketSize)
+            : base(remoteChannelNumber)
+        {
+            InitialWindowSize = initialWindowSize;
+            MaximumPacketSize = maximumPacketSize;
+        }
+
+        /// <summary>
+        /// Gets the initial size of the window.
+        /// </summary>
+        /// <value>
+        /// The initial size of the window.
+        /// </value>
+        public uint InitialWindowSize { get; private set; }
+
+        /// <summary>
+        /// Gets the maximum size of the packet.
+        /// </summary>
+        /// <value>
+        /// The maximum size of the packet.
+        /// </value>
+        public uint MaximumPacketSize { get; private set; }
+    }
+}

+ 38 - 38
src/Renci.SshNet/Common/ChannelOpenFailedEventArgs.cs

@@ -1,38 +1,38 @@
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Provides data for <see cref="Renci.SshNet.Channels.ClientChannel.OpenFailed"/> event.
-    /// </summary>
-    internal class ChannelOpenFailedEventArgs : ChannelEventArgs
-    {
-        /// <summary>
-        /// Gets failure reason code.
-        /// </summary>
-        public uint ReasonCode { get; private set; }
-
-        /// <summary>
-        /// Gets failure description.
-        /// </summary>
-        public string Description { get; private set; }
-
-        /// <summary>
-        /// Gets failure language.
-        /// </summary>
-        public string Language { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ChannelOpenFailedEventArgs"/> class.
-        /// </summary>
-        /// <param name="channelNumber">Channel number.</param>
-        /// <param name="reasonCode">Failure reason code.</param>
-        /// <param name="description">Failure description.</param>
-        /// <param name="language">Failure language.</param>
-        public ChannelOpenFailedEventArgs(uint channelNumber, uint reasonCode, string description, string language)
-            : base(channelNumber)
-        {
-            ReasonCode = reasonCode;
-            Description = description;
-            Language = language;
-        }
-    }
-}
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Provides data for <see cref="Renci.SshNet.Channels.ClientChannel.OpenFailed"/> event.
+    /// </summary>
+    internal class ChannelOpenFailedEventArgs : ChannelEventArgs
+    {
+        /// <summary>
+        /// Gets failure reason code.
+        /// </summary>
+        public uint ReasonCode { get; private set; }
+
+        /// <summary>
+        /// Gets failure description.
+        /// </summary>
+        public string Description { get; private set; }
+
+        /// <summary>
+        /// Gets failure language.
+        /// </summary>
+        public string Language { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ChannelOpenFailedEventArgs"/> class.
+        /// </summary>
+        /// <param name="channelNumber">Channel number.</param>
+        /// <param name="reasonCode">Failure reason code.</param>
+        /// <param name="description">Failure description.</param>
+        /// <param name="language">Failure language.</param>
+        public ChannelOpenFailedEventArgs(uint channelNumber, uint reasonCode, string description, string language)
+            : base(channelNumber)
+        {
+            ReasonCode = reasonCode;
+            Description = description;
+            Language = language;
+        }
+    }
+}

+ 25 - 25
src/Renci.SshNet/Common/ChannelRequestEventArgs.cs

@@ -1,25 +1,25 @@
-using System;
-using Renci.SshNet.Messages.Connection;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Provides data for <see cref="Renci.SshNet.Channels.Channel.RequestReceived"/> event.
-    /// </summary>
-    internal class ChannelRequestEventArgs : EventArgs
-    {
-        /// <summary>
-        /// Gets request information.
-        /// </summary>
-        public RequestInfo Info { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ChannelRequestEventArgs"/> class.
-        /// </summary>
-        /// <param name="info">Request information.</param>
-        public ChannelRequestEventArgs(RequestInfo info)
-        {
-            Info = info;
-        }
-    }
-}
+using System;
+using Renci.SshNet.Messages.Connection;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Provides data for <see cref="Renci.SshNet.Channels.Channel.RequestReceived"/> event.
+    /// </summary>
+    internal class ChannelRequestEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Gets request information.
+        /// </summary>
+        public RequestInfo Info { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ChannelRequestEventArgs"/> class.
+        /// </summary>
+        /// <param name="info">Request information.</param>
+        public ChannelRequestEventArgs(RequestInfo info)
+        {
+            Info = info;
+        }
+    }
+}

+ 333 - 333
src/Renci.SshNet/Common/DerData.cs

@@ -1,333 +1,333 @@
-using System;
-using System.Collections.Generic;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Base class for DER encoded data.
-    /// </summary>
-    public class DerData
-    {
-        private const byte Constructed = 0x20;
-
-        private const byte Boolean = 0x01;
-        private const byte Integer = 0x02;
-        //private const byte BITSTRING = 0x03;
-        private const byte Octetstring = 0x04;
-        private const byte Null = 0x05;
-        private const byte Objectidentifier = 0x06;
-        //private const byte EXTERNAL = 0x08;
-        //private const byte ENUMERATED = 0x0a;
-        private const byte Sequence = 0x10;
-        //private const byte SEQUENCEOF = 0x10; // for completeness
-        //private const byte SET = 0x11;
-        //private const byte SETOF = 0x11; // for completeness
-
-        //private const byte NUMERICSTRING = 0x12;
-        //private const byte PRINTABLESTRING = 0x13;
-        //private const byte T61STRING = 0x14;
-        //private const byte VIDEOTEXSTRING = 0x15;
-        //private const byte IA5STRING = 0x16;
-        //private const byte UTCTIME = 0x17;
-        //private const byte GENERALIZEDTIME = 0x18;
-        //private const byte GRAPHICSTRING = 0x19;
-        //private const byte VISIBLESTRING = 0x1a;
-        //private const byte GENERALSTRING = 0x1b;
-        //private const byte UNIVERSALSTRING = 0x1c;
-        //private const byte BMPSTRING = 0x1e;
-        //private const byte UTF8STRING = 0x0c;
-        //private const byte APPLICATION = 0x40;
-        //private const byte TAGGED = 0x80;
-
-        private readonly List<byte> _data;
-
-        private int _readerIndex;
-        private readonly int _lastIndex;
-
-        /// <summary>
-        /// Gets a value indicating whether end of data is reached.
-        /// </summary>
-        /// <value>
-        /// 	<c>true</c> if end of data is reached; otherwise, <c>false</c>.
-        /// </value>
-        public bool IsEndOfData
-        {
-            get
-            {
-                return _readerIndex >= _lastIndex;
-            }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="DerData"/> class.
-        /// </summary>
-        public DerData()
-        {
-            _data = new List<byte>();
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="DerData"/> class.
-        /// </summary>
-        /// <param name="data">DER encoded data.</param>
-        public DerData(byte[] data)
-        {
-            _data = new List<byte>(data);
-            ReadByte(); // skip dataType
-            var length = ReadLength();
-            _lastIndex = _readerIndex + length;
-        }
-
-        /// <summary>
-        /// Encodes written data as DER byte array.
-        /// </summary>
-        /// <returns>DER Encoded array.</returns>
-        public byte[] Encode()
-        {
-            var length = _data.Count;
-            var lengthBytes = GetLength(length);
-
-            _data.InsertRange(0, lengthBytes);
-            _data.Insert(0, Constructed | Sequence);
-
-            return _data.ToArray();
-        }
-
-        /// <summary>
-        /// Reads next mpint data type from internal buffer.
-        /// </summary>
-        /// <returns>mpint read.</returns>
-        public BigInteger ReadBigInteger()
-        {
-            var type = ReadByte();
-            if (type != Integer)
-                throw new InvalidOperationException("Invalid data type, INTEGER(02) is expected.");
-
-            var length = ReadLength();
-
-            var data = ReadBytes(length);
-
-            return new BigInteger(data.Reverse());
-        }
-
-        /// <summary>
-        /// Reads next int data type from internal buffer.
-        /// </summary>
-        /// <returns>int read.</returns>
-        public int ReadInteger()
-        {
-            var type = ReadByte();
-            if (type != Integer)
-                throw new InvalidOperationException("Invalid data type, INTEGER(02) is expected.");
-
-            var length = ReadLength();
-
-            var data = ReadBytes(length);
-
-            if (length > 4)
-                throw new InvalidOperationException("Integer type cannot occupy more then 4 bytes");
-
-            var result = 0;
-            var shift = (length - 1) * 8;
-            for (var i = 0; i < length; i++)
-            {
-                result |= data[i] << shift;
-                shift -= 8;
-            }
-
-            //return (int)(data[0] << 56 | data[1] << 48 | data[2] << 40 | data[3] << 32 | data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]);
-
-            return result;
-        }
-
-        /// <summary>
-        /// Writes BOOLEAN data into internal buffer.
-        /// </summary>
-        /// <param name="data">UInt32 data to write.</param>
-        public void Write(bool data)
-        {
-            _data.Add(Boolean);
-            _data.Add(1);
-            _data.Add((byte)(data ? 1 : 0));
-        }
-
-        /// <summary>
-        /// Writes UInt32 data into internal buffer.
-        /// </summary>
-        /// <param name="data">UInt32 data to write.</param>
-        public void Write(uint data)
-        {
-            var bytes = data.GetBytes();
-            _data.Add(Integer);
-            var length = GetLength(bytes.Length);
-            WriteBytes(length);
-            WriteBytes(bytes);
-        }
-
-        /// <summary>
-        /// Writes INTEGER data into internal buffer.
-        /// </summary>
-        /// <param name="data">BigInteger data to write.</param>
-        public void Write(BigInteger data)
-        {
-            var bytes = data.ToByteArray().Reverse();
-            _data.Add(Integer);
-            var length = GetLength(bytes.Length);
-            WriteBytes(length);
-            WriteBytes(bytes);
-        }
-
-        /// <summary>
-        /// Writes OCTETSTRING data into internal buffer.
-        /// </summary>
-        /// <param name="data">The data.</param>
-        public void Write(byte[] data)
-        {
-            _data.Add(Octetstring);
-            var length = GetLength(data.Length);
-            WriteBytes(length);
-            WriteBytes(data);
-        }
-
-        /// <summary>
-        /// Writes OBJECTIDENTIFIER data into internal buffer.
-        /// </summary>
-        /// <param name="identifier">The identifier.</param>
-        public void Write(ObjectIdentifier identifier)
-        {
-            var temp = new ulong[identifier.Identifiers.Length - 1];
-            temp[0] = identifier.Identifiers[0] * 40 + identifier.Identifiers[1];
-            Buffer.BlockCopy(identifier.Identifiers, 2 * sizeof(ulong), temp, 1 * sizeof(ulong), (identifier.Identifiers.Length - 2) * sizeof(ulong));
-            var bytes = new List<byte>();
-            foreach (var subidentifier in temp)
-            {
-                var item = subidentifier;
-                var buffer = new byte[8];
-                var bufferIndex = buffer.Length - 1;
-
-                var current = (byte)(item & 0x7F);
-                do
-                {
-                    buffer[bufferIndex] = current;
-                    if (bufferIndex < buffer.Length - 1)
-                        buffer[bufferIndex] |= 0x80;
-                    item >>= 7;
-                    current = (byte)(item & 0x7F);
-                    bufferIndex--;
-                }
-                while (current > 0);
-
-                for (var i = bufferIndex + 1; i < buffer.Length; i++)
-                {
-                    bytes.Add(buffer[i]);
-                }
-            }
-
-            _data.Add(Objectidentifier);
-            var length = GetLength(bytes.Count);
-            WriteBytes(length);
-            WriteBytes(bytes);
-        }
-
-        /// <summary>
-        /// Writes NULL data into internal buffer.
-        /// </summary>
-        public void WriteNull()
-        {
-            _data.Add(Null);
-            _data.Add(0);
-        }
-
-        /// <summary>
-        /// Writes DerData data into internal buffer.
-        /// </summary>
-        /// <param name="data">DerData data to write.</param>
-        public void Write(DerData data)
-        {
-            var bytes = data.Encode();
-            _data.AddRange(bytes);
-        }
-
-        private static IEnumerable<byte> GetLength(int length)
-        {
-            if (length > 127)
-            {
-                var size = 1;
-                var val = length;
-
-                while ((val >>= 8) != 0)
-                    size++;
-
-                var data = new byte[size];
-                data[0] = (byte)(size | 0x80);
-
-                for (int i = (size - 1) * 8, j = 1; i >= 0; i -= 8, j++)
-                {
-                    data[j] = (byte)(length >> i);
-                }
-
-                return data;
-            }
-            return new[] {(byte) length};
-        }
-
-        private int ReadLength()
-        {
-            int length = ReadByte();
-
-            if (length == 0x80)
-            {
-                throw new NotSupportedException("Indefinite-length encoding is not supported.");
-            }
-
-            if (length > 127)
-            {
-                var size = length & 0x7f;
-
-                // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
-                if (size > 4)
-                    throw new InvalidOperationException(string.Format("DER length is '{0}' and cannot be more than 4 bytes.", size));
-
-                length = 0;
-                for (var i = 0; i < size; i++)
-                {
-                    int next = ReadByte();
-
-                    length = (length << 8) + next;
-                }
-
-                if (length < 0)
-                    throw new InvalidOperationException("Corrupted data - negative length found");
-
-                //if (length >= limit)   // after all we must have read at least 1 byte
-                //    throw new IOException("Corrupted stream - out of bounds length found");
-            }
-
-            return length;
-        }
-
-        private void WriteBytes(IEnumerable<byte> data)
-        {
-            _data.AddRange(data);
-        }
-
-        private byte ReadByte()
-        {
-            if (_readerIndex > _data.Count)
-                throw new InvalidOperationException("Read out of boundaries.");
-
-            return _data[_readerIndex++];
-        }
-
-        private byte[] ReadBytes(int length)
-        {
-            if (_readerIndex + length > _data.Count)
-                throw new InvalidOperationException("Read out of boundaries.");
-
-            var result = new byte[length];
-            _data.CopyTo(_readerIndex, result, 0, length);
-            _readerIndex += length;
-            return result;
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Base class for DER encoded data.
+    /// </summary>
+    public class DerData
+    {
+        private const byte Constructed = 0x20;
+
+        private const byte Boolean = 0x01;
+        private const byte Integer = 0x02;
+        //private const byte BITSTRING = 0x03;
+        private const byte Octetstring = 0x04;
+        private const byte Null = 0x05;
+        private const byte Objectidentifier = 0x06;
+        //private const byte EXTERNAL = 0x08;
+        //private const byte ENUMERATED = 0x0a;
+        private const byte Sequence = 0x10;
+        //private const byte SEQUENCEOF = 0x10; // for completeness
+        //private const byte SET = 0x11;
+        //private const byte SETOF = 0x11; // for completeness
+
+        //private const byte NUMERICSTRING = 0x12;
+        //private const byte PRINTABLESTRING = 0x13;
+        //private const byte T61STRING = 0x14;
+        //private const byte VIDEOTEXSTRING = 0x15;
+        //private const byte IA5STRING = 0x16;
+        //private const byte UTCTIME = 0x17;
+        //private const byte GENERALIZEDTIME = 0x18;
+        //private const byte GRAPHICSTRING = 0x19;
+        //private const byte VISIBLESTRING = 0x1a;
+        //private const byte GENERALSTRING = 0x1b;
+        //private const byte UNIVERSALSTRING = 0x1c;
+        //private const byte BMPSTRING = 0x1e;
+        //private const byte UTF8STRING = 0x0c;
+        //private const byte APPLICATION = 0x40;
+        //private const byte TAGGED = 0x80;
+
+        private readonly List<byte> _data;
+
+        private int _readerIndex;
+        private readonly int _lastIndex;
+
+        /// <summary>
+        /// Gets a value indicating whether end of data is reached.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> if end of data is reached; otherwise, <c>false</c>.
+        /// </value>
+        public bool IsEndOfData
+        {
+            get
+            {
+                return _readerIndex >= _lastIndex;
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="DerData"/> class.
+        /// </summary>
+        public DerData()
+        {
+            _data = new List<byte>();
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="DerData"/> class.
+        /// </summary>
+        /// <param name="data">DER encoded data.</param>
+        public DerData(byte[] data)
+        {
+            _data = new List<byte>(data);
+            ReadByte(); // skip dataType
+            var length = ReadLength();
+            _lastIndex = _readerIndex + length;
+        }
+
+        /// <summary>
+        /// Encodes written data as DER byte array.
+        /// </summary>
+        /// <returns>DER Encoded array.</returns>
+        public byte[] Encode()
+        {
+            var length = _data.Count;
+            var lengthBytes = GetLength(length);
+
+            _data.InsertRange(0, lengthBytes);
+            _data.Insert(0, Constructed | Sequence);
+
+            return _data.ToArray();
+        }
+
+        /// <summary>
+        /// Reads next mpint data type from internal buffer.
+        /// </summary>
+        /// <returns>mpint read.</returns>
+        public BigInteger ReadBigInteger()
+        {
+            var type = ReadByte();
+            if (type != Integer)
+                throw new InvalidOperationException("Invalid data type, INTEGER(02) is expected.");
+
+            var length = ReadLength();
+
+            var data = ReadBytes(length);
+
+            return new BigInteger(data.Reverse());
+        }
+
+        /// <summary>
+        /// Reads next int data type from internal buffer.
+        /// </summary>
+        /// <returns>int read.</returns>
+        public int ReadInteger()
+        {
+            var type = ReadByte();
+            if (type != Integer)
+                throw new InvalidOperationException("Invalid data type, INTEGER(02) is expected.");
+
+            var length = ReadLength();
+
+            var data = ReadBytes(length);
+
+            if (length > 4)
+                throw new InvalidOperationException("Integer type cannot occupy more then 4 bytes");
+
+            var result = 0;
+            var shift = (length - 1) * 8;
+            for (var i = 0; i < length; i++)
+            {
+                result |= data[i] << shift;
+                shift -= 8;
+            }
+
+            //return (int)(data[0] << 56 | data[1] << 48 | data[2] << 40 | data[3] << 32 | data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]);
+
+            return result;
+        }
+
+        /// <summary>
+        /// Writes BOOLEAN data into internal buffer.
+        /// </summary>
+        /// <param name="data">UInt32 data to write.</param>
+        public void Write(bool data)
+        {
+            _data.Add(Boolean);
+            _data.Add(1);
+            _data.Add((byte)(data ? 1 : 0));
+        }
+
+        /// <summary>
+        /// Writes UInt32 data into internal buffer.
+        /// </summary>
+        /// <param name="data">UInt32 data to write.</param>
+        public void Write(uint data)
+        {
+            var bytes = data.GetBytes();
+            _data.Add(Integer);
+            var length = GetLength(bytes.Length);
+            WriteBytes(length);
+            WriteBytes(bytes);
+        }
+
+        /// <summary>
+        /// Writes INTEGER data into internal buffer.
+        /// </summary>
+        /// <param name="data">BigInteger data to write.</param>
+        public void Write(BigInteger data)
+        {
+            var bytes = data.ToByteArray().Reverse();
+            _data.Add(Integer);
+            var length = GetLength(bytes.Length);
+            WriteBytes(length);
+            WriteBytes(bytes);
+        }
+
+        /// <summary>
+        /// Writes OCTETSTRING data into internal buffer.
+        /// </summary>
+        /// <param name="data">The data.</param>
+        public void Write(byte[] data)
+        {
+            _data.Add(Octetstring);
+            var length = GetLength(data.Length);
+            WriteBytes(length);
+            WriteBytes(data);
+        }
+
+        /// <summary>
+        /// Writes OBJECTIDENTIFIER data into internal buffer.
+        /// </summary>
+        /// <param name="identifier">The identifier.</param>
+        public void Write(ObjectIdentifier identifier)
+        {
+            var temp = new ulong[identifier.Identifiers.Length - 1];
+            temp[0] = identifier.Identifiers[0] * 40 + identifier.Identifiers[1];
+            Buffer.BlockCopy(identifier.Identifiers, 2 * sizeof(ulong), temp, 1 * sizeof(ulong), (identifier.Identifiers.Length - 2) * sizeof(ulong));
+            var bytes = new List<byte>();
+            foreach (var subidentifier in temp)
+            {
+                var item = subidentifier;
+                var buffer = new byte[8];
+                var bufferIndex = buffer.Length - 1;
+
+                var current = (byte)(item & 0x7F);
+                do
+                {
+                    buffer[bufferIndex] = current;
+                    if (bufferIndex < buffer.Length - 1)
+                        buffer[bufferIndex] |= 0x80;
+                    item >>= 7;
+                    current = (byte)(item & 0x7F);
+                    bufferIndex--;
+                }
+                while (current > 0);
+
+                for (var i = bufferIndex + 1; i < buffer.Length; i++)
+                {
+                    bytes.Add(buffer[i]);
+                }
+            }
+
+            _data.Add(Objectidentifier);
+            var length = GetLength(bytes.Count);
+            WriteBytes(length);
+            WriteBytes(bytes);
+        }
+
+        /// <summary>
+        /// Writes NULL data into internal buffer.
+        /// </summary>
+        public void WriteNull()
+        {
+            _data.Add(Null);
+            _data.Add(0);
+        }
+
+        /// <summary>
+        /// Writes DerData data into internal buffer.
+        /// </summary>
+        /// <param name="data">DerData data to write.</param>
+        public void Write(DerData data)
+        {
+            var bytes = data.Encode();
+            _data.AddRange(bytes);
+        }
+
+        private static IEnumerable<byte> GetLength(int length)
+        {
+            if (length > 127)
+            {
+                var size = 1;
+                var val = length;
+
+                while ((val >>= 8) != 0)
+                    size++;
+
+                var data = new byte[size];
+                data[0] = (byte)(size | 0x80);
+
+                for (int i = (size - 1) * 8, j = 1; i >= 0; i -= 8, j++)
+                {
+                    data[j] = (byte)(length >> i);
+                }
+
+                return data;
+            }
+            return new[] {(byte) length};
+        }
+
+        private int ReadLength()
+        {
+            int length = ReadByte();
+
+            if (length == 0x80)
+            {
+                throw new NotSupportedException("Indefinite-length encoding is not supported.");
+            }
+
+            if (length > 127)
+            {
+                var size = length & 0x7f;
+
+                // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
+                if (size > 4)
+                    throw new InvalidOperationException(string.Format("DER length is '{0}' and cannot be more than 4 bytes.", size));
+
+                length = 0;
+                for (var i = 0; i < size; i++)
+                {
+                    int next = ReadByte();
+
+                    length = (length << 8) + next;
+                }
+
+                if (length < 0)
+                    throw new InvalidOperationException("Corrupted data - negative length found");
+
+                //if (length >= limit)   // after all we must have read at least 1 byte
+                //    throw new IOException("Corrupted stream - out of bounds length found");
+            }
+
+            return length;
+        }
+
+        private void WriteBytes(IEnumerable<byte> data)
+        {
+            _data.AddRange(data);
+        }
+
+        private byte ReadByte()
+        {
+            if (_readerIndex > _data.Count)
+                throw new InvalidOperationException("Read out of boundaries.");
+
+            return _data[_readerIndex++];
+        }
+
+        private byte[] ReadBytes(int length)
+        {
+            if (_readerIndex + length > _data.Count)
+                throw new InvalidOperationException("Read out of boundaries.");
+
+            var result = new byte[length];
+            _data.CopyTo(_readerIndex, result, 0, length);
+            _readerIndex += length;
+            return result;
+        }
+    }
+}

+ 24 - 24
src/Renci.SshNet/Common/ExceptionEventArgs.cs

@@ -1,24 +1,24 @@
-using System;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Provides data for the ErrorOccured events.
-    /// </summary>
-    public class ExceptionEventArgs : EventArgs
-    {
-        /// <summary>
-        /// Gets the System.Exception that represents the error that occurred.
-        /// </summary>
-        public Exception Exception { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ExceptionEventArgs"/> class.
-        /// </summary>
-        /// <param name="exception">An System.Exception that represents the error that occurred.</param>
-        public ExceptionEventArgs(Exception exception)
-        {
-            Exception = exception;
-        }
-    }
-}
+using System;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Provides data for the ErrorOccured events.
+    /// </summary>
+    public class ExceptionEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Gets the System.Exception that represents the error that occurred.
+        /// </summary>
+        public Exception Exception { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ExceptionEventArgs"/> class.
+        /// </summary>
+        /// <param name="exception">An System.Exception that represents the error that occurred.</param>
+        public ExceptionEventArgs(Exception exception)
+        {
+            Exception = exception;
+        }
+    }
+}

+ 32 - 32
src/Renci.SshNet/Common/Extensions.NET40.cs

@@ -1,32 +1,32 @@
-using System.Net.Sockets;
-
-namespace Renci.SshNet
-{
-    /// <summary>
-    /// Collection of different extension method specific for .NET 4.0
-    /// </summary>
-    public static partial class Extensions
-    {
-        /// <summary>
-        /// Indicates whether a specified string is null, empty, or consists only of white-space characters.
-        /// </summary>
-        /// <param name="value">The string to test.</param>
-        /// <returns>
-        ///   <c>true</c> if the value parameter is null or System.String.Empty, or if value consists exclusively of white-space characters; otherwise, <c>false</c>.
-        /// </returns>
-        internal static bool IsNullOrWhiteSpace(this string value)
-        {
-            return string.IsNullOrWhiteSpace(value);
-        }
-
-        internal static bool CanRead(this Socket socket)
-        {
-            return socket.Connected && socket.Poll(-1, SelectMode.SelectRead) && socket.Available > 0;
-        }
-
-        internal static bool CanWrite(this Socket socket)
-        {
-            return socket.Connected && socket.Poll(-1, SelectMode.SelectWrite);
-        }
-    }
-}
+using System.Net.Sockets;
+
+namespace Renci.SshNet
+{
+    /// <summary>
+    /// Collection of different extension method specific for .NET 4.0
+    /// </summary>
+    public static partial class Extensions
+    {
+        /// <summary>
+        /// Indicates whether a specified string is null, empty, or consists only of white-space characters.
+        /// </summary>
+        /// <param name="value">The string to test.</param>
+        /// <returns>
+        ///   <c>true</c> if the value parameter is null or System.String.Empty, or if value consists exclusively of white-space characters; otherwise, <c>false</c>.
+        /// </returns>
+        internal static bool IsNullOrWhiteSpace(this string value)
+        {
+            return string.IsNullOrWhiteSpace(value);
+        }
+
+        internal static bool CanRead(this Socket socket)
+        {
+            return socket.Connected && socket.Poll(-1, SelectMode.SelectRead) && socket.Available > 0;
+        }
+
+        internal static bool CanWrite(this Socket socket)
+        {
+            return socket.Connected && socket.Poll(-1, SelectMode.SelectWrite);
+        }
+    }
+}

+ 359 - 359
src/Renci.SshNet/Common/Extensions.cs

@@ -1,359 +1,359 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Globalization;
-using System.Linq;
-using System.Net;
-using System.Net.Sockets;
-using System.Text;
-using Renci.SshNet.Abstractions;
-using Renci.SshNet.Common;
-using Renci.SshNet.Messages;
-using Renci.SshNet.Messages.Connection;
-
-namespace Renci.SshNet
-{
-    /// <summary>
-    /// Collection of different extension method
-    /// </summary>
-    internal static partial class Extensions
-    {
-        /// <summary>
-        /// Determines whether [is null or white space] [the specified value].
-        /// </summary>
-        /// <param name="value">The value.</param>
-        /// <returns>
-        ///   <c>true</c> if [is null or white space] [the specified value]; otherwise, <c>false</c>.
-        /// </returns>
-        public static bool IsNullOrWhiteSpace(this string value)
-        {
-            if (string.IsNullOrEmpty(value)) return true;
-
-            return value.All(char.IsWhiteSpace);
-        }
-
-        internal static byte[] ToArray(this GlobalRequestName globalRequestName)
-        {
-            switch (globalRequestName)
-            {
-                case GlobalRequestName.TcpIpForward:
-                    return SshData.Ascii.GetBytes("tcpip-forward");
-                case GlobalRequestName.CancelTcpIpForward:
-                    return SshData.Ascii.GetBytes("cancel-tcpip-forward");
-                default:
-                    throw new NotSupportedException(string.Format("Global request name '{0}' is not supported.", globalRequestName));
-            }
-        }
-
-        internal static byte[] ToArray(this ServiceName serviceName)
-        {
-            switch (serviceName)
-            {
-                case ServiceName.UserAuthentication:
-                    return SshData.Ascii.GetBytes("ssh-userauth");
-                case ServiceName.Connection:
-                    return SshData.Ascii.GetBytes("ssh-connection");
-                default:
-                    throw new NotSupportedException(string.Format("Service name '{0}' is not supported.", serviceName));
-            }
-        }
-
-        internal static ServiceName ToServiceName(this byte[] data)
-        {
-            var sshServiceName = SshData.Ascii.GetString(data, 0, data.Length);
-            switch (sshServiceName)
-            {
-                case "ssh-userauth":
-                    return ServiceName.UserAuthentication;
-                case "ssh-connection":
-                    return ServiceName.Connection;
-                default:
-                    throw new NotSupportedException(string.Format("Service name '{0}' is not supported.", sshServiceName));
-            }
-        }
-
-        internal static GlobalRequestName ToGlobalRequestName(this byte[] data)
-        {
-            var sshGlobalRequestName = SshData.Ascii.GetString(data, 0, data.Length);
-            switch (sshGlobalRequestName)
-            {
-                case "tcpip-forward":
-                    return GlobalRequestName.TcpIpForward;
-                case "cancel-tcpip-forward":
-                    return GlobalRequestName.CancelTcpIpForward;
-                default:
-                    throw new NotSupportedException(string.Format("Global request name '{0}' is not supported.", sshGlobalRequestName));
-            }
-        }
-
-        internal static BigInteger ToBigInteger(this byte[] data)
-        {
-            var reversed = new byte[data.Length];
-            Buffer.BlockCopy(data, 0, reversed, 0, data.Length);
-            return new BigInteger(reversed.Reverse());
-        }
-
-        /// <summary>
-        /// Reverses the sequence of the elements in the entire one-dimensional <see cref="Array"/>.
-        /// </summary>
-        /// <param name="array">The one-dimensional <see cref="Array"/> to reverse.</param>
-        /// <returns>
-        /// The <see cref="Array"/> with its elements reversed.
-        /// </returns>
-        internal static T[] Reverse<T>(this T[] array)
-        {
-            Array.Reverse(array);
-            return array;
-        }
-
-        /// <summary>
-        /// Prints out 
-        /// </summary>
-        /// <param name="bytes">The bytes.</param>
-        internal static void DebugPrint(this IEnumerable<byte> bytes)
-        {
-            var sb = new StringBuilder();
-
-            foreach (var b in bytes)
-            {
-                sb.AppendFormat(CultureInfo.CurrentCulture, "0x{0:x2}, ", b);
-            }
-            Debug.WriteLine(sb.ToString());
-        }
-
-        /// <summary>
-        /// Creates an instance of the specified type using that type's default constructor.
-        /// </summary>
-        /// <typeparam name="T">The type to create.</typeparam>
-        /// <param name="type">Type of the instance to create.</param>
-        /// <returns>A reference to the newly created object.</returns>
-        internal static T CreateInstance<T>(this Type type) where T : class
-        {
-            if (type == null)
-                return null;
-            return Activator.CreateInstance(type) as T;
-        }
-
-        /// <summary>
-        /// Returns the specified 16-bit unsigned integer value as an array of bytes.
-        /// </summary>
-        /// <param name="value">The number to convert.</param>
-        /// <returns>An array of bytes with length 2.</returns>
-        internal static byte[] GetBytes(this ushort value)
-        {
-            return new[] {(byte) (value >> 8), (byte) (value & 0xFF)};
-        }
-
-        /// <summary>
-        /// Returns the specified 32-bit unsigned integer value as an array of bytes.
-        /// </summary>
-        /// <param name="value">The number to convert.</param>
-        /// <returns>An array of bytes with length 4.</returns>
-        internal static byte[] GetBytes(this uint value)
-        {
-            var buffer = new byte[4];
-            value.Write(buffer, 0);
-            return buffer;
-        }
-
-        /// <summary>
-        /// Returns the specified 32-bit unsigned integer value as an array of bytes.
-        /// </summary>
-        /// <param name="value">The number to convert.</param>
-        /// <param name="buffer">The array of bytes to write <paramref name="value"/> to.</param>
-        /// <param name="offset">The zero-based offset in <paramref name="buffer"/> at which to begin writing.</param>
-        internal static void Write(this uint value, byte[] buffer, int offset)
-        {
-            buffer[offset++] = (byte) (value >> 24);
-            buffer[offset++] = (byte) (value >> 16);
-            buffer[offset++] = (byte)(value >> 8);
-            buffer[offset] = (byte) (value & 0xFF);
-        }
-
-        /// <summary>
-        /// Returns the specified 64-bit unsigned integer value as an array of bytes.
-        /// </summary>
-        /// <param name="value">The number to convert.</param>
-        /// <returns>An array of bytes with length 8.</returns>
-        internal static byte[] GetBytes(this ulong value)
-        {
-            return new[]
-                {
-                    (byte) (value >> 56), (byte) (value >> 48), (byte) (value >> 40), (byte) (value >> 32),
-                    (byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) (value & 0xFF)
-                };
-        }
-
-        /// <summary>
-        /// Returns the specified 64-bit signed integer value as an array of bytes.
-        /// </summary>
-        /// <param name="value">The number to convert.</param>
-        /// <returns>An array of bytes with length 8.</returns>
-        internal static byte[] GetBytes(this long value)
-        {
-            return new[]
-                {
-                    (byte) (value >> 56), (byte) (value >> 48), (byte) (value >> 40), (byte) (value >> 32),
-                    (byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) (value & 0xFF)
-                };
-        }
-
-        internal static void ValidatePort(this uint value, string argument)
-        {
-            if (value > IPEndPoint.MaxPort)
-                throw new ArgumentOutOfRangeException(argument,
-                    string.Format(CultureInfo.InvariantCulture, "Specified value cannot be greater than {0}.",
-                        IPEndPoint.MaxPort));
-        }
-
-        internal static void ValidatePort(this int value, string argument)
-        {
-            if (value < IPEndPoint.MinPort)
-                throw new ArgumentOutOfRangeException(argument,
-                    string.Format(CultureInfo.InvariantCulture, "Specified value cannot be less than {0}.",
-                        IPEndPoint.MinPort));
-
-            if (value > IPEndPoint.MaxPort)
-                throw new ArgumentOutOfRangeException(argument,
-                    string.Format(CultureInfo.InvariantCulture, "Specified value cannot be greater than {0}.",
-                        IPEndPoint.MaxPort));
-        }
-
-        /// <summary>
-        /// Returns a specified number of contiguous bytes from a given offset.
-        /// </summary>
-        /// <param name="value">The array to return a number of bytes from.</param>
-        /// <param name="offset">The zero-based offset in <paramref name="value"/> at which to begin taking bytes.</param>
-        /// <param name="count">The number of bytes to take from <paramref name="value"/>.</param>
-        /// <returns>
-        /// A <see cref="byte"/> array that contains the specified number of bytes at the specified offset
-        /// of the input array.
-        /// </returns>
-        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c>.</exception>
-        /// <remarks>
-        /// When <paramref name="offset"/> is zero and <paramref name="count"/> equals the length of <paramref name="value"/>,
-        /// then <paramref name="value"/> is returned.
-        /// </remarks>
-        public static byte[] Take(this byte[] value, int offset, int count)
-        {
-            if (value == null)
-                throw new ArgumentNullException("value");
-
-            if (count == 0)
-                return Array<byte>.Empty;
-
-            if (offset == 0 && value.Length == count)
-                return value;
-
-            var taken = new byte[count];
-            Buffer.BlockCopy(value, offset, taken, 0, count);
-            return taken;
-        }
-
-        /// <summary>
-        /// Returns a specified number of contiguous bytes from the start of the specified byte array.
-        /// </summary>
-        /// <param name="value">The array to return a number of bytes from.</param>
-        /// <param name="count">The number of bytes to take from <paramref name="value"/>.</param>
-        /// <returns>
-        /// A <see cref="byte"/> array that contains the specified number of bytes at the start of the input array.
-        /// </returns>
-        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c>.</exception>
-        /// <remarks>
-        /// When <paramref name="count"/> equals the length of <paramref name="value"/>, then <paramref name="value"/>
-        /// is returned.
-        /// </remarks>
-        public static byte[] Take(this byte[] value, int count)
-        {
-            if (value == null)
-                throw new ArgumentNullException("value");
-
-            if (count == 0)
-                return Array<byte>.Empty;
-
-            if (value.Length == count)
-                return value;
-
-            var taken = new byte[count];
-            Buffer.BlockCopy(value, 0, taken, 0, count);
-            return taken;
-        }
-
-        public static bool IsEqualTo(this byte[] left, byte[] right)
-        {
-            if (left == null)
-                throw new ArgumentNullException("left");
-            if (right == null)
-                throw new ArgumentNullException("right");
-
-            if (left == right)
-                return true;
-
-            if (left.Length != right.Length)
-                return false;
-
-            for (var i = 0; i < left.Length; i++)
-            {
-                if (left[i] != right[i])
-                    return false;
-            }
-
-            return true;
-        }
-
-        /// <summary>
-        /// Trims the leading zero from a byte array.
-        /// </summary>
-        /// <param name="value">The value.</param>
-        /// <returns>
-        /// <paramref name="value"/> without leading zeros.
-        /// </returns>
-        public static byte[] TrimLeadingZeros(this byte[] value)
-        {
-            if (value == null)
-                throw new ArgumentNullException("value");
-
-            for (var i = 0; i < value.Length; i++)
-            {
-                if (value[i] == 0)
-                    continue;
-
-                // if the first byte is non-zero, then we return the byte array as is
-                if (i == 0)
-                    return value;
-
-                var remainingBytes = value.Length - i;
-
-                var cleaned = new byte[remainingBytes];
-                Buffer.BlockCopy(value, i, cleaned, 0, remainingBytes);
-                return cleaned;
-            }
-
-            return value;
-        }
-
-        public static byte[] Concat(this byte[] first, byte[] second)
-        {
-            if (first == null || first.Length == 0)
-                return second;
-
-            if (second == null || second.Length == 0)
-                return first;
-
-            var concat = new byte[first.Length + second.Length];
-            Buffer.BlockCopy(first, 0, concat, 0, first.Length);
-            Buffer.BlockCopy(second, 0, concat, first.Length, second.Length);
-            return concat;
-        }
-
-        internal static bool CanRead(this Socket socket)
-        {
-            return SocketAbstraction.CanRead(socket);
-        }
-
-        internal static bool CanWrite(this Socket socket)
-        {
-            return SocketAbstraction.CanWrite(socket);
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using Renci.SshNet.Abstractions;
+using Renci.SshNet.Common;
+using Renci.SshNet.Messages;
+using Renci.SshNet.Messages.Connection;
+
+namespace Renci.SshNet
+{
+    /// <summary>
+    /// Collection of different extension method
+    /// </summary>
+    internal static partial class Extensions
+    {
+        /// <summary>
+        /// Determines whether [is null or white space] [the specified value].
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>
+        ///   <c>true</c> if [is null or white space] [the specified value]; otherwise, <c>false</c>.
+        /// </returns>
+        public static bool IsNullOrWhiteSpace(this string value)
+        {
+            if (string.IsNullOrEmpty(value)) return true;
+
+            return value.All(char.IsWhiteSpace);
+        }
+
+        internal static byte[] ToArray(this GlobalRequestName globalRequestName)
+        {
+            switch (globalRequestName)
+            {
+                case GlobalRequestName.TcpIpForward:
+                    return SshData.Ascii.GetBytes("tcpip-forward");
+                case GlobalRequestName.CancelTcpIpForward:
+                    return SshData.Ascii.GetBytes("cancel-tcpip-forward");
+                default:
+                    throw new NotSupportedException(string.Format("Global request name '{0}' is not supported.", globalRequestName));
+            }
+        }
+
+        internal static byte[] ToArray(this ServiceName serviceName)
+        {
+            switch (serviceName)
+            {
+                case ServiceName.UserAuthentication:
+                    return SshData.Ascii.GetBytes("ssh-userauth");
+                case ServiceName.Connection:
+                    return SshData.Ascii.GetBytes("ssh-connection");
+                default:
+                    throw new NotSupportedException(string.Format("Service name '{0}' is not supported.", serviceName));
+            }
+        }
+
+        internal static ServiceName ToServiceName(this byte[] data)
+        {
+            var sshServiceName = SshData.Ascii.GetString(data, 0, data.Length);
+            switch (sshServiceName)
+            {
+                case "ssh-userauth":
+                    return ServiceName.UserAuthentication;
+                case "ssh-connection":
+                    return ServiceName.Connection;
+                default:
+                    throw new NotSupportedException(string.Format("Service name '{0}' is not supported.", sshServiceName));
+            }
+        }
+
+        internal static GlobalRequestName ToGlobalRequestName(this byte[] data)
+        {
+            var sshGlobalRequestName = SshData.Ascii.GetString(data, 0, data.Length);
+            switch (sshGlobalRequestName)
+            {
+                case "tcpip-forward":
+                    return GlobalRequestName.TcpIpForward;
+                case "cancel-tcpip-forward":
+                    return GlobalRequestName.CancelTcpIpForward;
+                default:
+                    throw new NotSupportedException(string.Format("Global request name '{0}' is not supported.", sshGlobalRequestName));
+            }
+        }
+
+        internal static BigInteger ToBigInteger(this byte[] data)
+        {
+            var reversed = new byte[data.Length];
+            Buffer.BlockCopy(data, 0, reversed, 0, data.Length);
+            return new BigInteger(reversed.Reverse());
+        }
+
+        /// <summary>
+        /// Reverses the sequence of the elements in the entire one-dimensional <see cref="Array"/>.
+        /// </summary>
+        /// <param name="array">The one-dimensional <see cref="Array"/> to reverse.</param>
+        /// <returns>
+        /// The <see cref="Array"/> with its elements reversed.
+        /// </returns>
+        internal static T[] Reverse<T>(this T[] array)
+        {
+            Array.Reverse(array);
+            return array;
+        }
+
+        /// <summary>
+        /// Prints out 
+        /// </summary>
+        /// <param name="bytes">The bytes.</param>
+        internal static void DebugPrint(this IEnumerable<byte> bytes)
+        {
+            var sb = new StringBuilder();
+
+            foreach (var b in bytes)
+            {
+                sb.AppendFormat(CultureInfo.CurrentCulture, "0x{0:x2}, ", b);
+            }
+            Debug.WriteLine(sb.ToString());
+        }
+
+        /// <summary>
+        /// Creates an instance of the specified type using that type's default constructor.
+        /// </summary>
+        /// <typeparam name="T">The type to create.</typeparam>
+        /// <param name="type">Type of the instance to create.</param>
+        /// <returns>A reference to the newly created object.</returns>
+        internal static T CreateInstance<T>(this Type type) where T : class
+        {
+            if (type == null)
+                return null;
+            return Activator.CreateInstance(type) as T;
+        }
+
+        /// <summary>
+        /// Returns the specified 16-bit unsigned integer value as an array of bytes.
+        /// </summary>
+        /// <param name="value">The number to convert.</param>
+        /// <returns>An array of bytes with length 2.</returns>
+        internal static byte[] GetBytes(this ushort value)
+        {
+            return new[] {(byte) (value >> 8), (byte) (value & 0xFF)};
+        }
+
+        /// <summary>
+        /// Returns the specified 32-bit unsigned integer value as an array of bytes.
+        /// </summary>
+        /// <param name="value">The number to convert.</param>
+        /// <returns>An array of bytes with length 4.</returns>
+        internal static byte[] GetBytes(this uint value)
+        {
+            var buffer = new byte[4];
+            value.Write(buffer, 0);
+            return buffer;
+        }
+
+        /// <summary>
+        /// Returns the specified 32-bit unsigned integer value as an array of bytes.
+        /// </summary>
+        /// <param name="value">The number to convert.</param>
+        /// <param name="buffer">The array of bytes to write <paramref name="value"/> to.</param>
+        /// <param name="offset">The zero-based offset in <paramref name="buffer"/> at which to begin writing.</param>
+        internal static void Write(this uint value, byte[] buffer, int offset)
+        {
+            buffer[offset++] = (byte) (value >> 24);
+            buffer[offset++] = (byte) (value >> 16);
+            buffer[offset++] = (byte)(value >> 8);
+            buffer[offset] = (byte) (value & 0xFF);
+        }
+
+        /// <summary>
+        /// Returns the specified 64-bit unsigned integer value as an array of bytes.
+        /// </summary>
+        /// <param name="value">The number to convert.</param>
+        /// <returns>An array of bytes with length 8.</returns>
+        internal static byte[] GetBytes(this ulong value)
+        {
+            return new[]
+                {
+                    (byte) (value >> 56), (byte) (value >> 48), (byte) (value >> 40), (byte) (value >> 32),
+                    (byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) (value & 0xFF)
+                };
+        }
+
+        /// <summary>
+        /// Returns the specified 64-bit signed integer value as an array of bytes.
+        /// </summary>
+        /// <param name="value">The number to convert.</param>
+        /// <returns>An array of bytes with length 8.</returns>
+        internal static byte[] GetBytes(this long value)
+        {
+            return new[]
+                {
+                    (byte) (value >> 56), (byte) (value >> 48), (byte) (value >> 40), (byte) (value >> 32),
+                    (byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) (value & 0xFF)
+                };
+        }
+
+        internal static void ValidatePort(this uint value, string argument)
+        {
+            if (value > IPEndPoint.MaxPort)
+                throw new ArgumentOutOfRangeException(argument,
+                    string.Format(CultureInfo.InvariantCulture, "Specified value cannot be greater than {0}.",
+                        IPEndPoint.MaxPort));
+        }
+
+        internal static void ValidatePort(this int value, string argument)
+        {
+            if (value < IPEndPoint.MinPort)
+                throw new ArgumentOutOfRangeException(argument,
+                    string.Format(CultureInfo.InvariantCulture, "Specified value cannot be less than {0}.",
+                        IPEndPoint.MinPort));
+
+            if (value > IPEndPoint.MaxPort)
+                throw new ArgumentOutOfRangeException(argument,
+                    string.Format(CultureInfo.InvariantCulture, "Specified value cannot be greater than {0}.",
+                        IPEndPoint.MaxPort));
+        }
+
+        /// <summary>
+        /// Returns a specified number of contiguous bytes from a given offset.
+        /// </summary>
+        /// <param name="value">The array to return a number of bytes from.</param>
+        /// <param name="offset">The zero-based offset in <paramref name="value"/> at which to begin taking bytes.</param>
+        /// <param name="count">The number of bytes to take from <paramref name="value"/>.</param>
+        /// <returns>
+        /// A <see cref="byte"/> array that contains the specified number of bytes at the specified offset
+        /// of the input array.
+        /// </returns>
+        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c>.</exception>
+        /// <remarks>
+        /// When <paramref name="offset"/> is zero and <paramref name="count"/> equals the length of <paramref name="value"/>,
+        /// then <paramref name="value"/> is returned.
+        /// </remarks>
+        public static byte[] Take(this byte[] value, int offset, int count)
+        {
+            if (value == null)
+                throw new ArgumentNullException("value");
+
+            if (count == 0)
+                return Array<byte>.Empty;
+
+            if (offset == 0 && value.Length == count)
+                return value;
+
+            var taken = new byte[count];
+            Buffer.BlockCopy(value, offset, taken, 0, count);
+            return taken;
+        }
+
+        /// <summary>
+        /// Returns a specified number of contiguous bytes from the start of the specified byte array.
+        /// </summary>
+        /// <param name="value">The array to return a number of bytes from.</param>
+        /// <param name="count">The number of bytes to take from <paramref name="value"/>.</param>
+        /// <returns>
+        /// A <see cref="byte"/> array that contains the specified number of bytes at the start of the input array.
+        /// </returns>
+        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c>.</exception>
+        /// <remarks>
+        /// When <paramref name="count"/> equals the length of <paramref name="value"/>, then <paramref name="value"/>
+        /// is returned.
+        /// </remarks>
+        public static byte[] Take(this byte[] value, int count)
+        {
+            if (value == null)
+                throw new ArgumentNullException("value");
+
+            if (count == 0)
+                return Array<byte>.Empty;
+
+            if (value.Length == count)
+                return value;
+
+            var taken = new byte[count];
+            Buffer.BlockCopy(value, 0, taken, 0, count);
+            return taken;
+        }
+
+        public static bool IsEqualTo(this byte[] left, byte[] right)
+        {
+            if (left == null)
+                throw new ArgumentNullException("left");
+            if (right == null)
+                throw new ArgumentNullException("right");
+
+            if (left == right)
+                return true;
+
+            if (left.Length != right.Length)
+                return false;
+
+            for (var i = 0; i < left.Length; i++)
+            {
+                if (left[i] != right[i])
+                    return false;
+            }
+
+            return true;
+        }
+
+        /// <summary>
+        /// Trims the leading zero from a byte array.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>
+        /// <paramref name="value"/> without leading zeros.
+        /// </returns>
+        public static byte[] TrimLeadingZeros(this byte[] value)
+        {
+            if (value == null)
+                throw new ArgumentNullException("value");
+
+            for (var i = 0; i < value.Length; i++)
+            {
+                if (value[i] == 0)
+                    continue;
+
+                // if the first byte is non-zero, then we return the byte array as is
+                if (i == 0)
+                    return value;
+
+                var remainingBytes = value.Length - i;
+
+                var cleaned = new byte[remainingBytes];
+                Buffer.BlockCopy(value, i, cleaned, 0, remainingBytes);
+                return cleaned;
+            }
+
+            return value;
+        }
+
+        public static byte[] Concat(this byte[] first, byte[] second)
+        {
+            if (first == null || first.Length == 0)
+                return second;
+
+            if (second == null || second.Length == 0)
+                return first;
+
+            var concat = new byte[first.Length + second.Length];
+            Buffer.BlockCopy(first, 0, concat, 0, first.Length);
+            Buffer.BlockCopy(second, 0, concat, first.Length, second.Length);
+            return concat;
+        }
+
+        internal static bool CanRead(this Socket socket)
+        {
+            return SocketAbstraction.CanRead(socket);
+        }
+
+        internal static bool CanWrite(this Socket socket)
+        {
+            return SocketAbstraction.CanWrite(socket);
+        }
+    }
+}

+ 63 - 63
src/Renci.SshNet/Common/HostKeyEventArgs.cs

@@ -1,63 +1,63 @@
-using System;
-using Renci.SshNet.Security.Cryptography;
-using Renci.SshNet.Security;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Provides data for the HostKeyReceived event.
-    /// </summary>
-    public class HostKeyEventArgs : EventArgs
-    {
-        /// <summary>
-        /// Gets or sets a value indicating whether host key can be trusted.
-        /// </summary>
-        /// <value>
-        ///   <c>true</c> if host key can be trusted; otherwise, <c>false</c>.
-        /// </value>
-        public bool CanTrust { get; set; }
-
-        /// <summary>
-        /// Gets the host key.
-        /// </summary>
-        public byte[] HostKey { get; private set; }
-
-        /// <summary>
-        /// Gets the host key name.
-        /// </summary>
-        public string HostKeyName{ get; private set; }
-
-        /// <summary>
-        /// Gets the finger print.
-        /// </summary>
-        public byte[] FingerPrint { get; private set; }
-
-        /// <summary>
-        /// Gets the length of the key in bits.
-        /// </summary>
-        /// <value>
-        /// The length of the key in bits.
-        /// </value>
-        public int KeyLength { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="HostKeyEventArgs"/> class.
-        /// </summary>
-        /// <param name="host">The host.</param>
-        public HostKeyEventArgs(KeyHostAlgorithm host)
-        {
-            CanTrust = true;   //  Set default value
-
-            HostKey = host.Data;
-
-            HostKeyName = host.Name;
-
-            KeyLength = host.Key.KeyLength;
-
-            using (var md5 = HashAlgorithmFactory.CreateMD5())
-            {
-                FingerPrint = md5.ComputeHash(host.Data);
-            }
-        }
-    }
-}
+using System;
+using Renci.SshNet.Security.Cryptography;
+using Renci.SshNet.Security;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Provides data for the HostKeyReceived event.
+    /// </summary>
+    public class HostKeyEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Gets or sets a value indicating whether host key can be trusted.
+        /// </summary>
+        /// <value>
+        ///   <c>true</c> if host key can be trusted; otherwise, <c>false</c>.
+        /// </value>
+        public bool CanTrust { get; set; }
+
+        /// <summary>
+        /// Gets the host key.
+        /// </summary>
+        public byte[] HostKey { get; private set; }
+
+        /// <summary>
+        /// Gets the host key name.
+        /// </summary>
+        public string HostKeyName{ get; private set; }
+
+        /// <summary>
+        /// Gets the finger print.
+        /// </summary>
+        public byte[] FingerPrint { get; private set; }
+
+        /// <summary>
+        /// Gets the length of the key in bits.
+        /// </summary>
+        /// <value>
+        /// The length of the key in bits.
+        /// </value>
+        public int KeyLength { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="HostKeyEventArgs"/> class.
+        /// </summary>
+        /// <param name="host">The host.</param>
+        public HostKeyEventArgs(KeyHostAlgorithm host)
+        {
+            CanTrust = true;   //  Set default value
+
+            HostKey = host.Data;
+
+            HostKeyName = host.Name;
+
+            KeyLength = host.Key.KeyLength;
+
+            using (var md5 = HashAlgorithmFactory.CreateMD5())
+            {
+                FingerPrint = md5.ComputeHash(host.Data);
+            }
+        }
+    }
+}

+ 24 - 24
src/Renci.SshNet/Common/NetConfServerException.NET40.cs

@@ -1,24 +1,24 @@
-using System;
-using System.Runtime.Serialization;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// The exception that is thrown when there is something wrong with the server capabilities.
-    /// </summary>
-    [Serializable]
-    public partial class NetConfServerException
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshAuthenticationException"/> class.
-        /// </summary>
-        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
-        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
-        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
-        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
-        protected NetConfServerException(SerializationInfo info, StreamingContext context)
-            : base(info, context)
-        {
-        }
-    }
-}
+using System;
+using System.Runtime.Serialization;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// The exception that is thrown when there is something wrong with the server capabilities.
+    /// </summary>
+    [Serializable]
+    public partial class NetConfServerException
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshAuthenticationException"/> class.
+        /// </summary>
+        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
+        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
+        protected NetConfServerException(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+        }
+    }
+}

+ 36 - 36
src/Renci.SshNet/Common/NetConfServerException.cs

@@ -1,36 +1,36 @@
-using System;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// The exception that is thrown when there is something wrong with the server capabilities.
-    /// </summary>
-    public partial class NetConfServerException : SshException
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="NetConfServerException"/> class.
-        /// </summary>
-        public NetConfServerException()
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="NetConfServerException"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        public NetConfServerException(string message)
-            : base(message)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="NetConfServerException"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <param name="innerException">The inner exception.</param>
-        public NetConfServerException(string message, Exception innerException) :
-            base(message, innerException)
-        {
-        }
-    }
-}
+using System;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// The exception that is thrown when there is something wrong with the server capabilities.
+    /// </summary>
+    public partial class NetConfServerException : SshException
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="NetConfServerException"/> class.
+        /// </summary>
+        public NetConfServerException()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="NetConfServerException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        public NetConfServerException(string message)
+            : base(message)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="NetConfServerException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        /// <param name="innerException">The inner exception.</param>
+        public NetConfServerException(string message, Exception innerException) :
+            base(message, innerException)
+        {
+        }
+    }
+}

+ 28 - 28
src/Renci.SshNet/Common/ObjectIdentifier.cs

@@ -1,28 +1,28 @@
-using System;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Describes object identifier for DER encoding
-    /// </summary>
-    public struct ObjectIdentifier
-    {
-        /// <summary>
-        /// Gets the object identifier.
-        /// </summary>
-        public ulong[] Identifiers { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ObjectIdentifier"/> class.
-        /// </summary>
-        /// <param name="identifiers">The identifiers.</param>
-        public ObjectIdentifier(params ulong[] identifiers)
-            : this()
-        {
-            if (identifiers.Length < 2)
-                throw new ArgumentException("identifiers");
-
-            Identifiers = identifiers;
-        }
-    }
-}
+using System;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Describes object identifier for DER encoding
+    /// </summary>
+    public struct ObjectIdentifier
+    {
+        /// <summary>
+        /// Gets the object identifier.
+        /// </summary>
+        public ulong[] Identifiers { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ObjectIdentifier"/> class.
+        /// </summary>
+        /// <param name="identifiers">The identifiers.</param>
+        public ObjectIdentifier(params ulong[] identifiers)
+            : this()
+        {
+            if (identifiers.Length < 2)
+                throw new ArgumentException("identifiers");
+
+            Identifiers = identifiers;
+        }
+    }
+}

+ 346 - 346
src/Renci.SshNet/Common/PipeStream.cs

@@ -1,346 +1,346 @@
-namespace Renci.SshNet.Common
-{
-    using System;
-    using System.Collections.Generic;
-    using System.IO;
-    using System.Threading;
-    using System.Globalization;
-
-    /// <summary>
-    /// PipeStream is a thread-safe read/write data stream for use between two threads in a 
-    /// single-producer/single-consumer type problem.
-    /// </summary>
-    /// <version>2006/10/13 1.0</version>
-    /// <remarks>Update on 2008/10/9 1.1 - uses Monitor instead of Manual Reset events for more elegant synchronicity.</remarks>
-    /// <license>
-    ///	Copyright (c) 2006 James Kolpack (james dot kolpack at google mail)
-    ///	
-    ///	Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 
-    ///	associated documentation files (the "Software"), to deal in the Software without restriction, 
-    ///	including without limitation the rights to use, copy, modify, merge, publish, distribute, 
-    ///	sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
-    ///	furnished to do so, subject to the following conditions:
-    ///	
-    ///	The above copyright notice and this permission notice shall be included in all copies or 
-    ///	substantial portions of the Software.
-    ///	
-    ///	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
-    ///	INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
-    ///	PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
-    ///	LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 
-    ///	OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
-    ///	OTHER DEALINGS IN THE SOFTWARE.
-    /// </license>
-    public class PipeStream : Stream
-    {
-        #region Private members
-
-        /// <summary>
-        /// Queue of bytes provides the datastructure for transmitting from an
-        /// input stream to an output stream.
-        /// </summary>
-        /// <remarks>Possible more effecient ways to accomplish this.</remarks>
-        private readonly Queue<byte> _buffer = new Queue<byte>();
-
-        /// <summary>
-        /// Indicates that the input stream has been flushed and that
-        /// all remaining data should be written to the output stream.
-        /// </summary>
-        private bool _isFlushed;
-
-        /// <summary>
-        /// Maximum number of bytes to store in the buffer.
-        /// </summary>
-        private long _maxBufferLength = 200 * 1024 * 1024;
-
-        /// <summary>
-        /// Setting this to true will cause Read() to block if it appears
-        /// that it will run out of data.
-        /// </summary>
-        private bool _canBlockLastRead;
-
-        /// <summary>
-        /// Indicates whether the current <see cref="PipeStream"/> is disposed.
-        /// </summary>
-        private bool _isDisposed;
-
-        #endregion
-
-        #region Public properties
-
-        /// <summary>
-        /// Gets or sets the maximum number of bytes to store in the buffer.
-        /// </summary>
-        /// <value>The length of the max buffer.</value>
-        public long MaxBufferLength
-        {
-            get { return _maxBufferLength; }
-            set { _maxBufferLength = value; }
-        }
-
-        /// <summary>
-        /// Gets or sets a value indicating whether to block last read method before the buffer is empty.
-        /// When true, Read() will block until it can fill the passed in buffer and count.
-        /// When false, Read() will not block, returning all the available buffer data.
-        /// </summary>
-        /// <remarks>
-        /// Setting to true will remove the possibility of ending a stream reader prematurely.
-        /// </remarks>
-        /// <value>
-        /// 	<c>true</c> if block last read method before the buffer is empty; otherwise, <c>false</c>.
-        /// </value>
-        /// <exception cref="ObjectDisposedException">Methods were called after the stream was closed.</exception>
-        public bool BlockLastReadBuffer
-        {
-            get
-            {
-                if (_isDisposed)
-                    throw CreateObjectDisposedException();
-
-                return _canBlockLastRead;
-            }
-            set
-            {
-                if (_isDisposed)
-                    throw CreateObjectDisposedException();
-
-                _canBlockLastRead = value;
-
-                // when turning off the block last read, signal Read() that it may now read the rest of the buffer.
-                if (!_canBlockLastRead)
-                    lock (_buffer)
-                        Monitor.Pulse(_buffer);
-            }
-        }
-
-        #endregion
-
-        #region Stream overide methods
-
-        /// <summary>
-        /// When overridden in a derived class, clears all buffers for this stream and causes any buffered data to be written to the underlying device.
-        /// </summary>
-        /// <exception cref="IOException">An I/O error occurs.</exception>
-        /// <exception cref="ObjectDisposedException">Methods were called after the stream was closed.</exception>
-        public override void Flush()
-        {
-            if (_isDisposed)
-                throw CreateObjectDisposedException();
-
-            _isFlushed = true;
-            lock (_buffer)
-                Monitor.Pulse(_buffer);
-        }
-
-        /// <summary>
-        /// When overridden in a derived class, sets the position within the current stream.
-        /// </summary>
-        /// <returns>
-        /// The new position within the current stream.
-        /// </returns>
-        /// <param name="offset">A byte offset relative to the origin parameter.</param>
-        /// <param name="origin">A value of type <see cref="SeekOrigin"/> indicating the reference point used to obtain the new position.</param>
-        /// <exception cref="NotSupportedException">The stream does not support seeking, such as if the stream is constructed from a pipe or console output.</exception>
-        public override long Seek(long offset, SeekOrigin origin)
-        {
-            throw new NotSupportedException();
-        }
-
-        /// <summary>
-        /// When overridden in a derived class, sets the length of the current stream.
-        /// </summary>
-        /// <param name="value">The desired length of the current stream in bytes.</param>
-        /// <exception cref="NotSupportedException">The stream does not support both writing and seeking, such as if the stream is constructed from a pipe or console output.</exception>
-        public override void SetLength(long value)
-        {
-            throw new NotSupportedException();
-        }
-
-        ///<summary>
-        ///When overridden in a derived class, reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read.
-        ///</summary>
-        ///<returns>
-        ///The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero if the end of the stream has been reached.
-        ///</returns>
-        ///<param name="offset">The zero-based byte offset in buffer at which to begin storing the data read from the current stream.</param>
-        ///<param name="count">The maximum number of bytes to be read from the current stream.</param>
-        ///<param name="buffer">An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and (offset + count - 1) replaced by the bytes read from the current source.</param>
-        ///<exception cref="ArgumentException">The sum of offset and count is larger than the buffer length.</exception>
-        ///<exception cref="ObjectDisposedException">Methods were called after the stream was closed.</exception>
-        ///<exception cref="NotSupportedException">The stream does not support reading.</exception>
-        ///<exception cref="ArgumentNullException">buffer is null.</exception>
-        ///<exception cref="IOException">An I/O error occurs.</exception>
-        ///<exception cref="ArgumentOutOfRangeException">offset or count is negative.</exception>
-        public override int Read(byte[] buffer, int offset, int count)
-        {
-            if (offset != 0)
-                throw new NotSupportedException("Offsets with value of non-zero are not supported");
-            if (buffer == null)
-                throw new ArgumentNullException("buffer");
-            if (offset + count > buffer.Length)
-                throw new ArgumentException("The sum of offset and count is greater than the buffer length.");
-            if (offset < 0 || count < 0)
-                throw new ArgumentOutOfRangeException("offset", "offset or count is negative.");
-            if (BlockLastReadBuffer && count >= _maxBufferLength)
-                throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, "count({0}) > mMaxBufferLength({1})", count, _maxBufferLength));
-            if (_isDisposed)
-                throw CreateObjectDisposedException();
-            if (count == 0)
-                return 0;
-
-            int readLength = 0;
-
-            lock (_buffer)
-            {
-                while (!ReadAvailable(count))
-                    Monitor.Wait(_buffer);
-
-                // fill the read buffer
-                for (; readLength < count && Length > 0 && _buffer.Count > 0; readLength++)
-                {
-                    buffer[readLength] = _buffer.Dequeue();
-                }
-
-                Monitor.Pulse(_buffer);
-            }
-            return readLength;
-        }
-
-        /// <summary>
-        /// Returns true if there are
-        /// </summary>
-        /// <param name="count">The count.</param>
-        /// <returns><c>True</c> if data available; otherwise<c>false</c>.</returns>
-        private bool ReadAvailable(int count)
-        {
-            return (Length >= count || _isFlushed) &&
-                   (Length >= (count + 1) || !BlockLastReadBuffer);
-        }
-
-        ///<summary>
-        ///When overridden in a derived class, writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written.
-        ///</summary>
-        ///<param name="offset">The zero-based byte offset in buffer at which to begin copying bytes to the current stream.</param>
-        ///<param name="count">The number of bytes to be written to the current stream.</param>
-        ///<param name="buffer">An array of bytes. This method copies count bytes from buffer to the current stream.</param>
-        ///<exception cref="IOException">An I/O error occurs.</exception>
-        ///<exception cref="NotSupportedException">The stream does not support writing.</exception>
-        ///<exception cref="ObjectDisposedException">Methods were called after the stream was closed.</exception>
-        ///<exception cref="ArgumentNullException">buffer is null.</exception>
-        ///<exception cref="ArgumentException">The sum of offset and count is greater than the buffer length.</exception>
-        ///<exception cref="ArgumentOutOfRangeException">offset or count is negative.</exception>
-        public override void Write(byte[] buffer, int offset, int count)
-        {
-            if (buffer == null)
-                throw new ArgumentNullException("buffer");
-            if (offset + count > buffer.Length)
-                throw new ArgumentException("The sum of offset and count is greater than the buffer length.");
-            if (offset < 0 || count < 0)
-                throw new ArgumentOutOfRangeException("offset", "offset or count is negative.");
-            if (_isDisposed)
-                throw CreateObjectDisposedException();
-            if (count == 0)
-                return;
-
-            lock (_buffer)
-            {
-                // wait until the buffer isn't full
-                while (Length >= _maxBufferLength)
-                    Monitor.Wait(_buffer);
-
-                _isFlushed = false; // if it were flushed before, it soon will not be.
-
-                // queue up the buffer data
-                for (int i = offset; i < offset + count; i++)
-                {
-                    _buffer.Enqueue(buffer[i]);
-                }
-
-                Monitor.Pulse(_buffer); // signal that write has occurred
-            }
-        }
-
-        /// <summary>
-        /// Releases the unmanaged resources used by the Stream and optionally releases the managed resources.
-        /// </summary>
-        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
-        protected override void Dispose(bool disposing)
-        {
-            base.Dispose(disposing);
-
-            _isDisposed = true;
-        }
-
-        ///<summary>
-        ///When overridden in a derived class, gets a value indicating whether the current stream supports reading.
-        ///</summary>
-        ///<returns>
-        ///true if the stream supports reading; otherwise, false.
-        ///</returns>
-        public override bool CanRead
-        {
-            get { return !_isDisposed; }
-        }
-
-        /// <summary>
-        /// When overridden in a derived class, gets a value indicating whether the current stream supports seeking.
-        /// </summary>
-        /// <returns>
-        /// <c>true</c> if the stream supports seeking; otherwise, <c>false</c>.
-        ///</returns>
-        public override bool CanSeek
-        {
-            get { return false; }
-        }
-
-        /// <summary>
-        /// When overridden in a derived class, gets a value indicating whether the current stream supports writing.
-        /// </summary>
-        /// <returns>
-        /// <c>true</c> if the stream supports writing; otherwise, <c>false</c>.
-        /// </returns>
-        public override bool CanWrite
-        {
-            get { return !_isDisposed; }
-        }
-
-        /// <summary>
-        /// When overridden in a derived class, gets the length in bytes of the stream.
-        /// </summary>
-        /// <returns>
-        /// A long value representing the length of the stream in bytes.
-        /// </returns>
-        /// <exception cref="NotSupportedException">A class derived from Stream does not support seeking.</exception>
-        /// <exception cref="ObjectDisposedException">Methods were called after the stream was closed.</exception>
-        public override long Length
-        {
-            get
-            {
-                if (_isDisposed)
-                    throw CreateObjectDisposedException();
-
-                return _buffer.Count;
-            }
-        }
-
-        /// <summary>
-        /// When overridden in a derived class, gets or sets the position within the current stream.
-        /// </summary>
-        /// <returns>
-        /// The current position within the stream.
-        /// </returns>
-        /// <exception cref="NotSupportedException">The stream does not support seeking.</exception>
-        public override long Position
-        {
-            get { return 0; }
-            set { throw new NotSupportedException(); }
-        }
-
-        #endregion
-
-        private ObjectDisposedException CreateObjectDisposedException()
-        {
-            return new ObjectDisposedException(GetType().FullName);
-        }
-    }
-}
+namespace Renci.SshNet.Common
+{
+    using System;
+    using System.Collections.Generic;
+    using System.IO;
+    using System.Threading;
+    using System.Globalization;
+
+    /// <summary>
+    /// PipeStream is a thread-safe read/write data stream for use between two threads in a 
+    /// single-producer/single-consumer type problem.
+    /// </summary>
+    /// <version>2006/10/13 1.0</version>
+    /// <remarks>Update on 2008/10/9 1.1 - uses Monitor instead of Manual Reset events for more elegant synchronicity.</remarks>
+    /// <license>
+    ///	Copyright (c) 2006 James Kolpack (james dot kolpack at google mail)
+    ///	
+    ///	Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 
+    ///	associated documentation files (the "Software"), to deal in the Software without restriction, 
+    ///	including without limitation the rights to use, copy, modify, merge, publish, distribute, 
+    ///	sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
+    ///	furnished to do so, subject to the following conditions:
+    ///	
+    ///	The above copyright notice and this permission notice shall be included in all copies or 
+    ///	substantial portions of the Software.
+    ///	
+    ///	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
+    ///	INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
+    ///	PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
+    ///	LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 
+    ///	OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
+    ///	OTHER DEALINGS IN THE SOFTWARE.
+    /// </license>
+    public class PipeStream : Stream
+    {
+        #region Private members
+
+        /// <summary>
+        /// Queue of bytes provides the datastructure for transmitting from an
+        /// input stream to an output stream.
+        /// </summary>
+        /// <remarks>Possible more effecient ways to accomplish this.</remarks>
+        private readonly Queue<byte> _buffer = new Queue<byte>();
+
+        /// <summary>
+        /// Indicates that the input stream has been flushed and that
+        /// all remaining data should be written to the output stream.
+        /// </summary>
+        private bool _isFlushed;
+
+        /// <summary>
+        /// Maximum number of bytes to store in the buffer.
+        /// </summary>
+        private long _maxBufferLength = 200 * 1024 * 1024;
+
+        /// <summary>
+        /// Setting this to true will cause Read() to block if it appears
+        /// that it will run out of data.
+        /// </summary>
+        private bool _canBlockLastRead;
+
+        /// <summary>
+        /// Indicates whether the current <see cref="PipeStream"/> is disposed.
+        /// </summary>
+        private bool _isDisposed;
+
+        #endregion
+
+        #region Public properties
+
+        /// <summary>
+        /// Gets or sets the maximum number of bytes to store in the buffer.
+        /// </summary>
+        /// <value>The length of the max buffer.</value>
+        public long MaxBufferLength
+        {
+            get { return _maxBufferLength; }
+            set { _maxBufferLength = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether to block last read method before the buffer is empty.
+        /// When true, Read() will block until it can fill the passed in buffer and count.
+        /// When false, Read() will not block, returning all the available buffer data.
+        /// </summary>
+        /// <remarks>
+        /// Setting to true will remove the possibility of ending a stream reader prematurely.
+        /// </remarks>
+        /// <value>
+        /// 	<c>true</c> if block last read method before the buffer is empty; otherwise, <c>false</c>.
+        /// </value>
+        /// <exception cref="ObjectDisposedException">Methods were called after the stream was closed.</exception>
+        public bool BlockLastReadBuffer
+        {
+            get
+            {
+                if (_isDisposed)
+                    throw CreateObjectDisposedException();
+
+                return _canBlockLastRead;
+            }
+            set
+            {
+                if (_isDisposed)
+                    throw CreateObjectDisposedException();
+
+                _canBlockLastRead = value;
+
+                // when turning off the block last read, signal Read() that it may now read the rest of the buffer.
+                if (!_canBlockLastRead)
+                    lock (_buffer)
+                        Monitor.Pulse(_buffer);
+            }
+        }
+
+        #endregion
+
+        #region Stream overide methods
+
+        /// <summary>
+        /// When overridden in a derived class, clears all buffers for this stream and causes any buffered data to be written to the underlying device.
+        /// </summary>
+        /// <exception cref="IOException">An I/O error occurs.</exception>
+        /// <exception cref="ObjectDisposedException">Methods were called after the stream was closed.</exception>
+        public override void Flush()
+        {
+            if (_isDisposed)
+                throw CreateObjectDisposedException();
+
+            _isFlushed = true;
+            lock (_buffer)
+                Monitor.Pulse(_buffer);
+        }
+
+        /// <summary>
+        /// When overridden in a derived class, sets the position within the current stream.
+        /// </summary>
+        /// <returns>
+        /// The new position within the current stream.
+        /// </returns>
+        /// <param name="offset">A byte offset relative to the origin parameter.</param>
+        /// <param name="origin">A value of type <see cref="SeekOrigin"/> indicating the reference point used to obtain the new position.</param>
+        /// <exception cref="NotSupportedException">The stream does not support seeking, such as if the stream is constructed from a pipe or console output.</exception>
+        public override long Seek(long offset, SeekOrigin origin)
+        {
+            throw new NotSupportedException();
+        }
+
+        /// <summary>
+        /// When overridden in a derived class, sets the length of the current stream.
+        /// </summary>
+        /// <param name="value">The desired length of the current stream in bytes.</param>
+        /// <exception cref="NotSupportedException">The stream does not support both writing and seeking, such as if the stream is constructed from a pipe or console output.</exception>
+        public override void SetLength(long value)
+        {
+            throw new NotSupportedException();
+        }
+
+        ///<summary>
+        ///When overridden in a derived class, reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read.
+        ///</summary>
+        ///<returns>
+        ///The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero if the end of the stream has been reached.
+        ///</returns>
+        ///<param name="offset">The zero-based byte offset in buffer at which to begin storing the data read from the current stream.</param>
+        ///<param name="count">The maximum number of bytes to be read from the current stream.</param>
+        ///<param name="buffer">An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and (offset + count - 1) replaced by the bytes read from the current source.</param>
+        ///<exception cref="ArgumentException">The sum of offset and count is larger than the buffer length.</exception>
+        ///<exception cref="ObjectDisposedException">Methods were called after the stream was closed.</exception>
+        ///<exception cref="NotSupportedException">The stream does not support reading.</exception>
+        ///<exception cref="ArgumentNullException">buffer is null.</exception>
+        ///<exception cref="IOException">An I/O error occurs.</exception>
+        ///<exception cref="ArgumentOutOfRangeException">offset or count is negative.</exception>
+        public override int Read(byte[] buffer, int offset, int count)
+        {
+            if (offset != 0)
+                throw new NotSupportedException("Offsets with value of non-zero are not supported");
+            if (buffer == null)
+                throw new ArgumentNullException("buffer");
+            if (offset + count > buffer.Length)
+                throw new ArgumentException("The sum of offset and count is greater than the buffer length.");
+            if (offset < 0 || count < 0)
+                throw new ArgumentOutOfRangeException("offset", "offset or count is negative.");
+            if (BlockLastReadBuffer && count >= _maxBufferLength)
+                throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, "count({0}) > mMaxBufferLength({1})", count, _maxBufferLength));
+            if (_isDisposed)
+                throw CreateObjectDisposedException();
+            if (count == 0)
+                return 0;
+
+            int readLength = 0;
+
+            lock (_buffer)
+            {
+                while (!ReadAvailable(count))
+                    Monitor.Wait(_buffer);
+
+                // fill the read buffer
+                for (; readLength < count && Length > 0 && _buffer.Count > 0; readLength++)
+                {
+                    buffer[readLength] = _buffer.Dequeue();
+                }
+
+                Monitor.Pulse(_buffer);
+            }
+            return readLength;
+        }
+
+        /// <summary>
+        /// Returns true if there are
+        /// </summary>
+        /// <param name="count">The count.</param>
+        /// <returns><c>True</c> if data available; otherwise<c>false</c>.</returns>
+        private bool ReadAvailable(int count)
+        {
+            return (Length >= count || _isFlushed) &&
+                   (Length >= (count + 1) || !BlockLastReadBuffer);
+        }
+
+        ///<summary>
+        ///When overridden in a derived class, writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written.
+        ///</summary>
+        ///<param name="offset">The zero-based byte offset in buffer at which to begin copying bytes to the current stream.</param>
+        ///<param name="count">The number of bytes to be written to the current stream.</param>
+        ///<param name="buffer">An array of bytes. This method copies count bytes from buffer to the current stream.</param>
+        ///<exception cref="IOException">An I/O error occurs.</exception>
+        ///<exception cref="NotSupportedException">The stream does not support writing.</exception>
+        ///<exception cref="ObjectDisposedException">Methods were called after the stream was closed.</exception>
+        ///<exception cref="ArgumentNullException">buffer is null.</exception>
+        ///<exception cref="ArgumentException">The sum of offset and count is greater than the buffer length.</exception>
+        ///<exception cref="ArgumentOutOfRangeException">offset or count is negative.</exception>
+        public override void Write(byte[] buffer, int offset, int count)
+        {
+            if (buffer == null)
+                throw new ArgumentNullException("buffer");
+            if (offset + count > buffer.Length)
+                throw new ArgumentException("The sum of offset and count is greater than the buffer length.");
+            if (offset < 0 || count < 0)
+                throw new ArgumentOutOfRangeException("offset", "offset or count is negative.");
+            if (_isDisposed)
+                throw CreateObjectDisposedException();
+            if (count == 0)
+                return;
+
+            lock (_buffer)
+            {
+                // wait until the buffer isn't full
+                while (Length >= _maxBufferLength)
+                    Monitor.Wait(_buffer);
+
+                _isFlushed = false; // if it were flushed before, it soon will not be.
+
+                // queue up the buffer data
+                for (int i = offset; i < offset + count; i++)
+                {
+                    _buffer.Enqueue(buffer[i]);
+                }
+
+                Monitor.Pulse(_buffer); // signal that write has occurred
+            }
+        }
+
+        /// <summary>
+        /// Releases the unmanaged resources used by the Stream and optionally releases the managed resources.
+        /// </summary>
+        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+
+            _isDisposed = true;
+        }
+
+        ///<summary>
+        ///When overridden in a derived class, gets a value indicating whether the current stream supports reading.
+        ///</summary>
+        ///<returns>
+        ///true if the stream supports reading; otherwise, false.
+        ///</returns>
+        public override bool CanRead
+        {
+            get { return !_isDisposed; }
+        }
+
+        /// <summary>
+        /// When overridden in a derived class, gets a value indicating whether the current stream supports seeking.
+        /// </summary>
+        /// <returns>
+        /// <c>true</c> if the stream supports seeking; otherwise, <c>false</c>.
+        ///</returns>
+        public override bool CanSeek
+        {
+            get { return false; }
+        }
+
+        /// <summary>
+        /// When overridden in a derived class, gets a value indicating whether the current stream supports writing.
+        /// </summary>
+        /// <returns>
+        /// <c>true</c> if the stream supports writing; otherwise, <c>false</c>.
+        /// </returns>
+        public override bool CanWrite
+        {
+            get { return !_isDisposed; }
+        }
+
+        /// <summary>
+        /// When overridden in a derived class, gets the length in bytes of the stream.
+        /// </summary>
+        /// <returns>
+        /// A long value representing the length of the stream in bytes.
+        /// </returns>
+        /// <exception cref="NotSupportedException">A class derived from Stream does not support seeking.</exception>
+        /// <exception cref="ObjectDisposedException">Methods were called after the stream was closed.</exception>
+        public override long Length
+        {
+            get
+            {
+                if (_isDisposed)
+                    throw CreateObjectDisposedException();
+
+                return _buffer.Count;
+            }
+        }
+
+        /// <summary>
+        /// When overridden in a derived class, gets or sets the position within the current stream.
+        /// </summary>
+        /// <returns>
+        /// The current position within the stream.
+        /// </returns>
+        /// <exception cref="NotSupportedException">The stream does not support seeking.</exception>
+        public override long Position
+        {
+            get { return 0; }
+            set { throw new NotSupportedException(); }
+        }
+
+        #endregion
+
+        private ObjectDisposedException CreateObjectDisposedException()
+        {
+            return new ObjectDisposedException(GetType().FullName);
+        }
+    }
+}

+ 37 - 37
src/Renci.SshNet/Common/PortForwardEventArgs.cs

@@ -1,37 +1,37 @@
-using System;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Provides data for <see cref="Renci.SshNet.ForwardedPort.RequestReceived"/> event.
-    /// </summary>
-    public class PortForwardEventArgs : EventArgs
-    {
-        /// <summary>
-        /// Gets request originator host.
-        /// </summary>
-        public string OriginatorHost { get; private set; }
-
-        /// <summary>
-        /// Gets request originator port.
-        /// </summary>
-        public uint OriginatorPort { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="PortForwardEventArgs"/> class.
-        /// </summary>
-        /// <param name="host">The host.</param>
-        /// <param name="port">The port.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="host"/> is <c>null</c>.</exception>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="port" /> is not within <see cref="F:System.Net.IPEndPoint.MinPort" /> and <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
-        internal PortForwardEventArgs(string host, uint port)
-        {
-            if (host == null)
-                throw new ArgumentNullException("host");
-            port.ValidatePort("port");
-
-            OriginatorHost = host;
-            OriginatorPort = port;
-        }
-    }
-}
+using System;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Provides data for <see cref="Renci.SshNet.ForwardedPort.RequestReceived"/> event.
+    /// </summary>
+    public class PortForwardEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Gets request originator host.
+        /// </summary>
+        public string OriginatorHost { get; private set; }
+
+        /// <summary>
+        /// Gets request originator port.
+        /// </summary>
+        public uint OriginatorPort { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="PortForwardEventArgs"/> class.
+        /// </summary>
+        /// <param name="host">The host.</param>
+        /// <param name="port">The port.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="host"/> is <c>null</c>.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="port" /> is not within <see cref="F:System.Net.IPEndPoint.MinPort" /> and <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
+        internal PortForwardEventArgs(string host, uint port)
+        {
+            if (host == null)
+                throw new ArgumentNullException("host");
+            port.ValidatePort("port");
+
+            OriginatorHost = host;
+            OriginatorPort = port;
+        }
+    }
+}

+ 22 - 22
src/Renci.SshNet/Common/ProxyException.NET40.cs

@@ -1,22 +1,22 @@
-using System;
-using System.Runtime.Serialization;
-
-namespace Renci.SshNet.Common
-{
-    [Serializable]
-    public partial class ProxyException
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ProxyException"/> class.
-        /// </summary>
-        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
-        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
-        /// <exception cref="ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
-        /// <exception cref="SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
-        protected ProxyException(SerializationInfo info, StreamingContext context)
-            : base(info, context)
-        {
-        }
-    }
-
-}
+using System;
+using System.Runtime.Serialization;
+
+namespace Renci.SshNet.Common
+{
+    [Serializable]
+    public partial class ProxyException
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ProxyException"/> class.
+        /// </summary>
+        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+        /// <exception cref="ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
+        /// <exception cref="SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
+        protected ProxyException(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+        }
+    }
+
+}

+ 37 - 37
src/Renci.SshNet/Common/ProxyException.cs

@@ -1,37 +1,37 @@
-using System;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// The exception that is thrown when SCP error occurred.
-    /// </summary>
-    public partial class ProxyException : SshException
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ScpException"/> class.
-        /// </summary>
-        public ProxyException()
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ScpException"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        public ProxyException(string message)
-            : base(message)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ScpException"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <param name="innerException">The inner exception.</param>
-        public ProxyException(string message, Exception innerException) :
-            base(message, innerException)
-        {
-        }
-    }
-
-}
+using System;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// The exception that is thrown when SCP error occurred.
+    /// </summary>
+    public partial class ProxyException : SshException
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ScpException"/> class.
+        /// </summary>
+        public ProxyException()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ScpException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        public ProxyException(string message)
+            : base(message)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ScpException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        /// <param name="innerException">The inner exception.</param>
+        public ProxyException(string message, Exception innerException) :
+            base(message, innerException)
+        {
+        }
+    }
+
+}

+ 38 - 38
src/Renci.SshNet/Common/ScpDownloadEventArgs.cs

@@ -1,38 +1,38 @@
-using System;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Provides data for the Downloading event.
-    /// </summary>
-    public class ScpDownloadEventArgs : EventArgs
-    {
-        /// <summary>
-        /// Gets the downloaded filename.
-        /// </summary>
-        public string Filename { get; private set; }
-
-        /// <summary>
-        /// Gets the downloaded file size.
-        /// </summary>
-        public long Size { get; private set; }
-
-        /// <summary>
-        /// Gets number of downloaded bytes so far.
-        /// </summary>
-        public long Downloaded { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ScpDownloadEventArgs"/> class.
-        /// </summary>
-        /// <param name="filename">The downloaded filename.</param>
-        /// <param name="size">The downloaded file size.</param>
-        /// <param name="downloaded">The number of downloaded bytes so far.</param>
-        public ScpDownloadEventArgs(string filename, long size, long downloaded)
-        {
-            Filename = filename;
-            Size = size;
-            Downloaded = downloaded;
-        }
-    }
-}
+using System;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Provides data for the Downloading event.
+    /// </summary>
+    public class ScpDownloadEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Gets the downloaded filename.
+        /// </summary>
+        public string Filename { get; private set; }
+
+        /// <summary>
+        /// Gets the downloaded file size.
+        /// </summary>
+        public long Size { get; private set; }
+
+        /// <summary>
+        /// Gets number of downloaded bytes so far.
+        /// </summary>
+        public long Downloaded { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ScpDownloadEventArgs"/> class.
+        /// </summary>
+        /// <param name="filename">The downloaded filename.</param>
+        /// <param name="size">The downloaded file size.</param>
+        /// <param name="downloaded">The number of downloaded bytes so far.</param>
+        public ScpDownloadEventArgs(string filename, long size, long downloaded)
+        {
+            Filename = filename;
+            Size = size;
+            Downloaded = downloaded;
+        }
+    }
+}

+ 21 - 21
src/Renci.SshNet/Common/ScpException.NET40.cs

@@ -1,21 +1,21 @@
-using System;
-using System.Runtime.Serialization;
-
-namespace Renci.SshNet.Common
-{
-    [Serializable]
-    public partial class ScpException
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ScpException"/> class.
-        /// </summary>
-        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
-        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
-        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
-        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
-        protected ScpException(SerializationInfo info, StreamingContext context)
-            : base(info, context)
-        {
-        }
-    }
-}
+using System;
+using System.Runtime.Serialization;
+
+namespace Renci.SshNet.Common
+{
+    [Serializable]
+    public partial class ScpException
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ScpException"/> class.
+        /// </summary>
+        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
+        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
+        protected ScpException(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+        }
+    }
+}

+ 38 - 38
src/Renci.SshNet/Common/ScpException.cs

@@ -1,38 +1,38 @@
-using System;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// The exception that is thrown when SCP error occurred.
-    /// </summary>
-    public partial class ScpException : SshException
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ScpException"/> class.
-        /// </summary>
-        public ScpException()
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ScpException"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        public ScpException(string message)
-            : base(message)
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ScpException"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <param name="innerException">The inner exception.</param>
-        public ScpException(string message, Exception innerException) :
-            base(message, innerException)
-        {
-        }
-    }
-}
+using System;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// The exception that is thrown when SCP error occurred.
+    /// </summary>
+    public partial class ScpException : SshException
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ScpException"/> class.
+        /// </summary>
+        public ScpException()
+        {
+
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ScpException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        public ScpException(string message)
+            : base(message)
+        {
+
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ScpException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        /// <param name="innerException">The inner exception.</param>
+        public ScpException(string message, Exception innerException) :
+            base(message, innerException)
+        {
+        }
+    }
+}

+ 38 - 38
src/Renci.SshNet/Common/ScpUploadEventArgs.cs

@@ -1,38 +1,38 @@
-using System;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Provides data for the Uploading event.
-    /// </summary>
-    public class ScpUploadEventArgs : EventArgs
-    {
-        /// <summary>
-        /// Gets the uploaded filename.
-        /// </summary>
-        public string Filename { get; private set; }
-
-        /// <summary>
-        /// Gets the uploaded file size.
-        /// </summary>
-        public long Size { get; private set; }
-
-        /// <summary>
-        /// Gets number of uploaded bytes so far.
-        /// </summary>
-        public long Uploaded { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ScpUploadEventArgs"/> class.
-        /// </summary>
-        /// <param name="filename">The uploaded filename.</param>
-        /// <param name="size">The uploaded file size.</param>
-        /// <param name="uploaded">The number of uploaded bytes so far.</param>
-        public ScpUploadEventArgs(string filename, long size, long uploaded)
-        {
-            Filename = filename;
-            Size = size;
-            Uploaded = uploaded;
-        }
-    }
-}
+using System;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Provides data for the Uploading event.
+    /// </summary>
+    public class ScpUploadEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Gets the uploaded filename.
+        /// </summary>
+        public string Filename { get; private set; }
+
+        /// <summary>
+        /// Gets the uploaded file size.
+        /// </summary>
+        public long Size { get; private set; }
+
+        /// <summary>
+        /// Gets number of uploaded bytes so far.
+        /// </summary>
+        public long Uploaded { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ScpUploadEventArgs"/> class.
+        /// </summary>
+        /// <param name="filename">The uploaded filename.</param>
+        /// <param name="size">The uploaded file size.</param>
+        /// <param name="uploaded">The number of uploaded bytes so far.</param>
+        public ScpUploadEventArgs(string filename, long size, long uploaded)
+        {
+            Filename = filename;
+            Size = size;
+            Uploaded = uploaded;
+        }
+    }
+}

+ 81 - 81
src/Renci.SshNet/Common/SemaphoreLight.cs

@@ -1,81 +1,81 @@
-using System;
-using System.Threading;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Light implementation of SemaphoreSlim.
-    /// </summary>
-    public class SemaphoreLight
-    {
-        private readonly object _lock = new object();
-
-        private int _currentCount;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SemaphoreLight"/> class, specifying 
-        /// the initial number of requests that can be granted concurrently.
-        /// </summary>
-        /// <param name="initialCount">The initial number of requests for the semaphore that can be granted concurrently.</param>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="initialCount"/> is a negative number.</exception>
-        public SemaphoreLight(int initialCount)
-        {
-            if (initialCount < 0 )
-                throw new ArgumentOutOfRangeException("initialCount", "The value cannot be negative.");
-
-            _currentCount = initialCount;
-        }
-
-        /// <summary>
-        /// Gets the current count of the <see cref="SemaphoreLight"/>.
-        /// </summary>
-        public int CurrentCount { get { return _currentCount; } }
-
-        /// <summary>
-        /// Exits the <see cref="SemaphoreLight"/> once.
-        /// </summary>
-        /// <returns>The previous count of the <see cref="SemaphoreLight"/>.</returns>
-        public int Release()
-        {
-            return Release(1);
-        }
-
-        /// <summary>
-        /// Exits the <see cref="SemaphoreLight"/> a specified number of times.
-        /// </summary>
-        /// <param name="releaseCount">The number of times to exit the semaphore.</param>
-        /// <returns>The previous count of the <see cref="SemaphoreLight"/>.</returns>
-        public int Release(int releaseCount)
-        {
-            var oldCount = _currentCount;
-
-            lock (_lock)
-            {
-                _currentCount += releaseCount;
-
-                Monitor.Pulse(_lock);
-            }
-
-            return oldCount;
-        }
-
-        /// <summary>
-        /// Blocks the current thread until it can enter the <see cref="SemaphoreLight"/>.
-        /// </summary>
-        public void Wait()
-        {
-
-            lock (_lock)
-            {
-                while (_currentCount < 1)
-                {
-                    Monitor.Wait(_lock);
-                }
-
-                _currentCount--;
-
-                Monitor.Pulse(_lock);
-            }
-        }
-    }
-}
+using System;
+using System.Threading;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Light implementation of SemaphoreSlim.
+    /// </summary>
+    public class SemaphoreLight
+    {
+        private readonly object _lock = new object();
+
+        private int _currentCount;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SemaphoreLight"/> class, specifying 
+        /// the initial number of requests that can be granted concurrently.
+        /// </summary>
+        /// <param name="initialCount">The initial number of requests for the semaphore that can be granted concurrently.</param>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="initialCount"/> is a negative number.</exception>
+        public SemaphoreLight(int initialCount)
+        {
+            if (initialCount < 0 )
+                throw new ArgumentOutOfRangeException("initialCount", "The value cannot be negative.");
+
+            _currentCount = initialCount;
+        }
+
+        /// <summary>
+        /// Gets the current count of the <see cref="SemaphoreLight"/>.
+        /// </summary>
+        public int CurrentCount { get { return _currentCount; } }
+
+        /// <summary>
+        /// Exits the <see cref="SemaphoreLight"/> once.
+        /// </summary>
+        /// <returns>The previous count of the <see cref="SemaphoreLight"/>.</returns>
+        public int Release()
+        {
+            return Release(1);
+        }
+
+        /// <summary>
+        /// Exits the <see cref="SemaphoreLight"/> a specified number of times.
+        /// </summary>
+        /// <param name="releaseCount">The number of times to exit the semaphore.</param>
+        /// <returns>The previous count of the <see cref="SemaphoreLight"/>.</returns>
+        public int Release(int releaseCount)
+        {
+            var oldCount = _currentCount;
+
+            lock (_lock)
+            {
+                _currentCount += releaseCount;
+
+                Monitor.Pulse(_lock);
+            }
+
+            return oldCount;
+        }
+
+        /// <summary>
+        /// Blocks the current thread until it can enter the <see cref="SemaphoreLight"/>.
+        /// </summary>
+        public void Wait()
+        {
+
+            lock (_lock)
+            {
+                while (_currentCount < 1)
+                {
+                    Monitor.Wait(_lock);
+                }
+
+                _currentCount--;
+
+                Monitor.Pulse(_lock);
+            }
+        }
+    }
+}

+ 24 - 24
src/Renci.SshNet/Common/SftpPathNotFoundException.NET40.cs

@@ -1,24 +1,24 @@
-using System;
-using System.Runtime.Serialization;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// The exception that is thrown when file or directory is not found.
-    /// </summary>
-    [Serializable]
-    public partial class SftpPathNotFoundException
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SftpPathNotFoundException"/> class.
-        /// </summary>
-        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
-        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
-        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
-        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
-        protected SftpPathNotFoundException(SerializationInfo info, StreamingContext context)
-            : base(info, context)
-        {
-        }
-    }
-}
+using System;
+using System.Runtime.Serialization;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// The exception that is thrown when file or directory is not found.
+    /// </summary>
+    [Serializable]
+    public partial class SftpPathNotFoundException
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SftpPathNotFoundException"/> class.
+        /// </summary>
+        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
+        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
+        protected SftpPathNotFoundException(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+        }
+    }
+}

+ 36 - 36
src/Renci.SshNet/Common/SftpPathNotFoundException.cs

@@ -1,36 +1,36 @@
-using System;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// The exception that is thrown when file or directory is not found.
-    /// </summary>
-    public partial class SftpPathNotFoundException : SshException
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SftpPathNotFoundException"/> class.
-        /// </summary>
-        public SftpPathNotFoundException()
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SftpPathNotFoundException"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        public SftpPathNotFoundException(string message)
-            : base(message)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SftpPathNotFoundException"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <param name="innerException">The inner exception.</param>
-        public SftpPathNotFoundException(string message, Exception innerException) :
-            base(message, innerException)
-        {
-        }
-    }
-}
+using System;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// The exception that is thrown when file or directory is not found.
+    /// </summary>
+    public partial class SftpPathNotFoundException : SshException
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SftpPathNotFoundException"/> class.
+        /// </summary>
+        public SftpPathNotFoundException()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SftpPathNotFoundException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        public SftpPathNotFoundException(string message)
+            : base(message)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SftpPathNotFoundException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        /// <param name="innerException">The inner exception.</param>
+        public SftpPathNotFoundException(string message, Exception innerException) :
+            base(message, innerException)
+        {
+        }
+    }
+}

+ 24 - 24
src/Renci.SshNet/Common/SftpPermissionDeniedException.NET40.cs

@@ -1,24 +1,24 @@
-using System;
-using System.Runtime.Serialization;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// The exception that is thrown when operation permission is denied.
-    /// </summary>
-    [Serializable]
-    public partial class SftpPermissionDeniedException
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SftpPermissionDeniedException"/> class.
-        /// </summary>
-        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
-        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
-        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
-        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
-        protected SftpPermissionDeniedException(SerializationInfo info, StreamingContext context)
-            : base(info, context)
-        {
-        }
-    }
-}
+using System;
+using System.Runtime.Serialization;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// The exception that is thrown when operation permission is denied.
+    /// </summary>
+    [Serializable]
+    public partial class SftpPermissionDeniedException
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SftpPermissionDeniedException"/> class.
+        /// </summary>
+        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
+        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
+        protected SftpPermissionDeniedException(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+        }
+    }
+}

+ 36 - 36
src/Renci.SshNet/Common/SftpPermissionDeniedException.cs

@@ -1,36 +1,36 @@
-using System;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// The exception that is thrown when operation permission is denied.
-    /// </summary>
-    public partial class SftpPermissionDeniedException : SshException
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SftpPermissionDeniedException"/> class.
-        /// </summary>
-        public SftpPermissionDeniedException()
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SftpPermissionDeniedException"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        public SftpPermissionDeniedException(string message)
-            : base(message)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SftpPermissionDeniedException"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <param name="innerException">The inner exception.</param>
-        public SftpPermissionDeniedException(string message, Exception innerException) :
-            base(message, innerException)
-        {
-        }
-    }
-}
+using System;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// The exception that is thrown when operation permission is denied.
+    /// </summary>
+    public partial class SftpPermissionDeniedException : SshException
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SftpPermissionDeniedException"/> class.
+        /// </summary>
+        public SftpPermissionDeniedException()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SftpPermissionDeniedException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        public SftpPermissionDeniedException(string message)
+            : base(message)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SftpPermissionDeniedException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        /// <param name="innerException">The inner exception.</param>
+        public SftpPermissionDeniedException(string message, Exception innerException) :
+            base(message, innerException)
+        {
+        }
+    }
+}

+ 38 - 38
src/Renci.SshNet/Common/ShellDataEventArgs.cs

@@ -1,38 +1,38 @@
-using System;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Provides data for Shell DataReceived event
-    /// </summary>
-    public class ShellDataEventArgs : EventArgs
-    {
-        /// <summary>
-        /// Gets the data.
-        /// </summary>
-        public byte[] Data { get; private set; }
-
-        /// <summary>
-        /// Gets the line data.
-        /// </summary>
-        public string Line { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ShellDataEventArgs"/> class.
-        /// </summary>
-        /// <param name="data">The data.</param>
-        public ShellDataEventArgs(byte[] data)
-        {
-            Data = data;
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ShellDataEventArgs"/> class.
-        /// </summary>
-        /// <param name="line">The line.</param>
-        public ShellDataEventArgs(string line)
-        {
-            Line = line;
-        }
-    }
-}
+using System;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Provides data for Shell DataReceived event
+    /// </summary>
+    public class ShellDataEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Gets the data.
+        /// </summary>
+        public byte[] Data { get; private set; }
+
+        /// <summary>
+        /// Gets the line data.
+        /// </summary>
+        public string Line { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ShellDataEventArgs"/> class.
+        /// </summary>
+        /// <param name="data">The data.</param>
+        public ShellDataEventArgs(byte[] data)
+        {
+            Data = data;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ShellDataEventArgs"/> class.
+        /// </summary>
+        /// <param name="line">The line.</param>
+        public ShellDataEventArgs(string line)
+        {
+            Line = line;
+        }
+    }
+}

+ 24 - 24
src/Renci.SshNet/Common/SshAuthenticationException.NET40.cs

@@ -1,24 +1,24 @@
-using System;
-using System.Runtime.Serialization;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// The exception that is thrown when authentication failed.
-    /// </summary>
-    [Serializable]
-    public partial class SshAuthenticationException
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshAuthenticationException"/> class.
-        /// </summary>
-        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
-        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
-        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
-        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
-        protected SshAuthenticationException(SerializationInfo info, StreamingContext context)
-            : base(info, context)
-        {
-        }
-    }
-}
+using System;
+using System.Runtime.Serialization;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// The exception that is thrown when authentication failed.
+    /// </summary>
+    [Serializable]
+    public partial class SshAuthenticationException
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshAuthenticationException"/> class.
+        /// </summary>
+        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
+        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
+        protected SshAuthenticationException(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+        }
+    }
+}

+ 38 - 38
src/Renci.SshNet/Common/SshAuthenticationException.cs

@@ -1,38 +1,38 @@
-using System;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// The exception that is thrown when authentication failed.
-    /// </summary>
-    public partial class SshAuthenticationException : SshException
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshAuthenticationException"/> class.
-        /// </summary>
-        public SshAuthenticationException()
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshAuthenticationException"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        public SshAuthenticationException(string message)
-            : base(message)
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshAuthenticationException"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <param name="innerException">The inner exception.</param>
-        public SshAuthenticationException(string message, Exception innerException) :
-            base(message, innerException)
-        {
-        }
-    }
-}
+using System;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// The exception that is thrown when authentication failed.
+    /// </summary>
+    public partial class SshAuthenticationException : SshException
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshAuthenticationException"/> class.
+        /// </summary>
+        public SshAuthenticationException()
+        {
+
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshAuthenticationException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        public SshAuthenticationException(string message)
+            : base(message)
+        {
+
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshAuthenticationException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        /// <param name="innerException">The inner exception.</param>
+        public SshAuthenticationException(string message, Exception innerException) :
+            base(message, innerException)
+        {
+        }
+    }
+}

+ 24 - 24
src/Renci.SshNet/Common/SshConnectionException.NET40.cs

@@ -1,24 +1,24 @@
-using System;
-using System.Runtime.Serialization;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// The exception that is thrown when connection was terminated.
-    /// </summary>
-    [Serializable]
-    public partial class SshConnectionException
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshConnectionException"/> class.
-        /// </summary>
-        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
-        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
-        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
-        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
-        protected SshConnectionException(SerializationInfo info, StreamingContext context)
-            : base(info, context)
-        {
-        }
-    }
-}
+using System;
+using System.Runtime.Serialization;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// The exception that is thrown when connection was terminated.
+    /// </summary>
+    [Serializable]
+    public partial class SshConnectionException
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshConnectionException"/> class.
+        /// </summary>
+        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
+        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
+        protected SshConnectionException(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+        }
+    }
+}

+ 56 - 56
src/Renci.SshNet/Common/SshConnectionException.cs

@@ -1,56 +1,56 @@
-using System;
-using Renci.SshNet.Messages.Transport;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// The exception that is thrown when connection was terminated.
-    /// </summary>
-    public partial class SshConnectionException : SshException
-    {
-        /// <summary>
-        /// Gets the disconnect reason if provided by the server or client. Otherwise None.
-        /// </summary>
-        public DisconnectReason DisconnectReason { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshConnectionException"/> class.
-        /// </summary>
-        public SshConnectionException()
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshConnectionException"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        public SshConnectionException(string message)
-            : base(message)
-        {
-            DisconnectReason = DisconnectReason.None;
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshConnectionException"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <param name="disconnectReasonCode">The disconnect reason code.</param>
-        public SshConnectionException(string message, DisconnectReason disconnectReasonCode)
-            : base(message)
-        {
-            DisconnectReason = disconnectReasonCode;
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshConnectionException"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <param name="disconnectReasonCode">The disconnect reason code.</param>
-        /// <param name="inner">The inner.</param>
-        public SshConnectionException(string message, DisconnectReason disconnectReasonCode, Exception inner)
-            : base(message, inner)
-        {
-            DisconnectReason = disconnectReasonCode;
-        }
-    }
-}
+using System;
+using Renci.SshNet.Messages.Transport;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// The exception that is thrown when connection was terminated.
+    /// </summary>
+    public partial class SshConnectionException : SshException
+    {
+        /// <summary>
+        /// Gets the disconnect reason if provided by the server or client. Otherwise None.
+        /// </summary>
+        public DisconnectReason DisconnectReason { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshConnectionException"/> class.
+        /// </summary>
+        public SshConnectionException()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshConnectionException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        public SshConnectionException(string message)
+            : base(message)
+        {
+            DisconnectReason = DisconnectReason.None;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshConnectionException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        /// <param name="disconnectReasonCode">The disconnect reason code.</param>
+        public SshConnectionException(string message, DisconnectReason disconnectReasonCode)
+            : base(message)
+        {
+            DisconnectReason = disconnectReasonCode;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshConnectionException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        /// <param name="disconnectReasonCode">The disconnect reason code.</param>
+        /// <param name="inner">The inner.</param>
+        public SshConnectionException(string message, DisconnectReason disconnectReasonCode, Exception inner)
+            : base(message, inner)
+        {
+            DisconnectReason = disconnectReasonCode;
+        }
+    }
+}

+ 443 - 443
src/Renci.SshNet/Common/SshData.cs

@@ -1,443 +1,443 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Base ssh data serialization type
-    /// </summary>
-    public abstract class SshData
-    {
-        internal const int DefaultCapacity = 64;
-
-        internal static readonly Encoding Ascii = new ASCIIEncoding();
-        internal static readonly Encoding Utf8 = Encoding.UTF8;
-
-        private SshDataStream _stream;
-
-        /// <summary>
-        /// Gets the underlying <see cref="SshDataStream"/> that is used for reading and writing SSH data.
-        /// </summary>
-        /// <value>
-        /// The underlying <see cref="SshDataStream"/> that is used for reading and writing SSH data.
-        /// </value>
-        protected SshDataStream DataStream
-        {
-            get { return _stream; }
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether all data from the buffer has been read.
-        /// </summary>
-        /// <value>
-        /// <c>true</c> if this instance is end of data; otherwise, <c>false</c>.
-        /// </value>
-        protected bool IsEndOfData
-        {
-            get
-            {
-                return _stream.Position >= _stream.Length;
-            }
-        }
-
-        private byte[] _loadedData;
-        private int _offset;
-
-        /// <summary>
-        /// Gets the index that represents zero in current data type.
-        /// </summary>
-        /// <value>
-        /// The index of the zero reader.
-        /// </value>
-        protected virtual int ZeroReaderIndex
-        {
-            get
-            {
-                return 0;
-            }
-        }
-
-        /// <summary>
-        /// Gets the size of the message in bytes.
-        /// </summary>
-        /// <value>
-        /// The size of the messages in bytes.
-        /// </value>
-        protected virtual int BufferCapacity
-        {
-            get { return 0; }
-        }
-
-        /// <summary>
-        /// Gets data bytes array
-        /// </summary>
-        /// <returns>Byte array representation of data structure.</returns>
-        public byte[] GetBytes()
-        {
-            var messageLength = BufferCapacity;
-            var capacity = messageLength != -1 ? messageLength : DefaultCapacity;
-            var dataStream = new SshDataStream(capacity);
-            WriteBytes(dataStream);
-            return dataStream.ToArray();
-        }
-
-        /// <summary>
-        /// Writes the current message to the specified <see cref="SshDataStream"/>.
-        /// </summary>
-        /// <param name="stream">The <see cref="SshDataStream"/> to write the message to.</param>
-        protected virtual void WriteBytes(SshDataStream stream)
-        {
-            _stream = stream;
-            SaveData();
-        }
-
-        internal T OfType<T>() where T : SshData, new()
-        {
-            var result = new T();
-            result.LoadBytes(_loadedData, _offset);
-            result.LoadData();
-            return result;
-        }
-
-        /// <summary>
-        /// Loads data from specified bytes.
-        /// </summary>
-        /// <param name="value">Bytes array.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="value"/> is null.</exception>
-        public void Load(byte[] value)
-        {
-            Load(value, 0);
-        }
-
-        /// <summary>
-        /// Loads data from the specified buffer.
-        /// </summary>
-        /// <param name="value">Bytes array.</param>
-        /// <param name="offset">The zero-based offset in <paramref name="value"/> at which to begin reading SSH data.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="value"/> is null.</exception>
-        public void Load(byte[] value, int offset)
-        {
-            LoadBytes(value, offset);
-            LoadData();
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be loaded.
-        /// </summary>
-        protected abstract void LoadData();
-
-        /// <summary>
-        /// Called when type specific data need to be saved.
-        /// </summary>
-        protected abstract void SaveData();
-
-        /// <summary>
-        /// Loads data bytes into internal buffer.
-        /// </summary>
-        /// <param name="bytes">The bytes.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="bytes"/> is null.</exception>
-        protected void LoadBytes(byte[] bytes)
-        {
-            LoadBytes(bytes, 0);
-        }
-
-        /// <summary>
-        /// Loads data bytes into internal buffer.
-        /// </summary>
-        /// <param name="bytes">The bytes.</param>
-        /// <param name="offset">The zero-based offset in <paramref name="bytes"/> at which to begin reading SSH data.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="bytes"/> is null.</exception>
-        protected void LoadBytes(byte[] bytes, int offset)
-        {
-            if (bytes == null)
-                throw new ArgumentNullException("bytes");
-
-            _loadedData = bytes;
-            _offset = offset;
-
-            _stream = new SshDataStream(bytes);
-            ResetReader();
-        }
-
-        /// <summary>
-        /// Resets internal data reader index.
-        /// </summary>
-        protected void ResetReader()
-        {
-            _stream.Position = ZeroReaderIndex + _offset;
-        }
-
-        /// <summary>
-        /// Reads all data left in internal buffer at current position.
-        /// </summary>
-        /// <returns>An array of bytes containing the remaining data in the internal buffer.</returns>
-        protected byte[] ReadBytes()
-        {
-            var bytesLength = (int) (_stream.Length - _stream.Position);
-            var data = new byte[bytesLength];
-            _stream.Read(data, 0, bytesLength);
-            return data;
-        }
-
-        /// <summary>
-        /// Reads next specified number of bytes data type from internal buffer.
-        /// </summary>
-        /// <param name="length">Number of bytes to read.</param>
-        /// <returns>An array of bytes that was read from the internal buffer.</returns>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="length"/> is greater than the internal buffer size.</exception>
-        protected byte[] ReadBytes(int length)
-        {
-            // Note that this also prevents allocating non-relevant lengths, such as if length is greater than _data.Count but less than int.MaxValue.
-            // For the nerds, the condition translates to: if (length > data.Count && length < int.MaxValue)
-            // Which probably would cause all sorts of exception, most notably OutOfMemoryException.
-
-            var data = new byte[length];
-            var bytesRead = _stream.Read(data, 0, length);
-
-            if (bytesRead < length)
-                throw new ArgumentOutOfRangeException("length");
-
-            return data;
-        }
-
-        /// <summary>
-        /// Reads next byte data type from internal buffer.
-        /// </summary>
-        /// <returns>Byte read.</returns>
-        protected byte ReadByte()
-        {
-            var byteRead = _stream.ReadByte();
-            if (byteRead == -1)
-                throw new InvalidOperationException("Attempt to read past the end of the SSH data stream.");
-            return (byte) byteRead;
-        }
-
-        /// <summary>
-        /// Reads next boolean data type from internal buffer.
-        /// </summary>
-        /// <returns>Boolean read.</returns>
-        protected bool ReadBoolean()
-        {
-            return ReadByte() != 0;
-        }
-
-        /// <summary>
-        /// Reads next uint16 data type from internal buffer.
-        /// </summary>
-        /// <returns>uint16 read</returns>
-        protected ushort ReadUInt16()
-        {
-            var data = ReadBytes(2);
-            return (ushort)(data[0] << 8 | data[1]);
-        }
-
-        /// <summary>
-        /// Reads next uint32 data type from internal buffer.
-        /// </summary>
-        /// <returns>uint32 read</returns>
-        protected uint ReadUInt32()
-        {
-            var data = ReadBytes(4);
-            return (uint)(data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]);
-        }
-
-        /// <summary>
-        /// Reads next uint64 data type from internal buffer.
-        /// </summary>
-        /// <returns>uint64 read</returns>
-        protected ulong ReadUInt64()
-        {
-            var data = ReadBytes(8);
-            return ((ulong)data[0] << 56 | (ulong)data[1] << 48 | (ulong)data[2] << 40 | (ulong)data[3] << 32 | (ulong)data[4] << 24 | (ulong)data[5] << 16 | (ulong)data[6] << 8 | data[7]);
-        }
-
-        /// <summary>
-        /// Reads next string data type from internal buffer using the specific encoding.
-        /// </summary>
-        /// <returns>
-        /// The <see cref="string"/> read.
-        /// </returns>
-        protected string ReadString(Encoding encoding)
-        {
-            return _stream.ReadString(encoding);
-        }
-
-        /// <summary>
-        /// Reads next data type as byte array from internal buffer.
-        /// </summary>
-        /// <returns>
-        /// The bytes read.
-        /// </returns>
-        protected byte[] ReadBinary()
-        {
-            return _stream.ReadBinary();
-        }
-
-        /// <summary>
-        /// Reads next name-list data type from internal buffer.
-        /// </summary>
-        /// <returns>
-        /// String array or read data.
-        /// </returns>
-        protected string[] ReadNamesList()
-        {
-            var namesList = ReadString(Ascii);
-            return namesList.Split(',');
-        }
-
-        /// <summary>
-        /// Reads next extension-pair data type from internal buffer.
-        /// </summary>
-        /// <returns>Extensions pair dictionary.</returns>
-        protected IDictionary<string, string> ReadExtensionPair()
-        {
-            var result = new Dictionary<string, string>();
-            while (!IsEndOfData)
-            {
-                var extensionName = ReadString(Ascii);
-                var extensionData = ReadString(Ascii);
-                result.Add(extensionName, extensionData);
-            }
-            return result;
-        }
-
-        /// <summary>
-        /// Writes bytes array data into internal buffer.
-        /// </summary>
-        /// <param name="data">Byte array data to write.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="data"/> is null.</exception>
-        protected void Write(byte[] data)
-        {
-            _stream.Write(data);
-        }
-
-        /// <summary>
-        /// Writes a sequence of bytes to the current SSH data stream and advances the current position
-        /// within this stream by the number of bytes written.
-        /// </summary>
-        /// <param name="buffer">An array of bytes. This method write <paramref name="count"/> bytes from buffer to the current SSH data stream.</param>
-        /// <param name="offset">The zero-based offset in <paramref name="buffer"/> at which to begin writing bytes to the SSH data stream.</param>
-        /// <param name="count">The number of bytes to be written to the current SSH data stream.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is null.</exception>
-        /// <exception cref="ArgumentException">The sum of <paramref name="offset"/> and <paramref name="count"/> is greater than the buffer length.</exception>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="offset"/> or <paramref name="count"/> is negative.</exception>
-        protected void Write(byte[] buffer, int offset, int count)
-        {
-            _stream.Write(buffer, offset, count);
-        }
-
-        /// <summary>
-        /// Writes <see cref="byte"/> data into internal buffer.
-        /// </summary>
-        /// <param name="data"><see cref="byte"/> data to write.</param>
-        protected void Write(byte data)
-        {
-            _stream.WriteByte(data);
-        }
-
-        /// <summary>
-        /// Writes <see cref="bool"/> into internal buffer.
-        /// </summary>
-        /// <param name="data"><see cref="bool" /> data to write.</param>
-        protected void Write(bool data)
-        {
-            Write(data ? (byte) 1 : (byte) 0);
-        }
-
-        /// <summary>
-        /// Writes <see cref="uint"/> data into internal buffer.
-        /// </summary>
-        /// <param name="data"><see cref="uint"/> data to write.</param>
-        protected void Write(uint data)
-        {
-            _stream.Write(data);
-        }
-
-        /// <summary>
-        /// Writes <see cref="ulong" /> data into internal buffer.
-        /// </summary>
-        /// <param name="data"><see cref="ulong"/> data to write.</param>
-        protected void Write(ulong data)
-        {
-            _stream.Write(data);
-        }
-
-        /// <summary>
-        /// Writes <see cref="string"/> data into internal buffer using default encoding.
-        /// </summary>
-        /// <param name="data"><see cref="string"/> data to write.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="data"/> is null.</exception>
-        protected void Write(string data)
-        {
-            Write(data, Utf8);
-        }
-
-        /// <summary>
-        /// Writes <see cref="string"/> data into internal buffer using the specified encoding.
-        /// </summary>
-        /// <param name="data"><see cref="string"/> data to write.</param>
-        /// <param name="encoding">The character encoding to use.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="data"/> is null.</exception>
-        /// <exception cref="ArgumentNullException"><paramref name="encoding"/> is null.</exception>
-        protected void Write(string data, Encoding encoding)
-        {
-            _stream.Write(data, encoding);
-        }
-
-        /// <summary>
-        /// Writes data into internal buffer.
-        /// </summary>
-        /// <param name="buffer">The data to write.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is null.</exception>
-        protected void WriteBinaryString(byte[] buffer)
-        {
-            _stream.WriteBinary(buffer);
-        }
-
-        /// <summary>
-        /// Writes data into internal buffer.
-        /// </summary>
-        /// <param name="buffer">An array of bytes. This method write <paramref name="count"/> bytes from buffer to the current SSH data stream.</param>
-        /// <param name="offset">The zero-based byte offset in <paramref name="buffer"/> at which to begin writing bytes to the SSH data stream.</param>
-        /// <param name="count">The number of bytes to be written to the current SSH data stream.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is null.</exception>
-        /// <exception cref="ArgumentException">The sum of <paramref name="offset"/> and <paramref name="count"/> is greater than the buffer length.</exception>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="offset"/> or <paramref name="count"/> is negative.</exception>
-        protected void WriteBinary(byte[] buffer, int offset, int count)
-        {
-            _stream.WriteBinary(buffer, offset, count);
-        }
-
-        /// <summary>
-        /// Writes mpint data into internal buffer.
-        /// </summary>
-        /// <param name="data">mpint data to write.</param>
-        protected void Write(BigInteger data)
-        {
-            _stream.Write(data);
-        }
-
-        /// <summary>
-        /// Writes name-list data into internal buffer.
-        /// </summary>
-        /// <param name="data">name-list data to write.</param>
-        protected void Write(string[] data)
-        {
-            Write(string.Join(",", data), Ascii);
-        }
-
-        /// <summary>
-        /// Writes extension-pair data into internal buffer.
-        /// </summary>
-        /// <param name="data">extension-pair data to write.</param>
-        protected void Write(IDictionary<string, string> data)
-        {
-            foreach (var item in data)
-            {
-                Write(item.Key, Ascii);
-                Write(item.Value, Ascii);
-            }
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Base ssh data serialization type
+    /// </summary>
+    public abstract class SshData
+    {
+        internal const int DefaultCapacity = 64;
+
+        internal static readonly Encoding Ascii = new ASCIIEncoding();
+        internal static readonly Encoding Utf8 = Encoding.UTF8;
+
+        private SshDataStream _stream;
+
+        /// <summary>
+        /// Gets the underlying <see cref="SshDataStream"/> that is used for reading and writing SSH data.
+        /// </summary>
+        /// <value>
+        /// The underlying <see cref="SshDataStream"/> that is used for reading and writing SSH data.
+        /// </value>
+        protected SshDataStream DataStream
+        {
+            get { return _stream; }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether all data from the buffer has been read.
+        /// </summary>
+        /// <value>
+        /// <c>true</c> if this instance is end of data; otherwise, <c>false</c>.
+        /// </value>
+        protected bool IsEndOfData
+        {
+            get
+            {
+                return _stream.Position >= _stream.Length;
+            }
+        }
+
+        private byte[] _loadedData;
+        private int _offset;
+
+        /// <summary>
+        /// Gets the index that represents zero in current data type.
+        /// </summary>
+        /// <value>
+        /// The index of the zero reader.
+        /// </value>
+        protected virtual int ZeroReaderIndex
+        {
+            get
+            {
+                return 0;
+            }
+        }
+
+        /// <summary>
+        /// Gets the size of the message in bytes.
+        /// </summary>
+        /// <value>
+        /// The size of the messages in bytes.
+        /// </value>
+        protected virtual int BufferCapacity
+        {
+            get { return 0; }
+        }
+
+        /// <summary>
+        /// Gets data bytes array
+        /// </summary>
+        /// <returns>Byte array representation of data structure.</returns>
+        public byte[] GetBytes()
+        {
+            var messageLength = BufferCapacity;
+            var capacity = messageLength != -1 ? messageLength : DefaultCapacity;
+            var dataStream = new SshDataStream(capacity);
+            WriteBytes(dataStream);
+            return dataStream.ToArray();
+        }
+
+        /// <summary>
+        /// Writes the current message to the specified <see cref="SshDataStream"/>.
+        /// </summary>
+        /// <param name="stream">The <see cref="SshDataStream"/> to write the message to.</param>
+        protected virtual void WriteBytes(SshDataStream stream)
+        {
+            _stream = stream;
+            SaveData();
+        }
+
+        internal T OfType<T>() where T : SshData, new()
+        {
+            var result = new T();
+            result.LoadBytes(_loadedData, _offset);
+            result.LoadData();
+            return result;
+        }
+
+        /// <summary>
+        /// Loads data from specified bytes.
+        /// </summary>
+        /// <param name="value">Bytes array.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="value"/> is null.</exception>
+        public void Load(byte[] value)
+        {
+            Load(value, 0);
+        }
+
+        /// <summary>
+        /// Loads data from the specified buffer.
+        /// </summary>
+        /// <param name="value">Bytes array.</param>
+        /// <param name="offset">The zero-based offset in <paramref name="value"/> at which to begin reading SSH data.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="value"/> is null.</exception>
+        public void Load(byte[] value, int offset)
+        {
+            LoadBytes(value, offset);
+            LoadData();
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be loaded.
+        /// </summary>
+        protected abstract void LoadData();
+
+        /// <summary>
+        /// Called when type specific data need to be saved.
+        /// </summary>
+        protected abstract void SaveData();
+
+        /// <summary>
+        /// Loads data bytes into internal buffer.
+        /// </summary>
+        /// <param name="bytes">The bytes.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="bytes"/> is null.</exception>
+        protected void LoadBytes(byte[] bytes)
+        {
+            LoadBytes(bytes, 0);
+        }
+
+        /// <summary>
+        /// Loads data bytes into internal buffer.
+        /// </summary>
+        /// <param name="bytes">The bytes.</param>
+        /// <param name="offset">The zero-based offset in <paramref name="bytes"/> at which to begin reading SSH data.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="bytes"/> is null.</exception>
+        protected void LoadBytes(byte[] bytes, int offset)
+        {
+            if (bytes == null)
+                throw new ArgumentNullException("bytes");
+
+            _loadedData = bytes;
+            _offset = offset;
+
+            _stream = new SshDataStream(bytes);
+            ResetReader();
+        }
+
+        /// <summary>
+        /// Resets internal data reader index.
+        /// </summary>
+        protected void ResetReader()
+        {
+            _stream.Position = ZeroReaderIndex + _offset;
+        }
+
+        /// <summary>
+        /// Reads all data left in internal buffer at current position.
+        /// </summary>
+        /// <returns>An array of bytes containing the remaining data in the internal buffer.</returns>
+        protected byte[] ReadBytes()
+        {
+            var bytesLength = (int) (_stream.Length - _stream.Position);
+            var data = new byte[bytesLength];
+            _stream.Read(data, 0, bytesLength);
+            return data;
+        }
+
+        /// <summary>
+        /// Reads next specified number of bytes data type from internal buffer.
+        /// </summary>
+        /// <param name="length">Number of bytes to read.</param>
+        /// <returns>An array of bytes that was read from the internal buffer.</returns>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="length"/> is greater than the internal buffer size.</exception>
+        protected byte[] ReadBytes(int length)
+        {
+            // Note that this also prevents allocating non-relevant lengths, such as if length is greater than _data.Count but less than int.MaxValue.
+            // For the nerds, the condition translates to: if (length > data.Count && length < int.MaxValue)
+            // Which probably would cause all sorts of exception, most notably OutOfMemoryException.
+
+            var data = new byte[length];
+            var bytesRead = _stream.Read(data, 0, length);
+
+            if (bytesRead < length)
+                throw new ArgumentOutOfRangeException("length");
+
+            return data;
+        }
+
+        /// <summary>
+        /// Reads next byte data type from internal buffer.
+        /// </summary>
+        /// <returns>Byte read.</returns>
+        protected byte ReadByte()
+        {
+            var byteRead = _stream.ReadByte();
+            if (byteRead == -1)
+                throw new InvalidOperationException("Attempt to read past the end of the SSH data stream.");
+            return (byte) byteRead;
+        }
+
+        /// <summary>
+        /// Reads next boolean data type from internal buffer.
+        /// </summary>
+        /// <returns>Boolean read.</returns>
+        protected bool ReadBoolean()
+        {
+            return ReadByte() != 0;
+        }
+
+        /// <summary>
+        /// Reads next uint16 data type from internal buffer.
+        /// </summary>
+        /// <returns>uint16 read</returns>
+        protected ushort ReadUInt16()
+        {
+            var data = ReadBytes(2);
+            return (ushort)(data[0] << 8 | data[1]);
+        }
+
+        /// <summary>
+        /// Reads next uint32 data type from internal buffer.
+        /// </summary>
+        /// <returns>uint32 read</returns>
+        protected uint ReadUInt32()
+        {
+            var data = ReadBytes(4);
+            return (uint)(data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]);
+        }
+
+        /// <summary>
+        /// Reads next uint64 data type from internal buffer.
+        /// </summary>
+        /// <returns>uint64 read</returns>
+        protected ulong ReadUInt64()
+        {
+            var data = ReadBytes(8);
+            return ((ulong)data[0] << 56 | (ulong)data[1] << 48 | (ulong)data[2] << 40 | (ulong)data[3] << 32 | (ulong)data[4] << 24 | (ulong)data[5] << 16 | (ulong)data[6] << 8 | data[7]);
+        }
+
+        /// <summary>
+        /// Reads next string data type from internal buffer using the specific encoding.
+        /// </summary>
+        /// <returns>
+        /// The <see cref="string"/> read.
+        /// </returns>
+        protected string ReadString(Encoding encoding)
+        {
+            return _stream.ReadString(encoding);
+        }
+
+        /// <summary>
+        /// Reads next data type as byte array from internal buffer.
+        /// </summary>
+        /// <returns>
+        /// The bytes read.
+        /// </returns>
+        protected byte[] ReadBinary()
+        {
+            return _stream.ReadBinary();
+        }
+
+        /// <summary>
+        /// Reads next name-list data type from internal buffer.
+        /// </summary>
+        /// <returns>
+        /// String array or read data.
+        /// </returns>
+        protected string[] ReadNamesList()
+        {
+            var namesList = ReadString(Ascii);
+            return namesList.Split(',');
+        }
+
+        /// <summary>
+        /// Reads next extension-pair data type from internal buffer.
+        /// </summary>
+        /// <returns>Extensions pair dictionary.</returns>
+        protected IDictionary<string, string> ReadExtensionPair()
+        {
+            var result = new Dictionary<string, string>();
+            while (!IsEndOfData)
+            {
+                var extensionName = ReadString(Ascii);
+                var extensionData = ReadString(Ascii);
+                result.Add(extensionName, extensionData);
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// Writes bytes array data into internal buffer.
+        /// </summary>
+        /// <param name="data">Byte array data to write.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="data"/> is null.</exception>
+        protected void Write(byte[] data)
+        {
+            _stream.Write(data);
+        }
+
+        /// <summary>
+        /// Writes a sequence of bytes to the current SSH data stream and advances the current position
+        /// within this stream by the number of bytes written.
+        /// </summary>
+        /// <param name="buffer">An array of bytes. This method write <paramref name="count"/> bytes from buffer to the current SSH data stream.</param>
+        /// <param name="offset">The zero-based offset in <paramref name="buffer"/> at which to begin writing bytes to the SSH data stream.</param>
+        /// <param name="count">The number of bytes to be written to the current SSH data stream.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is null.</exception>
+        /// <exception cref="ArgumentException">The sum of <paramref name="offset"/> and <paramref name="count"/> is greater than the buffer length.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="offset"/> or <paramref name="count"/> is negative.</exception>
+        protected void Write(byte[] buffer, int offset, int count)
+        {
+            _stream.Write(buffer, offset, count);
+        }
+
+        /// <summary>
+        /// Writes <see cref="byte"/> data into internal buffer.
+        /// </summary>
+        /// <param name="data"><see cref="byte"/> data to write.</param>
+        protected void Write(byte data)
+        {
+            _stream.WriteByte(data);
+        }
+
+        /// <summary>
+        /// Writes <see cref="bool"/> into internal buffer.
+        /// </summary>
+        /// <param name="data"><see cref="bool" /> data to write.</param>
+        protected void Write(bool data)
+        {
+            Write(data ? (byte) 1 : (byte) 0);
+        }
+
+        /// <summary>
+        /// Writes <see cref="uint"/> data into internal buffer.
+        /// </summary>
+        /// <param name="data"><see cref="uint"/> data to write.</param>
+        protected void Write(uint data)
+        {
+            _stream.Write(data);
+        }
+
+        /// <summary>
+        /// Writes <see cref="ulong" /> data into internal buffer.
+        /// </summary>
+        /// <param name="data"><see cref="ulong"/> data to write.</param>
+        protected void Write(ulong data)
+        {
+            _stream.Write(data);
+        }
+
+        /// <summary>
+        /// Writes <see cref="string"/> data into internal buffer using default encoding.
+        /// </summary>
+        /// <param name="data"><see cref="string"/> data to write.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="data"/> is null.</exception>
+        protected void Write(string data)
+        {
+            Write(data, Utf8);
+        }
+
+        /// <summary>
+        /// Writes <see cref="string"/> data into internal buffer using the specified encoding.
+        /// </summary>
+        /// <param name="data"><see cref="string"/> data to write.</param>
+        /// <param name="encoding">The character encoding to use.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="data"/> is null.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="encoding"/> is null.</exception>
+        protected void Write(string data, Encoding encoding)
+        {
+            _stream.Write(data, encoding);
+        }
+
+        /// <summary>
+        /// Writes data into internal buffer.
+        /// </summary>
+        /// <param name="buffer">The data to write.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is null.</exception>
+        protected void WriteBinaryString(byte[] buffer)
+        {
+            _stream.WriteBinary(buffer);
+        }
+
+        /// <summary>
+        /// Writes data into internal buffer.
+        /// </summary>
+        /// <param name="buffer">An array of bytes. This method write <paramref name="count"/> bytes from buffer to the current SSH data stream.</param>
+        /// <param name="offset">The zero-based byte offset in <paramref name="buffer"/> at which to begin writing bytes to the SSH data stream.</param>
+        /// <param name="count">The number of bytes to be written to the current SSH data stream.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is null.</exception>
+        /// <exception cref="ArgumentException">The sum of <paramref name="offset"/> and <paramref name="count"/> is greater than the buffer length.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="offset"/> or <paramref name="count"/> is negative.</exception>
+        protected void WriteBinary(byte[] buffer, int offset, int count)
+        {
+            _stream.WriteBinary(buffer, offset, count);
+        }
+
+        /// <summary>
+        /// Writes mpint data into internal buffer.
+        /// </summary>
+        /// <param name="data">mpint data to write.</param>
+        protected void Write(BigInteger data)
+        {
+            _stream.Write(data);
+        }
+
+        /// <summary>
+        /// Writes name-list data into internal buffer.
+        /// </summary>
+        /// <param name="data">name-list data to write.</param>
+        protected void Write(string[] data)
+        {
+            Write(string.Join(",", data), Ascii);
+        }
+
+        /// <summary>
+        /// Writes extension-pair data into internal buffer.
+        /// </summary>
+        /// <param name="data">extension-pair data to write.</param>
+        protected void Write(IDictionary<string, string> data)
+        {
+            foreach (var item in data)
+            {
+                Write(item.Key, Ascii);
+                Write(item.Value, Ascii);
+            }
+        }
+    }
+}

+ 253 - 253
src/Renci.SshNet/Common/SshDataStream.cs

@@ -1,253 +1,253 @@
-using System;
-using System.Globalization;
-using System.IO;
-using System.Text;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Specialized <see cref="MemoryStream"/> for reading and writing data SSH data.
-    /// </summary>
-    public class SshDataStream : MemoryStream
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshDataStream"/> class with an expandable capacity initialized
-        /// as specified.
-        /// </summary>
-        /// <param name="capacity">The initial size of the internal array in bytes.</param>
-        public SshDataStream(int capacity)
-            : base(capacity)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new non-resizable instance of the <see cref="SshDataStream"/> class based on the specified byte array.
-        /// </summary>
-        /// <param name="buffer">The array of unsigned bytes from which to create the current stream.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is <c>null.</c></exception>
-        public SshDataStream(byte[] buffer)
-            : base(buffer)
-        {
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether all data from the SSH data stream has been read.
-        /// </summary>
-        /// <value>
-        /// <c>true</c> if this instance is end of data; otherwise, <c>false</c>.
-        /// </value>
-        public bool IsEndOfData
-        {
-            get
-            {
-                return Position >= Length;
-            }
-        }
-
-        /// <summary>
-        /// Writes an <see cref="uint"/> to the SSH data stream.
-        /// </summary>
-        /// <param name="value"><see cref="uint"/> data to write.</param>
-        public void Write(uint value)
-        {
-            var bytes = value.GetBytes();
-            Write(bytes, 0, bytes.Length);
-        }
-
-        /// <summary>
-        /// Writes an <see cref="ulong"/> to the SSH data stream.
-        /// </summary>
-        /// <param name="value"><see cref="ulong"/> data to write.</param>
-        public void Write(ulong value)
-        {
-            var bytes = value.GetBytes();
-            Write(bytes, 0, bytes.Length);
-        }
-
-        /// <summary>
-        /// Writes a <see cref="BigInteger"/> into the SSH data stream.
-        /// </summary>
-        /// <param name="data">The <see cref="BigInteger" /> to write.</param>
-        public void Write(BigInteger data)
-        {
-            var bytes = data.ToByteArray().Reverse();
-            WriteBinary(bytes, 0, bytes.Length);
-        }
-
-        /// <summary>
-        /// Writes bytes array data into the SSH data stream.
-        /// </summary>
-        /// <param name="data">Byte array data to write.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="data"/> is null.</exception>
-        public void Write(byte[] data)
-        {
-            if (data == null)
-                throw new ArgumentNullException("data");
-
-            Write(data, 0, data.Length);
-        }
-
-        /// <summary>
-        /// Reads a byte array from the SSH data stream.
-        /// </summary>
-        /// <returns>
-        /// The byte array read from the SSH data stream.
-        /// </returns>
-        public byte[] ReadBinary()
-        {
-            var length = ReadUInt32();
-
-            if (length > int.MaxValue)
-            {
-                throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Data longer than {0} is not supported.", int.MaxValue));
-            }
-
-            return ReadBytes((int)length);
-        }
-
-        /// <summary>
-        /// Writes a buffer preceded by its length into the SSH data stream.
-        /// </summary>
-        /// <param name="buffer">The data to write.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is null.</exception>
-        public void WriteBinary(byte[] buffer)
-        {
-            if (buffer == null)
-                throw new ArgumentNullException("buffer");
-
-            WriteBinary(buffer, 0, buffer.Length);
-        }
-
-        /// <summary>
-        /// Writes a buffer preceded by its length into the SSH data stream.
-        /// </summary>
-        /// <param name="buffer">An array of bytes. This method write <paramref name="count"/> bytes from buffer to the current SSH data stream.</param>
-        /// <param name="offset">The zero-based byte offset in <paramref name="buffer"/> at which to begin writing bytes to the SSH data stream.</param>
-        /// <param name="count">The number of bytes to be written to the current SSH data stream.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is null.</exception>
-        /// <exception cref="ArgumentException">The sum of <paramref name="offset"/> and <paramref name="count"/> is greater than the buffer length.</exception>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="offset"/> or <paramref name="count"/> is negative.</exception>
-        public void WriteBinary(byte[] buffer, int offset, int count)
-        {
-            Write((uint) count);
-            Write(buffer, offset, count);
-        }
-
-        /// <summary>
-        /// Writes string data to the SSH data stream using the specified encoding.
-        /// </summary>
-        /// <param name="s">The string data to write.</param>
-        /// <param name="encoding">The character encoding to use.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="s"/> is null.</exception>
-        /// <exception cref="ArgumentNullException"><paramref name="encoding"/> is null.</exception>
-        public void Write(string s, Encoding encoding)
-        {
-            if (encoding == null)
-                throw new ArgumentNullException("encoding");
-
-            var bytes = encoding.GetBytes(s);
-            WriteBinary(bytes, 0, bytes.Length);
-        }
-
-        /// <summary>
-        /// Reads a <see cref="BigInteger"/> from the SSH datastream.
-        /// </summary>
-        /// <returns>
-        /// The <see cref="BigInteger"/> read from the SSH data stream.
-        /// </returns>
-        public BigInteger ReadBigInt()
-        {
-            var length = ReadUInt32();
-            var data = ReadBytes((int) length);
-            return new BigInteger(data.Reverse());
-        }
-
-        /// <summary>
-        /// Reads the next <see cref="uint"/> data type from the SSH data stream.
-        /// </summary>
-        /// <returns>
-        /// The <see cref="uint"/> read from the SSH data stream.
-        /// </returns>
-        public uint ReadUInt32()
-        {
-            var data = ReadBytes(4);
-            return (uint) (data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]);
-        }
-
-        /// <summary>
-        /// Reads the next <see cref="ulong"/> data type from the SSH data stream.
-        /// </summary>
-        /// <returns>
-        /// The <see cref="ulong"/> read from the SSH data stream.
-        /// </returns>
-        public ulong ReadUInt64()
-        {
-            var data = ReadBytes(8);
-            return ((ulong) data[0] << 56 | (ulong) data[1] << 48 | (ulong) data[2] << 40 | (ulong) data[3] << 32 |
-                    (ulong) data[4] << 24 | (ulong) data[5] << 16 | (ulong) data[6] << 8 | data[7]);
-        }
-
-        /// <summary>
-        /// Reads the next <see cref="string"/> data type from the SSH data stream.
-        /// </summary>
-        /// <returns>
-        /// The <see cref="string"/> read from the SSH data stream.
-        /// </returns>
-        public string ReadString(Encoding encoding)
-        {
-            var length = ReadUInt32();
-
-            if (length > int.MaxValue)
-            {
-                throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Strings longer than {0} is not supported.", int.MaxValue));
-            }
-
-            var bytes = ReadBytes((int) length);
-            return encoding.GetString(bytes, 0, bytes.Length);
-        }
-
-        /// <summary>
-        /// Reads next specified number of bytes data type from internal buffer.
-        /// </summary>
-        /// <param name="length">Number of bytes to read.</param>
-        /// <returns>
-        /// An array of bytes that was read from the internal buffer.
-        /// </returns>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="length"/> is greater than the internal buffer size.</exception>
-        private byte[] ReadBytes(int length)
-        {
-            var data = new byte[length];
-            var bytesRead = Read(data, 0, length);
-
-            if (bytesRead < length)
-                throw new ArgumentOutOfRangeException("length");
-
-            return data;
-        }
-
-        /// <summary>
-        /// Writes the stream contents to a byte array, regardless of the <see cref="MemoryStream.Position"/>.
-        /// </summary>
-        /// <returns>
-        /// This method returns the contents of the <see cref="SshDataStream"/> as a byte array.
-        /// </returns>
-        /// <remarks>
-        /// If the current instance was constructed on a provided byte array, a copy of the section of the array
-        /// to which this instance has access is returned.
-        /// </remarks>
-        public override byte[] ToArray()
-        {
-            if (Capacity == Length)
-            {
-#if FEATURE_MEMORYSTREAM_GETBUFFER
-                return GetBuffer();
-#elif FEATURE_MEMORYSTREAM_TRYGETBUFFER
-                ArraySegment<byte> buffer;
-                if (TryGetBuffer(out buffer))
-                    return buffer.Array;
-#endif
-            }
-            return base.ToArray();
-        }
-    }
-}
+using System;
+using System.Globalization;
+using System.IO;
+using System.Text;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Specialized <see cref="MemoryStream"/> for reading and writing data SSH data.
+    /// </summary>
+    public class SshDataStream : MemoryStream
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshDataStream"/> class with an expandable capacity initialized
+        /// as specified.
+        /// </summary>
+        /// <param name="capacity">The initial size of the internal array in bytes.</param>
+        public SshDataStream(int capacity)
+            : base(capacity)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new non-resizable instance of the <see cref="SshDataStream"/> class based on the specified byte array.
+        /// </summary>
+        /// <param name="buffer">The array of unsigned bytes from which to create the current stream.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is <c>null.</c></exception>
+        public SshDataStream(byte[] buffer)
+            : base(buffer)
+        {
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether all data from the SSH data stream has been read.
+        /// </summary>
+        /// <value>
+        /// <c>true</c> if this instance is end of data; otherwise, <c>false</c>.
+        /// </value>
+        public bool IsEndOfData
+        {
+            get
+            {
+                return Position >= Length;
+            }
+        }
+
+        /// <summary>
+        /// Writes an <see cref="uint"/> to the SSH data stream.
+        /// </summary>
+        /// <param name="value"><see cref="uint"/> data to write.</param>
+        public void Write(uint value)
+        {
+            var bytes = value.GetBytes();
+            Write(bytes, 0, bytes.Length);
+        }
+
+        /// <summary>
+        /// Writes an <see cref="ulong"/> to the SSH data stream.
+        /// </summary>
+        /// <param name="value"><see cref="ulong"/> data to write.</param>
+        public void Write(ulong value)
+        {
+            var bytes = value.GetBytes();
+            Write(bytes, 0, bytes.Length);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="BigInteger"/> into the SSH data stream.
+        /// </summary>
+        /// <param name="data">The <see cref="BigInteger" /> to write.</param>
+        public void Write(BigInteger data)
+        {
+            var bytes = data.ToByteArray().Reverse();
+            WriteBinary(bytes, 0, bytes.Length);
+        }
+
+        /// <summary>
+        /// Writes bytes array data into the SSH data stream.
+        /// </summary>
+        /// <param name="data">Byte array data to write.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="data"/> is null.</exception>
+        public void Write(byte[] data)
+        {
+            if (data == null)
+                throw new ArgumentNullException("data");
+
+            Write(data, 0, data.Length);
+        }
+
+        /// <summary>
+        /// Reads a byte array from the SSH data stream.
+        /// </summary>
+        /// <returns>
+        /// The byte array read from the SSH data stream.
+        /// </returns>
+        public byte[] ReadBinary()
+        {
+            var length = ReadUInt32();
+
+            if (length > int.MaxValue)
+            {
+                throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Data longer than {0} is not supported.", int.MaxValue));
+            }
+
+            return ReadBytes((int)length);
+        }
+
+        /// <summary>
+        /// Writes a buffer preceded by its length into the SSH data stream.
+        /// </summary>
+        /// <param name="buffer">The data to write.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is null.</exception>
+        public void WriteBinary(byte[] buffer)
+        {
+            if (buffer == null)
+                throw new ArgumentNullException("buffer");
+
+            WriteBinary(buffer, 0, buffer.Length);
+        }
+
+        /// <summary>
+        /// Writes a buffer preceded by its length into the SSH data stream.
+        /// </summary>
+        /// <param name="buffer">An array of bytes. This method write <paramref name="count"/> bytes from buffer to the current SSH data stream.</param>
+        /// <param name="offset">The zero-based byte offset in <paramref name="buffer"/> at which to begin writing bytes to the SSH data stream.</param>
+        /// <param name="count">The number of bytes to be written to the current SSH data stream.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is null.</exception>
+        /// <exception cref="ArgumentException">The sum of <paramref name="offset"/> and <paramref name="count"/> is greater than the buffer length.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="offset"/> or <paramref name="count"/> is negative.</exception>
+        public void WriteBinary(byte[] buffer, int offset, int count)
+        {
+            Write((uint) count);
+            Write(buffer, offset, count);
+        }
+
+        /// <summary>
+        /// Writes string data to the SSH data stream using the specified encoding.
+        /// </summary>
+        /// <param name="s">The string data to write.</param>
+        /// <param name="encoding">The character encoding to use.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="s"/> is null.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="encoding"/> is null.</exception>
+        public void Write(string s, Encoding encoding)
+        {
+            if (encoding == null)
+                throw new ArgumentNullException("encoding");
+
+            var bytes = encoding.GetBytes(s);
+            WriteBinary(bytes, 0, bytes.Length);
+        }
+
+        /// <summary>
+        /// Reads a <see cref="BigInteger"/> from the SSH datastream.
+        /// </summary>
+        /// <returns>
+        /// The <see cref="BigInteger"/> read from the SSH data stream.
+        /// </returns>
+        public BigInteger ReadBigInt()
+        {
+            var length = ReadUInt32();
+            var data = ReadBytes((int) length);
+            return new BigInteger(data.Reverse());
+        }
+
+        /// <summary>
+        /// Reads the next <see cref="uint"/> data type from the SSH data stream.
+        /// </summary>
+        /// <returns>
+        /// The <see cref="uint"/> read from the SSH data stream.
+        /// </returns>
+        public uint ReadUInt32()
+        {
+            var data = ReadBytes(4);
+            return (uint) (data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]);
+        }
+
+        /// <summary>
+        /// Reads the next <see cref="ulong"/> data type from the SSH data stream.
+        /// </summary>
+        /// <returns>
+        /// The <see cref="ulong"/> read from the SSH data stream.
+        /// </returns>
+        public ulong ReadUInt64()
+        {
+            var data = ReadBytes(8);
+            return ((ulong) data[0] << 56 | (ulong) data[1] << 48 | (ulong) data[2] << 40 | (ulong) data[3] << 32 |
+                    (ulong) data[4] << 24 | (ulong) data[5] << 16 | (ulong) data[6] << 8 | data[7]);
+        }
+
+        /// <summary>
+        /// Reads the next <see cref="string"/> data type from the SSH data stream.
+        /// </summary>
+        /// <returns>
+        /// The <see cref="string"/> read from the SSH data stream.
+        /// </returns>
+        public string ReadString(Encoding encoding)
+        {
+            var length = ReadUInt32();
+
+            if (length > int.MaxValue)
+            {
+                throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Strings longer than {0} is not supported.", int.MaxValue));
+            }
+
+            var bytes = ReadBytes((int) length);
+            return encoding.GetString(bytes, 0, bytes.Length);
+        }
+
+        /// <summary>
+        /// Reads next specified number of bytes data type from internal buffer.
+        /// </summary>
+        /// <param name="length">Number of bytes to read.</param>
+        /// <returns>
+        /// An array of bytes that was read from the internal buffer.
+        /// </returns>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="length"/> is greater than the internal buffer size.</exception>
+        private byte[] ReadBytes(int length)
+        {
+            var data = new byte[length];
+            var bytesRead = Read(data, 0, length);
+
+            if (bytesRead < length)
+                throw new ArgumentOutOfRangeException("length");
+
+            return data;
+        }
+
+        /// <summary>
+        /// Writes the stream contents to a byte array, regardless of the <see cref="MemoryStream.Position"/>.
+        /// </summary>
+        /// <returns>
+        /// This method returns the contents of the <see cref="SshDataStream"/> as a byte array.
+        /// </returns>
+        /// <remarks>
+        /// If the current instance was constructed on a provided byte array, a copy of the section of the array
+        /// to which this instance has access is returned.
+        /// </remarks>
+        public override byte[] ToArray()
+        {
+            if (Capacity == Length)
+            {
+#if FEATURE_MEMORYSTREAM_GETBUFFER
+                return GetBuffer();
+#elif FEATURE_MEMORYSTREAM_TRYGETBUFFER
+                ArraySegment<byte> buffer;
+                if (TryGetBuffer(out buffer))
+                    return buffer.Array;
+#endif
+            }
+            return base.ToArray();
+        }
+    }
+}

+ 25 - 25
src/Renci.SshNet/Common/SshException.NET40.cs

@@ -1,25 +1,25 @@
-using System;
-using System.Runtime.Serialization;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// The exception that is thrown when SSH exception occurs.
-    /// </summary>
-    [Serializable]
-    public partial class SshException
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshException"/> class.
-        /// </summary>
-        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
-        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
-        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
-        ///   
-        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
-        protected SshException(SerializationInfo info, StreamingContext context)
-            : base(info, context)
-        {
-        }
-    }
-}
+using System;
+using System.Runtime.Serialization;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// The exception that is thrown when SSH exception occurs.
+    /// </summary>
+    [Serializable]
+    public partial class SshException
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshException"/> class.
+        /// </summary>
+        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
+        ///   
+        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
+        protected SshException(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+        }
+    }
+}

+ 36 - 36
src/Renci.SshNet/Common/SshException.cs

@@ -1,36 +1,36 @@
-using System;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// The exception that is thrown when SSH exception occurs.
-    /// </summary>
-    public partial class SshException : Exception
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshException"/> class.
-        /// </summary>
-        public SshException()
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshException"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        public SshException(string message)
-            : base(message)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshException"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <param name="inner">The inner.</param>
-        public SshException(string message, Exception inner)
-            : base(message, inner)
-        {
-        }
-    }
-}
+using System;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// The exception that is thrown when SSH exception occurs.
+    /// </summary>
+    public partial class SshException : Exception
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshException"/> class.
+        /// </summary>
+        public SshException()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        public SshException(string message)
+            : base(message)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        /// <param name="inner">The inner.</param>
+        public SshException(string message, Exception inner)
+            : base(message, inner)
+        {
+        }
+    }
+}

+ 21 - 21
src/Renci.SshNet/Common/SshOperationTimeoutException.NET40.cs

@@ -1,21 +1,21 @@
-using System;
-using System.Runtime.Serialization;
-
-namespace Renci.SshNet.Common
-{
-    [Serializable]
-    public partial class SshOperationTimeoutException
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshOperationTimeoutException"/> class.
-        /// </summary>
-        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
-        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
-        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
-        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
-        protected SshOperationTimeoutException(SerializationInfo info, StreamingContext context)
-            : base(info, context)
-        {
-        }
-    }
-}
+using System;
+using System.Runtime.Serialization;
+
+namespace Renci.SshNet.Common
+{
+    [Serializable]
+    public partial class SshOperationTimeoutException
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshOperationTimeoutException"/> class.
+        /// </summary>
+        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
+        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
+        protected SshOperationTimeoutException(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+        }
+    }
+}

+ 36 - 36
src/Renci.SshNet/Common/SshOperationTimeoutException.cs

@@ -1,36 +1,36 @@
-using System;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// The exception that is thrown when operation is timed out.
-    /// </summary>
-    public partial class SshOperationTimeoutException : SshException
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshOperationTimeoutException"/> class.
-        /// </summary>
-        public SshOperationTimeoutException()
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshOperationTimeoutException"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        public SshOperationTimeoutException(string message)
-            : base(message)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshOperationTimeoutException"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <param name="innerException">The inner exception.</param>
-        public SshOperationTimeoutException(string message, Exception innerException) :
-            base(message, innerException)
-        {
-        }
-    }
-}
+using System;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// The exception that is thrown when operation is timed out.
+    /// </summary>
+    public partial class SshOperationTimeoutException : SshException
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshOperationTimeoutException"/> class.
+        /// </summary>
+        public SshOperationTimeoutException()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshOperationTimeoutException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        public SshOperationTimeoutException(string message)
+            : base(message)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshOperationTimeoutException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        /// <param name="innerException">The inner exception.</param>
+        public SshOperationTimeoutException(string message, Exception innerException) :
+            base(message, innerException)
+        {
+        }
+    }
+}

+ 24 - 24
src/Renci.SshNet/Common/SshPassPhraseNullOrEmptyException.NET40.cs

@@ -1,24 +1,24 @@
-using System;
-using System.Runtime.Serialization;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// The exception that is thrown when pass phrase for key file is empty or null
-    /// </summary>
-    [Serializable]
-    public partial class SshPassPhraseNullOrEmptyException
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshPassPhraseNullOrEmptyException"/> class.
-        /// </summary>
-        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
-        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
-        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
-        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
-        protected SshPassPhraseNullOrEmptyException(SerializationInfo info, StreamingContext context)
-            : base(info, context)
-        {
-        }
-    }
-}
+using System;
+using System.Runtime.Serialization;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// The exception that is thrown when pass phrase for key file is empty or null
+    /// </summary>
+    [Serializable]
+    public partial class SshPassPhraseNullOrEmptyException
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshPassPhraseNullOrEmptyException"/> class.
+        /// </summary>
+        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
+        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
+        protected SshPassPhraseNullOrEmptyException(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+        }
+    }
+}

+ 38 - 38
src/Renci.SshNet/Common/SshPassPhraseNullOrEmptyException.cs

@@ -1,38 +1,38 @@
-using System;
-
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// The exception that is thrown when pass phrase for key file is empty or null
-    /// </summary>
-    public partial class SshPassPhraseNullOrEmptyException : SshException
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshPassPhraseNullOrEmptyException"/> class.
-        /// </summary>
-        public SshPassPhraseNullOrEmptyException()
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshPassPhraseNullOrEmptyException"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        public SshPassPhraseNullOrEmptyException(string message)
-            : base(message)
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SshPassPhraseNullOrEmptyException"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <param name="innerException">The inner exception.</param>
-        public SshPassPhraseNullOrEmptyException(string message, Exception innerException) :
-            base(message, innerException)
-        {
-        }
-    }
-}
+using System;
+
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// The exception that is thrown when pass phrase for key file is empty or null
+    /// </summary>
+    public partial class SshPassPhraseNullOrEmptyException : SshException
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshPassPhraseNullOrEmptyException"/> class.
+        /// </summary>
+        public SshPassPhraseNullOrEmptyException()
+        {
+
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshPassPhraseNullOrEmptyException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        public SshPassPhraseNullOrEmptyException(string message)
+            : base(message)
+        {
+
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshPassPhraseNullOrEmptyException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        /// <param name="innerException">The inner exception.</param>
+        public SshPassPhraseNullOrEmptyException(string message, Exception innerException) :
+            base(message, innerException)
+        {
+        }
+    }
+}

+ 288 - 288
src/Renci.SshNet/Common/TerminalModes.cs

@@ -1,288 +1,288 @@
-namespace Renci.SshNet.Common
-{
-    /// <summary>
-    /// Specifies the initial assignments of the opcode values that are used in the 'encoded terminal modes' valu
-    /// </summary>
-    public enum TerminalModes : byte
-    {
-        /// <summary>
-        /// Indicates end of options.
-        /// </summary> 
-        TTY_OP_END = 0,
-        
-        /// <summary>
-        /// Interrupt character; 255 if none.  Similarly for the other characters.  Not all of these characters are supported on all systems.
-        /// </summary> 
-        VINTR = 1,
-
-        /// <summary>
-        /// The quit character (sends SIGQUIT signal on POSIX systems).
-        /// </summary> 
-        VQUIT = 2,
-        
-        /// <summary>
-        /// Erase the character to left of the cursor. 
-        /// </summary>
-        VERASE = 3,
-
-        /// <summary>
-        /// Kill the current input line.
-        /// </summary>
-        VKILL = 4,
-
-        /// <summary>
-        /// End-of-file character (sends EOF from the terminal).
-        /// </summary>
-        VEOF = 5,
-        
-        /// <summary>
-        /// End-of-line character in addition to carriage return and/or linefeed.
-        /// </summary>
-        VEOL = 6,
-        
-        /// <summary>
-        /// Additional end-of-line character.
-        /// </summary>
-        VEOL2 = 7,
-        
-        /// <summary>
-        /// Continues paused output (normally control-Q).
-        /// </summary>
-        VSTART = 8,
-        
-        /// <summary>
-        /// Pauses output (normally control-S).
-        /// </summary>
-        VSTOP = 9,
-        
-        /// <summary>
-        /// Suspends the current program.
-        /// </summary>
-        VSUSP = 10,
-        
-        /// <summary>
-        /// Another suspend character.
-        /// </summary>
-        VDSUSP = 11,
-
-        /// <summary>
-        /// Reprints the current input line.
-        /// </summary>
-        VREPRINT = 12,
-
-        /// <summary>
-        /// Erases a word left of cursor.
-        /// </summary>
-        VWERASE = 13,
-
-        /// <summary>
-        /// Enter the next character typed literally, even if it is a special character
-        /// </summary>
-        VLNEXT = 14,
-
-        /// <summary>
-        /// Character to flush output.
-        /// </summary>
-        VFLUSH = 15,
-
-        /// <summary>
-        /// Switch to a different shell layer.
-        /// </summary>
-        VSWTCH = 16,
-
-        /// <summary>
-        /// Prints system status line (load, command, pid, etc).
-        /// </summary>
-        VSTATUS = 17,
-
-        /// <summary>
-        /// Toggles the flushing of terminal output.
-        /// </summary>
-        VDISCARD = 18,
-
-        /// <summary>
-        /// The ignore parity flag.  The parameter SHOULD be 0 if this flag is FALSE, and 1 if it is TRUE.
-        /// </summary>
-        IGNPAR = 30,
-
-        /// <summary>
-        /// Mark parity and framing errors.
-        /// </summary>
-        PARMRK = 31,
-
-        /// <summary>
-        /// Enable checking of parity errors.
-        /// </summary>
-        INPCK = 32,
-
-        /// <summary>
-        /// Strip 8th bit off characters.
-        /// </summary>
-        ISTRIP = 33,
-
-        /// <summary>
-        /// Map NL into CR on input.
-        /// </summary>
-        INLCR = 34,
-
-        /// <summary>
-        /// Ignore CR on input.
-        /// </summary>
-        IGNCR = 35,
-
-        /// <summary>
-        /// Map CR to NL on input.
-        /// </summary>
-        ICRNL = 36,
-
-        /// <summary>
-        /// Translate uppercase characters to lowercase.
-        /// </summary>
-        IUCLC = 37,
-
-        /// <summary>
-        /// Enable output flow control.
-        /// </summary>
-        IXON = 38,
-
-        /// <summary>
-        /// Any char will restart after stop.
-        /// </summary>
-        IXANY = 39,
-
-        /// <summary>
-        /// Enable input flow control.
-        /// </summary>
-        IXOFF = 40,
-
-        /// <summary>
-        /// Ring bell on input queue full.
-        /// </summary>
-        IMAXBEL = 41,
-
-        /// <summary>
-        /// Enable signals INTR, QUIT, [D]SUSP.
-        /// </summary>
-        ISIG = 50,
-
-        /// <summary>
-        /// Canonicalize input lines.
-        /// </summary>
-        ICANON = 51,
-
-        /// <summary>
-        /// Enable input and output of uppercase characters by preceding their lowercase equivalents with "\".
-        /// </summary>
-        XCASE = 52,
-
-        /// <summary>
-        /// Enable echoing.
-        /// </summary>
-        ECHO = 53,
-
-        /// <summary>
-        /// Visually erase chars.
-        /// </summary>
-        ECHOE = 54,
-
-        /// <summary>
-        /// Kill character discards current line.
-        /// </summary>
-        ECHOK = 55,
-
-        /// <summary>
-        /// Echo NL even if ECHO is off.
-        /// </summary>
-        ECHONL = 56,
-
-        /// <summary>
-        /// Don't flush after interrupt.
-        /// </summary>
-        NOFLSH = 57,
-
-        /// <summary>
-        /// Stop background jobs from output.
-        /// </summary>
-        TOSTOP = 58,
-
-        /// <summary>
-        /// Enable extensions.
-        /// </summary>
-        IEXTEN = 59,
-
-        /// <summary>
-        /// Echo control characters as ^(Char).
-        /// </summary>
-        ECHOCTL = 60,
-
-        /// <summary>
-        /// Visual erase for line kill.
-        /// </summary>
-        ECHOKE = 61,
-
-        /// <summary>
-        /// Retype pending input.
-        /// </summary>
-        PENDIN = 62,
-
-        /// <summary>
-        /// Enable output processing.
-        /// </summary>
-        OPOST = 70,
-
-        /// <summary>
-        /// Convert lowercase to uppercase.
-        /// </summary>
-        OLCUC = 71,
-
-        /// <summary>
-        /// Map NL to CR-NL.
-        /// </summary>
-        ONLCR = 72,
-
-        /// <summary>
-        /// Translate carriage return to newline (output).
-        /// </summary>
-        OCRNL = 73,
-
-        /// <summary>
-        /// Translate newline to carriage return-newline (output).
-        /// </summary>
-        ONOCR = 74,
-
-        /// <summary>
-        /// Newline performs a carriage return (output).
-        /// </summary>
-        ONLRET = 75,
-
-        /// <summary>
-        /// 7 bit mode.
-        /// </summary>
-        CS7 = 90,
-
-        /// <summary>
-        /// 8 bit mode.
-        /// </summary>
-        CS8 = 91,
-
-        /// <summary>
-        /// Parity enable.
-        /// </summary>
-        PARENB = 92,
-
-        /// <summary>
-        /// Odd parity, else even.
-        /// </summary>
-        PARODD = 93,
-
-        /// <summary>
-        /// Specifies the input baud rate in bits per second.
-        /// </summary>
-        TTY_OP_ISPEED = 128,
-
-        /// <summary>
-        /// Specifies the output baud rate in bits per second.
-        /// </summary>
-        TTY_OP_OSPEED = 129,
-    }
-}
+namespace Renci.SshNet.Common
+{
+    /// <summary>
+    /// Specifies the initial assignments of the opcode values that are used in the 'encoded terminal modes' valu
+    /// </summary>
+    public enum TerminalModes : byte
+    {
+        /// <summary>
+        /// Indicates end of options.
+        /// </summary> 
+        TTY_OP_END = 0,
+        
+        /// <summary>
+        /// Interrupt character; 255 if none.  Similarly for the other characters.  Not all of these characters are supported on all systems.
+        /// </summary> 
+        VINTR = 1,
+
+        /// <summary>
+        /// The quit character (sends SIGQUIT signal on POSIX systems).
+        /// </summary> 
+        VQUIT = 2,
+        
+        /// <summary>
+        /// Erase the character to left of the cursor. 
+        /// </summary>
+        VERASE = 3,
+
+        /// <summary>
+        /// Kill the current input line.
+        /// </summary>
+        VKILL = 4,
+
+        /// <summary>
+        /// End-of-file character (sends EOF from the terminal).
+        /// </summary>
+        VEOF = 5,
+        
+        /// <summary>
+        /// End-of-line character in addition to carriage return and/or linefeed.
+        /// </summary>
+        VEOL = 6,
+        
+        /// <summary>
+        /// Additional end-of-line character.
+        /// </summary>
+        VEOL2 = 7,
+        
+        /// <summary>
+        /// Continues paused output (normally control-Q).
+        /// </summary>
+        VSTART = 8,
+        
+        /// <summary>
+        /// Pauses output (normally control-S).
+        /// </summary>
+        VSTOP = 9,
+        
+        /// <summary>
+        /// Suspends the current program.
+        /// </summary>
+        VSUSP = 10,
+        
+        /// <summary>
+        /// Another suspend character.
+        /// </summary>
+        VDSUSP = 11,
+
+        /// <summary>
+        /// Reprints the current input line.
+        /// </summary>
+        VREPRINT = 12,
+
+        /// <summary>
+        /// Erases a word left of cursor.
+        /// </summary>
+        VWERASE = 13,
+
+        /// <summary>
+        /// Enter the next character typed literally, even if it is a special character
+        /// </summary>
+        VLNEXT = 14,
+
+        /// <summary>
+        /// Character to flush output.
+        /// </summary>
+        VFLUSH = 15,
+
+        /// <summary>
+        /// Switch to a different shell layer.
+        /// </summary>
+        VSWTCH = 16,
+
+        /// <summary>
+        /// Prints system status line (load, command, pid, etc).
+        /// </summary>
+        VSTATUS = 17,
+
+        /// <summary>
+        /// Toggles the flushing of terminal output.
+        /// </summary>
+        VDISCARD = 18,
+
+        /// <summary>
+        /// The ignore parity flag.  The parameter SHOULD be 0 if this flag is FALSE, and 1 if it is TRUE.
+        /// </summary>
+        IGNPAR = 30,
+
+        /// <summary>
+        /// Mark parity and framing errors.
+        /// </summary>
+        PARMRK = 31,
+
+        /// <summary>
+        /// Enable checking of parity errors.
+        /// </summary>
+        INPCK = 32,
+
+        /// <summary>
+        /// Strip 8th bit off characters.
+        /// </summary>
+        ISTRIP = 33,
+
+        /// <summary>
+        /// Map NL into CR on input.
+        /// </summary>
+        INLCR = 34,
+
+        /// <summary>
+        /// Ignore CR on input.
+        /// </summary>
+        IGNCR = 35,
+
+        /// <summary>
+        /// Map CR to NL on input.
+        /// </summary>
+        ICRNL = 36,
+
+        /// <summary>
+        /// Translate uppercase characters to lowercase.
+        /// </summary>
+        IUCLC = 37,
+
+        /// <summary>
+        /// Enable output flow control.
+        /// </summary>
+        IXON = 38,
+
+        /// <summary>
+        /// Any char will restart after stop.
+        /// </summary>
+        IXANY = 39,
+
+        /// <summary>
+        /// Enable input flow control.
+        /// </summary>
+        IXOFF = 40,
+
+        /// <summary>
+        /// Ring bell on input queue full.
+        /// </summary>
+        IMAXBEL = 41,
+
+        /// <summary>
+        /// Enable signals INTR, QUIT, [D]SUSP.
+        /// </summary>
+        ISIG = 50,
+
+        /// <summary>
+        /// Canonicalize input lines.
+        /// </summary>
+        ICANON = 51,
+
+        /// <summary>
+        /// Enable input and output of uppercase characters by preceding their lowercase equivalents with "\".
+        /// </summary>
+        XCASE = 52,
+
+        /// <summary>
+        /// Enable echoing.
+        /// </summary>
+        ECHO = 53,
+
+        /// <summary>
+        /// Visually erase chars.
+        /// </summary>
+        ECHOE = 54,
+
+        /// <summary>
+        /// Kill character discards current line.
+        /// </summary>
+        ECHOK = 55,
+
+        /// <summary>
+        /// Echo NL even if ECHO is off.
+        /// </summary>
+        ECHONL = 56,
+
+        /// <summary>
+        /// Don't flush after interrupt.
+        /// </summary>
+        NOFLSH = 57,
+
+        /// <summary>
+        /// Stop background jobs from output.
+        /// </summary>
+        TOSTOP = 58,
+
+        /// <summary>
+        /// Enable extensions.
+        /// </summary>
+        IEXTEN = 59,
+
+        /// <summary>
+        /// Echo control characters as ^(Char).
+        /// </summary>
+        ECHOCTL = 60,
+
+        /// <summary>
+        /// Visual erase for line kill.
+        /// </summary>
+        ECHOKE = 61,
+
+        /// <summary>
+        /// Retype pending input.
+        /// </summary>
+        PENDIN = 62,
+
+        /// <summary>
+        /// Enable output processing.
+        /// </summary>
+        OPOST = 70,
+
+        /// <summary>
+        /// Convert lowercase to uppercase.
+        /// </summary>
+        OLCUC = 71,
+
+        /// <summary>
+        /// Map NL to CR-NL.
+        /// </summary>
+        ONLCR = 72,
+
+        /// <summary>
+        /// Translate carriage return to newline (output).
+        /// </summary>
+        OCRNL = 73,
+
+        /// <summary>
+        /// Translate newline to carriage return-newline (output).
+        /// </summary>
+        ONOCR = 74,
+
+        /// <summary>
+        /// Newline performs a carriage return (output).
+        /// </summary>
+        ONLRET = 75,
+
+        /// <summary>
+        /// 7 bit mode.
+        /// </summary>
+        CS7 = 90,
+
+        /// <summary>
+        /// 8 bit mode.
+        /// </summary>
+        CS8 = 91,
+
+        /// <summary>
+        /// Parity enable.
+        /// </summary>
+        PARENB = 92,
+
+        /// <summary>
+        /// Odd parity, else even.
+        /// </summary>
+        PARODD = 93,
+
+        /// <summary>
+        /// Specifies the input baud rate in bits per second.
+        /// </summary>
+        TTY_OP_ISPEED = 128,
+
+        /// <summary>
+        /// Specifies the output baud rate in bits per second.
+        /// </summary>
+        TTY_OP_OSPEED = 129,
+    }
+}

+ 18 - 18
src/Renci.SshNet/Compression/CompressionMode.cs

@@ -1,18 +1,18 @@
-namespace Renci.SshNet.Compression
-{
-    /// <summary>
-    /// Specifies compression modes
-    /// </summary>
-    public enum CompressionMode
-    {
-        /// <summary>
-        /// Specifies that content should be compressed.
-        /// </summary>
-        Compress = 0,
-
-        /// <summary>
-        /// Specifies that content should be decompressed.
-        /// </summary>
-        Decompress = 1,
-    }
-}
+namespace Renci.SshNet.Compression
+{
+    /// <summary>
+    /// Specifies compression modes
+    /// </summary>
+    public enum CompressionMode
+    {
+        /// <summary>
+        /// Specifies that content should be compressed.
+        /// </summary>
+        Compress = 0,
+
+        /// <summary>
+        /// Specifies that content should be decompressed.
+        /// </summary>
+        Decompress = 1,
+    }
+}

+ 183 - 183
src/Renci.SshNet/Compression/Compressor.cs

@@ -1,183 +1,183 @@
-using Renci.SshNet.Security;
-using System.IO;
-using System;
-
-namespace Renci.SshNet.Compression
-{
-    /// <summary>
-    /// Represents base class for compression algorithm implementation
-    /// </summary>
-    public abstract class Compressor : Algorithm, IDisposable
-    {
-        private readonly ZlibStream _compressor;
-        private readonly ZlibStream _decompressor;
-
-        private MemoryStream _compressorStream;
-        private MemoryStream _decompressorStream;
-
-        /// <summary>
-        /// Gets or sets a value indicating whether compression is active.
-        /// </summary>
-        /// <value>
-        ///   <c>true</c> if compression is active; otherwise, <c>false</c>.
-        /// </value>
-        protected bool IsActive { get; set; }
-
-        /// <summary>
-        /// Gets the session.
-        /// </summary>
-        protected Session Session { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="Compressor"/> class.
-        /// </summary>
-        protected Compressor()
-        {
-            _compressorStream = new MemoryStream();
-            _decompressorStream = new MemoryStream();
-
-            _compressor = new ZlibStream(_compressorStream, CompressionMode.Compress);
-            _decompressor = new ZlibStream(_decompressorStream, CompressionMode.Decompress);
-        }
-
-        /// <summary>
-        /// Initializes the algorithm
-        /// </summary>
-        /// <param name="session">The session.</param>
-        public virtual void Init(Session session)
-        {
-            Session = session;
-        }
-
-        /// <summary>
-        /// Compresses the specified data.
-        /// </summary>
-        /// <param name="data">Data to compress.</param>
-        /// <returns>Compressed data</returns>
-        public virtual byte[] Compress(byte[] data)
-        {
-            return Compress(data, 0, data.Length);
-        }
-
-        /// <summary>
-        /// Compresses the specified data.
-        /// </summary>
-        /// <param name="data">Data to compress.</param>
-        /// <param name="offset">The zero-based byte offset in <paramref name="data"/> at which to begin reading the data to compress. </param>
-        /// <param name="length">The number of bytes to be compressed. </param>
-        /// <returns>
-        /// The compressed data.
-        /// </returns>
-        public virtual byte[] Compress(byte[] data, int offset, int length)
-        {
-            if (!IsActive)
-            {
-                if (offset == 0 && length == data.Length)
-                    return data;
-
-                var buffer = new byte[length];
-                Buffer.BlockCopy(data, offset, buffer, 0, length);
-                return buffer;
-            }
-
-            _compressorStream.SetLength(0);
-
-            _compressor.Write(data, offset, length);
-
-            return _compressorStream.ToArray();
-        }
-
-        /// <summary>
-        /// Decompresses the specified data.
-        /// </summary>
-        /// <param name="data">Compressed data.</param>
-        /// <returns>
-        /// The decompressed data.
-        /// </returns>
-        public virtual byte[] Decompress(byte[] data)
-        {
-            return Decompress(data, 0, data.Length);
-        }
-
-        /// <summary>
-        /// Decompresses the specified data.
-        /// </summary>
-        /// <param name="data">Compressed data.</param>
-        /// <param name="offset">The zero-based byte offset in <paramref name="data"/> at which to begin reading the data to decompress. </param>
-        /// <param name="length">The number of bytes to be read from the compressed data. </param>
-        /// <returns>
-        /// The decompressed data.
-        /// </returns>
-        public virtual byte[] Decompress(byte[] data, int offset, int length)
-        {
-            if (!IsActive)
-            {
-                if (offset == 0 && length == data.Length)
-                    return data;
-
-                var buffer = new byte[length];
-                Buffer.BlockCopy(data, offset, buffer, 0, length);
-                return buffer;
-            }
-
-            _decompressorStream.SetLength(0);
-
-            _decompressor.Write(data, offset, length);
-
-            return _decompressorStream.ToArray();
-        }
-
-        #region IDisposable Members
-
-        private bool _isDisposed;
-
-        /// <summary>
-        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
-        /// </summary>
-        public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
-
-        /// <summary>
-        /// Releases unmanaged and - optionally - managed resources
-        /// </summary>
-        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
-        protected virtual void Dispose(bool disposing)
-        {
-            if (_isDisposed)
-                return;
-
-            if (disposing)
-            {
-                var compressorStream = _compressorStream;
-                if (compressorStream != null)
-                {
-                    compressorStream.Dispose();
-                    _compressorStream = null;
-                }
-
-                var decompressorStream = _decompressorStream;
-                if (decompressorStream != null)
-                {
-                    decompressorStream.Dispose();
-                    _decompressorStream = null;
-                }
-
-                _isDisposed = true;
-            }
-        }
-
-        /// <summary>
-        /// Releases unmanaged resources and performs other cleanup operations before the <see cref="Compressor"/> is reclaimed
-        /// by garbage collection.
-        /// </summary>
-        ~Compressor()
-        {
-            Dispose(false);
-        }
-
-        #endregion
-    }
-}
+using Renci.SshNet.Security;
+using System.IO;
+using System;
+
+namespace Renci.SshNet.Compression
+{
+    /// <summary>
+    /// Represents base class for compression algorithm implementation
+    /// </summary>
+    public abstract class Compressor : Algorithm, IDisposable
+    {
+        private readonly ZlibStream _compressor;
+        private readonly ZlibStream _decompressor;
+
+        private MemoryStream _compressorStream;
+        private MemoryStream _decompressorStream;
+
+        /// <summary>
+        /// Gets or sets a value indicating whether compression is active.
+        /// </summary>
+        /// <value>
+        ///   <c>true</c> if compression is active; otherwise, <c>false</c>.
+        /// </value>
+        protected bool IsActive { get; set; }
+
+        /// <summary>
+        /// Gets the session.
+        /// </summary>
+        protected Session Session { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="Compressor"/> class.
+        /// </summary>
+        protected Compressor()
+        {
+            _compressorStream = new MemoryStream();
+            _decompressorStream = new MemoryStream();
+
+            _compressor = new ZlibStream(_compressorStream, CompressionMode.Compress);
+            _decompressor = new ZlibStream(_decompressorStream, CompressionMode.Decompress);
+        }
+
+        /// <summary>
+        /// Initializes the algorithm
+        /// </summary>
+        /// <param name="session">The session.</param>
+        public virtual void Init(Session session)
+        {
+            Session = session;
+        }
+
+        /// <summary>
+        /// Compresses the specified data.
+        /// </summary>
+        /// <param name="data">Data to compress.</param>
+        /// <returns>Compressed data</returns>
+        public virtual byte[] Compress(byte[] data)
+        {
+            return Compress(data, 0, data.Length);
+        }
+
+        /// <summary>
+        /// Compresses the specified data.
+        /// </summary>
+        /// <param name="data">Data to compress.</param>
+        /// <param name="offset">The zero-based byte offset in <paramref name="data"/> at which to begin reading the data to compress. </param>
+        /// <param name="length">The number of bytes to be compressed. </param>
+        /// <returns>
+        /// The compressed data.
+        /// </returns>
+        public virtual byte[] Compress(byte[] data, int offset, int length)
+        {
+            if (!IsActive)
+            {
+                if (offset == 0 && length == data.Length)
+                    return data;
+
+                var buffer = new byte[length];
+                Buffer.BlockCopy(data, offset, buffer, 0, length);
+                return buffer;
+            }
+
+            _compressorStream.SetLength(0);
+
+            _compressor.Write(data, offset, length);
+
+            return _compressorStream.ToArray();
+        }
+
+        /// <summary>
+        /// Decompresses the specified data.
+        /// </summary>
+        /// <param name="data">Compressed data.</param>
+        /// <returns>
+        /// The decompressed data.
+        /// </returns>
+        public virtual byte[] Decompress(byte[] data)
+        {
+            return Decompress(data, 0, data.Length);
+        }
+
+        /// <summary>
+        /// Decompresses the specified data.
+        /// </summary>
+        /// <param name="data">Compressed data.</param>
+        /// <param name="offset">The zero-based byte offset in <paramref name="data"/> at which to begin reading the data to decompress. </param>
+        /// <param name="length">The number of bytes to be read from the compressed data. </param>
+        /// <returns>
+        /// The decompressed data.
+        /// </returns>
+        public virtual byte[] Decompress(byte[] data, int offset, int length)
+        {
+            if (!IsActive)
+            {
+                if (offset == 0 && length == data.Length)
+                    return data;
+
+                var buffer = new byte[length];
+                Buffer.BlockCopy(data, offset, buffer, 0, length);
+                return buffer;
+            }
+
+            _decompressorStream.SetLength(0);
+
+            _decompressor.Write(data, offset, length);
+
+            return _decompressorStream.ToArray();
+        }
+
+        #region IDisposable Members
+
+        private bool _isDisposed;
+
+        /// <summary>
+        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+        /// </summary>
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources
+        /// </summary>
+        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected virtual void Dispose(bool disposing)
+        {
+            if (_isDisposed)
+                return;
+
+            if (disposing)
+            {
+                var compressorStream = _compressorStream;
+                if (compressorStream != null)
+                {
+                    compressorStream.Dispose();
+                    _compressorStream = null;
+                }
+
+                var decompressorStream = _decompressorStream;
+                if (decompressorStream != null)
+                {
+                    decompressorStream.Dispose();
+                    _decompressorStream = null;
+                }
+
+                _isDisposed = true;
+            }
+        }
+
+        /// <summary>
+        /// Releases unmanaged resources and performs other cleanup operations before the <see cref="Compressor"/> is reclaimed
+        /// by garbage collection.
+        /// </summary>
+        ~Compressor()
+        {
+            Dispose(false);
+        }
+
+        #endregion
+    }
+}

+ 25 - 25
src/Renci.SshNet/Compression/Zlib.cs

@@ -1,26 +1,26 @@
-namespace Renci.SshNet.Compression
-{
-    /// <summary>
-    /// Represents "zlib" compression implementation
-    /// </summary>
-    internal class Zlib : Compressor
-    {
-        /// <summary>
-        /// Gets algorithm name.
-        /// </summary>
-        public override string Name
-        {
-            get { return "zlib"; }
-        }
-
-        /// <summary>
-        /// Initializes the algorithm
-        /// </summary>
-        /// <param name="session">The session.</param>
-        public override void Init(Session session)
-        {
-            base.Init(session);
-            IsActive = true;
-        }
-    }
+namespace Renci.SshNet.Compression
+{
+    /// <summary>
+    /// Represents "zlib" compression implementation
+    /// </summary>
+    internal class Zlib : Compressor
+    {
+        /// <summary>
+        /// Gets algorithm name.
+        /// </summary>
+        public override string Name
+        {
+            get { return "zlib"; }
+        }
+
+        /// <summary>
+        /// Initializes the algorithm
+        /// </summary>
+        /// <param name="session">The session.</param>
+        public override void Init(Session session)
+        {
+            base.Init(session);
+            IsActive = true;
+        }
+    }
 }

+ 34 - 34
src/Renci.SshNet/Compression/ZlibOpenSsh.cs

@@ -1,35 +1,35 @@
-using Renci.SshNet.Messages.Authentication;
-
-namespace Renci.SshNet.Compression
-{
-    /// <summary>
-    /// Represents "zlib@openssh.org" compression implementation
-    /// </summary>
-    public class ZlibOpenSsh : Compressor
-    {
-        /// <summary>
-        /// Gets algorithm name.
-        /// </summary>
-        public override string Name
-        {
-            get { return "zlib@openssh.org"; }
-        }
-
-        /// <summary>
-        /// Initializes the algorithm
-        /// </summary>
-        /// <param name="session">The session.</param>
-        public override void Init(Session session)
-        {
-            base.Init(session);
-
-            session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
-        }
-
-        private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs<SuccessMessage> e)
-        {
-            IsActive = true;
-            Session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
-        }
-    }
+using Renci.SshNet.Messages.Authentication;
+
+namespace Renci.SshNet.Compression
+{
+    /// <summary>
+    /// Represents "zlib@openssh.org" compression implementation
+    /// </summary>
+    public class ZlibOpenSsh : Compressor
+    {
+        /// <summary>
+        /// Gets algorithm name.
+        /// </summary>
+        public override string Name
+        {
+            get { return "zlib@openssh.org"; }
+        }
+
+        /// <summary>
+        /// Initializes the algorithm
+        /// </summary>
+        /// <param name="session">The session.</param>
+        public override void Init(Session session)
+        {
+            base.Init(session);
+
+            session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
+        }
+
+        private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs<SuccessMessage> e)
+        {
+            IsActive = true;
+            Session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
+        }
+    }
 }

+ 45 - 45
src/Renci.SshNet/Compression/ZlibStream.cs

@@ -1,45 +1,45 @@
-using System.IO;
-
-namespace Renci.SshNet.Compression
-{
-    /// <summary>
-    /// Implements Zlib compression algorithm.
-    /// </summary>
-    public class ZlibStream
-    {
-        //private readonly Ionic.Zlib.ZlibStream _baseStream;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ZlibStream" /> class.
-        /// </summary>
-        /// <param name="stream">The stream.</param>
-        /// <param name="mode">The mode.</param>
-        public ZlibStream(Stream stream, CompressionMode mode)
-        {
-            //switch (mode)
-            //{
-            //    case CompressionMode.Compress:
-            //        this._baseStream = new Ionic.Zlib.ZlibStream(stream, Ionic.Zlib.CompressionMode.Compress, Ionic.Zlib.CompressionLevel.Default);
-            //        break;
-            //    case CompressionMode.Decompress:
-            //        this._baseStream = new Ionic.Zlib.ZlibStream(stream, Ionic.Zlib.CompressionMode.Decompress, Ionic.Zlib.CompressionLevel.Default);
-            //        break;
-            //    default:
-            //        break;
-            //}
-
-            //this._baseStream.FlushMode = Ionic.Zlib.FlushType.Partial;
-        }
-
-        /// <summary>
-        /// Writes the specified buffer.
-        /// </summary>
-        /// <param name="buffer">The buffer.</param>
-        /// <param name="offset">The offset.</param>
-        /// <param name="count">The count.</param>
-        public void Write(byte[] buffer, int offset, int count)
-        {
-            //this._baseStream.Write(buffer, offset, count);
-        }
-    }
-}
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+    /// <summary>
+    /// Implements Zlib compression algorithm.
+    /// </summary>
+    public class ZlibStream
+    {
+        //private readonly Ionic.Zlib.ZlibStream _baseStream;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ZlibStream" /> class.
+        /// </summary>
+        /// <param name="stream">The stream.</param>
+        /// <param name="mode">The mode.</param>
+        public ZlibStream(Stream stream, CompressionMode mode)
+        {
+            //switch (mode)
+            //{
+            //    case CompressionMode.Compress:
+            //        this._baseStream = new Ionic.Zlib.ZlibStream(stream, Ionic.Zlib.CompressionMode.Compress, Ionic.Zlib.CompressionLevel.Default);
+            //        break;
+            //    case CompressionMode.Decompress:
+            //        this._baseStream = new Ionic.Zlib.ZlibStream(stream, Ionic.Zlib.CompressionMode.Decompress, Ionic.Zlib.CompressionLevel.Default);
+            //        break;
+            //    default:
+            //        break;
+            //}
+
+            //this._baseStream.FlushMode = Ionic.Zlib.FlushType.Partial;
+        }
+
+        /// <summary>
+        /// Writes the specified buffer.
+        /// </summary>
+        /// <param name="buffer">The buffer.</param>
+        /// <param name="offset">The offset.</param>
+        /// <param name="count">The count.</param>
+        public void Write(byte[] buffer, int offset, int count)
+        {
+            //this._baseStream.Write(buffer, offset, count);
+        }
+    }
+}

+ 443 - 443
src/Renci.SshNet/ConnectionInfo.cs

@@ -1,443 +1,443 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Security;
-using Renci.SshNet.Messages.Connection;
-using Renci.SshNet.Common;
-using Renci.SshNet.Messages.Authentication;
-using Renci.SshNet.Security.Cryptography;
-using Renci.SshNet.Security.Cryptography.Ciphers.Modes;
-using Renci.SshNet.Security.Cryptography.Ciphers;
-
-namespace Renci.SshNet
-{
-    /// <summary>
-    /// Represents remote connection information class.
-    /// </summary>
-    /// <remarks>
-    /// This class is NOT thread-safe. Do not use the same <see cref="ConnectionInfo"/> with multiple
-    /// client instances.
-    /// </remarks>
-    public class ConnectionInfo : IConnectionInfoInternal
-    {
-        internal static int DefaultPort = 22;
-
-        /// <summary>
-        /// Gets supported key exchange algorithms for this connection.
-        /// </summary>
-        public IDictionary<string, Type> KeyExchangeAlgorithms { get; private set; }
-
-        /// <summary>
-        /// Gets supported encryptions for this connection.
-        /// </summary>
-        public IDictionary<string, CipherInfo> Encryptions { get; private set; }
-
-        /// <summary>
-        /// Gets supported hash algorithms for this connection.
-        /// </summary>
-        public IDictionary<string, HashInfo> HmacAlgorithms { get; private set; }
-
-        /// <summary>
-        /// Gets supported host key algorithms for this connection.
-        /// </summary>
-        public IDictionary<string, Func<byte[], KeyHostAlgorithm>> HostKeyAlgorithms { get; private set; }
-
-        /// <summary>
-        /// Gets supported authentication methods for this connection.
-        /// </summary>
-        public IList<AuthenticationMethod> AuthenticationMethods { get; private set; }
-
-        /// <summary>
-        /// Gets supported compression algorithms for this connection.
-        /// </summary>
-        public IDictionary<string, Type> CompressionAlgorithms { get; private set; }
-
-        /// <summary>
-        /// Gets the supported channel requests for this connection.
-        /// </summary>
-        /// <value>
-        /// The supported channel requests for this connection.
-        /// </value>
-        public IDictionary<string, RequestInfo> ChannelRequests { get; private set; }
-
-        /// <summary>
-        /// Gets a value indicating whether connection is authenticated.
-        /// </summary>
-        /// <value>
-        /// <c>true</c> if connection is authenticated; otherwise, <c>false</c>.
-        /// </value>
-        public bool IsAuthenticated { get; private set; }
-
-        /// <summary>
-        /// Gets connection host.
-        /// </summary>
-        public string Host { get; private set; }
-
-        /// <summary>
-        /// Gets connection port.
-        /// </summary>
-        /// <value>
-        /// The connection port. The default value is 22.
-        /// </value>
-        public int Port { get; private set; }
-
-        /// <summary>
-        /// Gets connection username.
-        /// </summary>
-        public string Username { get; private set; }
-
-        /// <summary>
-        /// Gets proxy type.
-        /// </summary>
-        /// <value>
-        /// The type of the proxy.
-        /// </value>
-        public ProxyTypes ProxyType { get; private set; }
-
-        /// <summary>
-        /// Gets proxy connection host.
-        /// </summary>
-        public string ProxyHost { get; private set; }
-
-        /// <summary>
-        /// Gets proxy connection port.
-        /// </summary>
-        public int ProxyPort { get; private set; }
-
-        /// <summary>
-        /// Gets proxy connection username.
-        /// </summary>
-        public string ProxyUsername { get; private set; }
-
-        /// <summary>
-        /// Gets proxy connection password.
-        /// </summary>
-        public string ProxyPassword { get; private set; }
-
-        /// <summary>
-        /// Gets or sets connection timeout.
-        /// </summary>
-        /// <value>
-        /// The connection timeout. The default value is 30 seconds.
-        /// </value>
-        /// <example>
-        ///   <code source="..\..\Renci.SshNet.Tests\Classes\SshClientTest.cs" region="Example SshClient Connect Timeout" language="C#" title="Specify connection timeout" />
-        /// </example>
-        public TimeSpan Timeout { get; set; }
-
-        /// <summary>
-        /// Gets or sets the character encoding.
-        /// </summary>
-        /// <value>
-        /// The character encoding. The default is <see cref="System.Text.Encoding.UTF8"/>.
-        /// </value>
-        public Encoding Encoding { get; set; }
-
-        /// <summary>
-        /// Gets or sets number of retry attempts when session channel creation failed.
-        /// </summary>
-        /// <value>
-        /// The number of retry attempts when session channel creation failed. The default
-        /// value is 10.
-        /// </value>
-        public int RetryAttempts { get; set; }
-
-        /// <summary>
-        /// Gets or sets maximum number of session channels to be open simultaneously.
-        /// </summary>
-        /// <value>
-        /// The maximum number of session channels to be open simultaneously. The default
-        /// value is 10.
-        /// </value>
-        public int MaxSessions { get; set; }
-
-        /// <summary>
-        /// Occurs when authentication banner is sent by the server.
-        /// </summary>
-        /// <example>
-        ///     <code source="..\..\Renci.SshNet.Tests\Classes\PasswordConnectionInfoTest.cs" region="Example PasswordConnectionInfo AuthenticationBanner" language="C#" title="Display authentication banner" />
-        /// </example>
-        public event EventHandler<AuthenticationBannerEventArgs> AuthenticationBanner;
-
-        /// <summary>
-        /// Gets the current key exchange algorithm.
-        /// </summary>
-        public string CurrentKeyExchangeAlgorithm { get; internal set; }
-
-        /// <summary>
-        /// Gets the current server encryption.
-        /// </summary>
-        public string CurrentServerEncryption { get; internal set; }
-
-        /// <summary>
-        /// Gets the current client encryption.
-        /// </summary>
-        public string CurrentClientEncryption { get; internal set; }
-
-        /// <summary>
-        /// Gets the current server hash algorithm.
-        /// </summary>
-        public string CurrentServerHmacAlgorithm { get; internal set; }
-
-        /// <summary>
-        /// Gets the current client hash algorithm.
-        /// </summary>
-        public string CurrentClientHmacAlgorithm { get; internal set; }
-
-        /// <summary>
-        /// Gets the current host key algorithm.
-        /// </summary>
-        public string CurrentHostKeyAlgorithm { get; internal set; }
-
-        /// <summary>
-        /// Gets the current server compression algorithm.
-        /// </summary>
-        public string CurrentServerCompressionAlgorithm { get; internal set; }
-
-        /// <summary>
-        /// Gets the server version.
-        /// </summary>
-        public string ServerVersion { get; internal set; }
-
-        /// <summary>
-        /// Get the client version.
-        /// </summary>
-        public string ClientVersion { get; internal set; }
-
-        /// <summary>
-        /// Gets the current client compression algorithm.
-        /// </summary>
-        public string CurrentClientCompressionAlgorithm { get; internal set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ConnectionInfo"/> class.
-        /// </summary>
-        /// <param name="host">The host.</param>
-        /// <param name="username">The username.</param>
-        /// <param name="authenticationMethods">The authentication methods.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="host"/> is <c>null</c>.</exception>
-        /// <exception cref="ArgumentException"><paramref name="host"/> is a zero-length string.</exception>
-        /// <exception cref="ArgumentException"><paramref name="username" /> is null, a zero-length string or contains only whitespace characters.</exception>
-        /// <exception cref="ArgumentNullException"><paramref name="authenticationMethods"/> is <c>null</c>.</exception>
-        /// <exception cref="ArgumentException">No <paramref name="authenticationMethods"/> specified.</exception>
-        public ConnectionInfo(string host, string username, params AuthenticationMethod[] authenticationMethods)
-            : this(host, DefaultPort, username, ProxyTypes.None, null, 0, null, null, authenticationMethods)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ConnectionInfo"/> class.
-        /// </summary>
-        /// <param name="host">The host.</param>
-        /// <param name="port">The port.</param>
-        /// <param name="username">The username.</param>
-        /// <param name="authenticationMethods">The authentication methods.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="host"/> is <c>null</c>.</exception>
-        /// <exception cref="ArgumentException"><paramref name="username" /> is null, a zero-length string or contains only whitespace characters.</exception>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="port" /> is not within <see cref="F:System.Net.IPEndPoint.MinPort" /> and <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
-        /// <exception cref="ArgumentNullException"><paramref name="authenticationMethods"/> is <c>null</c>.</exception>
-        /// <exception cref="ArgumentException">No <paramref name="authenticationMethods"/> specified.</exception>
-        public ConnectionInfo(string host, int port, string username, params AuthenticationMethod[] authenticationMethods)
-            : this(host, port, username, ProxyTypes.None, null, 0, null, null, authenticationMethods)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ConnectionInfo" /> class.
-        /// </summary>
-        /// <param name="host">Connection host.</param>
-        /// <param name="port">Connection port.</param>
-        /// <param name="username">Connection username.</param>
-        /// <param name="proxyType">Type of the proxy.</param>
-        /// <param name="proxyHost">The proxy host.</param>
-        /// <param name="proxyPort">The proxy port.</param>
-        /// <param name="proxyUsername">The proxy username.</param>
-        /// <param name="proxyPassword">The proxy password.</param>
-        /// <param name="authenticationMethods">The authentication methods.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="host"/> is <c>null</c>.</exception>
-        /// <exception cref="ArgumentException"><paramref name="username" /> is null, a zero-length string or contains only whitespace characters.</exception>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="port" /> is not within <see cref="F:System.Net.IPEndPoint.MinPort" /> and <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
-        /// <exception cref="ArgumentNullException"><paramref name="proxyType"/> is not <see cref="ProxyTypes.None"/> and <paramref name="proxyHost" /> is <c>null</c>.</exception>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="proxyType"/> is not <see cref="ProxyTypes.None"/> and <paramref name="proxyPort" /> is not within <see cref="F:System.Net.IPEndPoint.MinPort" /> and <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
-        /// <exception cref="ArgumentNullException"><paramref name="authenticationMethods"/> is <c>null</c>.</exception>
-        /// <exception cref="ArgumentException">No <paramref name="authenticationMethods"/> specified.</exception>
-        public ConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword, params AuthenticationMethod[] authenticationMethods)
-        {
-            if (host == null)
-                throw new ArgumentNullException("host");
-            port.ValidatePort("port");
-
-            if (username == null)
-                throw new ArgumentNullException("username");
-            if (username.All(char.IsWhiteSpace))
-                throw new ArgumentException("Cannot be empty or contain only whitespace.", "username");
-
-            if (proxyType != ProxyTypes.None)
-            {
-                if (proxyHost == null)
-                    throw new ArgumentNullException("proxyHost");
-                proxyPort.ValidatePort("proxyPort");
-            }
-
-            if (authenticationMethods == null)
-                throw new ArgumentNullException("authenticationMethods");
-            if (authenticationMethods.Length == 0)
-                throw new ArgumentException("At least one authentication method should be specified.", "authenticationMethods");
-
-            //  Set default connection values
-            Timeout = TimeSpan.FromSeconds(30);
-            RetryAttempts = 10;
-            MaxSessions = 10;
-            Encoding = Encoding.UTF8;
-
-            KeyExchangeAlgorithms = new Dictionary<string, Type>
-                {
-                    {"diffie-hellman-group-exchange-sha256", typeof (KeyExchangeDiffieHellmanGroupExchangeSha256)},
-                    {"diffie-hellman-group-exchange-sha1", typeof (KeyExchangeDiffieHellmanGroupExchangeSha1)},
-                    {"diffie-hellman-group14-sha1", typeof (KeyExchangeDiffieHellmanGroup14Sha1)},
-                    {"diffie-hellman-group1-sha1", typeof (KeyExchangeDiffieHellmanGroup1Sha1)},
-                    //{"ecdh-sha2-nistp256", typeof(KeyExchangeEllipticCurveDiffieHellman)},
-                    //{"ecdh-sha2-nistp256", typeof(...)},
-                    //{"ecdh-sha2-nistp384", typeof(...)},
-                    //{"ecdh-sha2-nistp521", typeof(...)},
-                    //"gss-group1-sha1-toWM5Slw5Ew8Mqkay+al2g==" - WinSSHD
-                    //"gss-gex-sha1-toWM5Slw5Ew8Mqkay+al2g==" - WinSSHD
-                };
-
-            Encryptions = new Dictionary<string, CipherInfo>
-                {
-                    {"aes256-ctr", new CipherInfo(256, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))},
-                    {"3des-cbc", new CipherInfo(192, (key, iv) => new TripleDesCipher(key, new CbcCipherMode(iv), null))},
-                    {"aes128-cbc", new CipherInfo(128, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))},
-                    {"aes192-cbc", new CipherInfo(192, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))},
-                    {"aes256-cbc", new CipherInfo(256, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))},
-                    {"blowfish-cbc", new CipherInfo(128, (key, iv) => new BlowfishCipher(key, new CbcCipherMode(iv), null))},
-                    {"twofish-cbc", new CipherInfo(256, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))},
-                    {"twofish192-cbc", new CipherInfo(192, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))},
-                    {"twofish128-cbc", new CipherInfo(128, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))},
-                    {"twofish256-cbc", new CipherInfo(256, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))},
-                    ////{"serpent256-cbc", typeof(CipherSerpent256CBC)},
-                    ////{"serpent192-cbc", typeof(...)},
-                    ////{"serpent128-cbc", typeof(...)},
-                    {"arcfour", new CipherInfo(128, (key, iv) => new Arc4Cipher(key, false))},
-                    {"arcfour128", new CipherInfo(128, (key, iv) => new Arc4Cipher(key, true))},
-                    {"arcfour256", new CipherInfo(256, (key, iv) => new Arc4Cipher(key, true))},
-                    ////{"idea-cbc", typeof(...)},
-                    {"cast128-cbc", new CipherInfo(128, (key, iv) => new CastCipher(key, new CbcCipherMode(iv), null))},
-                    ////{"rijndael-cbc@lysator.liu.se", typeof(...)},                
-                    {"aes128-ctr", new CipherInfo(128, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))},
-                    {"aes192-ctr", new CipherInfo(192, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))},
-                };
-
-            HmacAlgorithms = new Dictionary<string, HashInfo>
-                {
-                    {"hmac-md5", new HashInfo(16*8, HashAlgorithmFactory.CreateHMACMD5)},
-                    {"hmac-md5-96", new HashInfo(16*8, key => HashAlgorithmFactory.CreateHMACMD5(key, 96))},
-                    {"hmac-sha1", new HashInfo(20*8, HashAlgorithmFactory.CreateHMACSHA1)},
-                    {"hmac-sha1-96", new HashInfo(20*8, key => HashAlgorithmFactory.CreateHMACSHA1(key, 96))},
-                    {"hmac-sha2-256", new HashInfo(32*8, HashAlgorithmFactory.CreateHMACSHA256)},
-                    {"hmac-sha2-256-96", new HashInfo(32*8, key => HashAlgorithmFactory.CreateHMACSHA256(key, 96))},
-                    {"hmac-sha2-512", new HashInfo(64 * 8, HashAlgorithmFactory.CreateHMACSHA512)},
-                    {"hmac-sha2-512-96", new HashInfo(64 * 8,  key => HashAlgorithmFactory.CreateHMACSHA512(key, 96))},
-                    //{"umac-64@openssh.com", typeof(HMacSha1)},
-                    {"hmac-ripemd160", new HashInfo(160, HashAlgorithmFactory.CreateHMACRIPEMD160)},
-                    {"hmac-ripemd160@openssh.com", new HashInfo(160, HashAlgorithmFactory.CreateHMACRIPEMD160)},
-                    //{"none", typeof(...)},
-                };
-
-            HostKeyAlgorithms = new Dictionary<string, Func<byte[], KeyHostAlgorithm>>
-                {
-                    {"ssh-rsa", data => new KeyHostAlgorithm("ssh-rsa", new RsaKey(), data)},
-                    {"ssh-dss", data => new KeyHostAlgorithm("ssh-dss", new DsaKey(), data)},
-                    //{"ecdsa-sha2-nistp256 "}
-                    //{"x509v3-sign-rsa", () => { ... },
-                    //{"x509v3-sign-dss", () => { ... },
-                    //{"spki-sign-rsa", () => { ... },
-                    //{"spki-sign-dss", () => { ... },
-                    //{"pgp-sign-rsa", () => { ... },
-                    //{"pgp-sign-dss", () => { ... },
-                };
-
-            CompressionAlgorithms = new Dictionary<string, Type>
-                {
-                    //{"zlib@openssh.com", typeof(ZlibOpenSsh)}, 
-                    //{"zlib", typeof(Zlib)}, 
-                    {"none", null},
-                };
-
-            ChannelRequests = new Dictionary<string, RequestInfo>
-                {
-                    {EnvironmentVariableRequestInfo.Name, new EnvironmentVariableRequestInfo()},
-                    {ExecRequestInfo.Name, new ExecRequestInfo()},
-                    {ExitSignalRequestInfo.Name, new ExitSignalRequestInfo()},
-                    {ExitStatusRequestInfo.Name, new ExitStatusRequestInfo()},
-                    {PseudoTerminalRequestInfo.Name, new PseudoTerminalRequestInfo()},
-                    {ShellRequestInfo.Name, new ShellRequestInfo()},
-                    {SignalRequestInfo.Name, new SignalRequestInfo()},
-                    {SubsystemRequestInfo.Name, new SubsystemRequestInfo()},
-                    {WindowChangeRequestInfo.Name, new WindowChangeRequestInfo()},
-                    {X11ForwardingRequestInfo.Name, new X11ForwardingRequestInfo()},
-                    {XonXoffRequestInfo.Name, new XonXoffRequestInfo()},
-                    {EndOfWriteRequestInfo.Name, new EndOfWriteRequestInfo()},
-                    {KeepAliveRequestInfo.Name, new KeepAliveRequestInfo()},
-                };
-
-            Host = host;
-            Port = port;
-            Username = username;
-
-            ProxyType = proxyType;
-            ProxyHost = proxyHost;
-            ProxyPort = proxyPort;
-            ProxyUsername = proxyUsername;
-            ProxyPassword = proxyPassword;
-
-            AuthenticationMethods = authenticationMethods;
-        }
-
-        /// <summary>
-        /// Authenticates the specified session.
-        /// </summary>
-        /// <param name="session">The session to be authenticated.</param>
-        /// <param name="serviceFactory">The factory to use for creating new services.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="session"/> is null.</exception>
-        /// <exception cref="ArgumentNullException"><paramref name="serviceFactory"/> is <c>null</c>.</exception>
-        /// <exception cref="SshAuthenticationException">No suitable authentication method found to complete authentication, or permission denied.</exception>
-        internal void Authenticate(ISession session, IServiceFactory serviceFactory)
-        {
-            if (serviceFactory == null)
-                throw new ArgumentNullException("serviceFactory");
-
-            IsAuthenticated = false;
-            var clientAuthentication = serviceFactory.CreateClientAuthentication();
-            clientAuthentication.Authenticate(this, session);
-            IsAuthenticated = true;
-        }
-
-        /// <summary>
-        /// Signals that an authentication banner message was received from the server.
-        /// </summary>
-        /// <param name="sender">The session in which the banner message was received.</param>
-        /// <param name="e">The banner message.{</param>
-        void IConnectionInfoInternal.UserAuthenticationBannerReceived(object sender, MessageEventArgs<BannerMessage> e)
-        {
-            var authenticationBanner = AuthenticationBanner;
-            if (authenticationBanner != null)
-            {
-                authenticationBanner(this,
-                    new AuthenticationBannerEventArgs(Username, e.Message.Message, e.Message.Language));
-            }
-        }
-
-        IAuthenticationMethod IConnectionInfoInternal.CreateNoneAuthenticationMethod()
-        {
-            return new NoneAuthenticationMethod(Username);
-        }
-
-        IList<IAuthenticationMethod> IConnectionInfoInternal.AuthenticationMethods
-        {
-            get { return AuthenticationMethods.Cast<IAuthenticationMethod>().ToList(); }
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Renci.SshNet.Security;
+using Renci.SshNet.Messages.Connection;
+using Renci.SshNet.Common;
+using Renci.SshNet.Messages.Authentication;
+using Renci.SshNet.Security.Cryptography;
+using Renci.SshNet.Security.Cryptography.Ciphers.Modes;
+using Renci.SshNet.Security.Cryptography.Ciphers;
+
+namespace Renci.SshNet
+{
+    /// <summary>
+    /// Represents remote connection information class.
+    /// </summary>
+    /// <remarks>
+    /// This class is NOT thread-safe. Do not use the same <see cref="ConnectionInfo"/> with multiple
+    /// client instances.
+    /// </remarks>
+    public class ConnectionInfo : IConnectionInfoInternal
+    {
+        internal static int DefaultPort = 22;
+
+        /// <summary>
+        /// Gets supported key exchange algorithms for this connection.
+        /// </summary>
+        public IDictionary<string, Type> KeyExchangeAlgorithms { get; private set; }
+
+        /// <summary>
+        /// Gets supported encryptions for this connection.
+        /// </summary>
+        public IDictionary<string, CipherInfo> Encryptions { get; private set; }
+
+        /// <summary>
+        /// Gets supported hash algorithms for this connection.
+        /// </summary>
+        public IDictionary<string, HashInfo> HmacAlgorithms { get; private set; }
+
+        /// <summary>
+        /// Gets supported host key algorithms for this connection.
+        /// </summary>
+        public IDictionary<string, Func<byte[], KeyHostAlgorithm>> HostKeyAlgorithms { get; private set; }
+
+        /// <summary>
+        /// Gets supported authentication methods for this connection.
+        /// </summary>
+        public IList<AuthenticationMethod> AuthenticationMethods { get; private set; }
+
+        /// <summary>
+        /// Gets supported compression algorithms for this connection.
+        /// </summary>
+        public IDictionary<string, Type> CompressionAlgorithms { get; private set; }
+
+        /// <summary>
+        /// Gets the supported channel requests for this connection.
+        /// </summary>
+        /// <value>
+        /// The supported channel requests for this connection.
+        /// </value>
+        public IDictionary<string, RequestInfo> ChannelRequests { get; private set; }
+
+        /// <summary>
+        /// Gets a value indicating whether connection is authenticated.
+        /// </summary>
+        /// <value>
+        /// <c>true</c> if connection is authenticated; otherwise, <c>false</c>.
+        /// </value>
+        public bool IsAuthenticated { get; private set; }
+
+        /// <summary>
+        /// Gets connection host.
+        /// </summary>
+        public string Host { get; private set; }
+
+        /// <summary>
+        /// Gets connection port.
+        /// </summary>
+        /// <value>
+        /// The connection port. The default value is 22.
+        /// </value>
+        public int Port { get; private set; }
+
+        /// <summary>
+        /// Gets connection username.
+        /// </summary>
+        public string Username { get; private set; }
+
+        /// <summary>
+        /// Gets proxy type.
+        /// </summary>
+        /// <value>
+        /// The type of the proxy.
+        /// </value>
+        public ProxyTypes ProxyType { get; private set; }
+
+        /// <summary>
+        /// Gets proxy connection host.
+        /// </summary>
+        public string ProxyHost { get; private set; }
+
+        /// <summary>
+        /// Gets proxy connection port.
+        /// </summary>
+        public int ProxyPort { get; private set; }
+
+        /// <summary>
+        /// Gets proxy connection username.
+        /// </summary>
+        public string ProxyUsername { get; private set; }
+
+        /// <summary>
+        /// Gets proxy connection password.
+        /// </summary>
+        public string ProxyPassword { get; private set; }
+
+        /// <summary>
+        /// Gets or sets connection timeout.
+        /// </summary>
+        /// <value>
+        /// The connection timeout. The default value is 30 seconds.
+        /// </value>
+        /// <example>
+        ///   <code source="..\..\Renci.SshNet.Tests\Classes\SshClientTest.cs" region="Example SshClient Connect Timeout" language="C#" title="Specify connection timeout" />
+        /// </example>
+        public TimeSpan Timeout { get; set; }
+
+        /// <summary>
+        /// Gets or sets the character encoding.
+        /// </summary>
+        /// <value>
+        /// The character encoding. The default is <see cref="System.Text.Encoding.UTF8"/>.
+        /// </value>
+        public Encoding Encoding { get; set; }
+
+        /// <summary>
+        /// Gets or sets number of retry attempts when session channel creation failed.
+        /// </summary>
+        /// <value>
+        /// The number of retry attempts when session channel creation failed. The default
+        /// value is 10.
+        /// </value>
+        public int RetryAttempts { get; set; }
+
+        /// <summary>
+        /// Gets or sets maximum number of session channels to be open simultaneously.
+        /// </summary>
+        /// <value>
+        /// The maximum number of session channels to be open simultaneously. The default
+        /// value is 10.
+        /// </value>
+        public int MaxSessions { get; set; }
+
+        /// <summary>
+        /// Occurs when authentication banner is sent by the server.
+        /// </summary>
+        /// <example>
+        ///     <code source="..\..\Renci.SshNet.Tests\Classes\PasswordConnectionInfoTest.cs" region="Example PasswordConnectionInfo AuthenticationBanner" language="C#" title="Display authentication banner" />
+        /// </example>
+        public event EventHandler<AuthenticationBannerEventArgs> AuthenticationBanner;
+
+        /// <summary>
+        /// Gets the current key exchange algorithm.
+        /// </summary>
+        public string CurrentKeyExchangeAlgorithm { get; internal set; }
+
+        /// <summary>
+        /// Gets the current server encryption.
+        /// </summary>
+        public string CurrentServerEncryption { get; internal set; }
+
+        /// <summary>
+        /// Gets the current client encryption.
+        /// </summary>
+        public string CurrentClientEncryption { get; internal set; }
+
+        /// <summary>
+        /// Gets the current server hash algorithm.
+        /// </summary>
+        public string CurrentServerHmacAlgorithm { get; internal set; }
+
+        /// <summary>
+        /// Gets the current client hash algorithm.
+        /// </summary>
+        public string CurrentClientHmacAlgorithm { get; internal set; }
+
+        /// <summary>
+        /// Gets the current host key algorithm.
+        /// </summary>
+        public string CurrentHostKeyAlgorithm { get; internal set; }
+
+        /// <summary>
+        /// Gets the current server compression algorithm.
+        /// </summary>
+        public string CurrentServerCompressionAlgorithm { get; internal set; }
+
+        /// <summary>
+        /// Gets the server version.
+        /// </summary>
+        public string ServerVersion { get; internal set; }
+
+        /// <summary>
+        /// Get the client version.
+        /// </summary>
+        public string ClientVersion { get; internal set; }
+
+        /// <summary>
+        /// Gets the current client compression algorithm.
+        /// </summary>
+        public string CurrentClientCompressionAlgorithm { get; internal set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ConnectionInfo"/> class.
+        /// </summary>
+        /// <param name="host">The host.</param>
+        /// <param name="username">The username.</param>
+        /// <param name="authenticationMethods">The authentication methods.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="host"/> is <c>null</c>.</exception>
+        /// <exception cref="ArgumentException"><paramref name="host"/> is a zero-length string.</exception>
+        /// <exception cref="ArgumentException"><paramref name="username" /> is null, a zero-length string or contains only whitespace characters.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="authenticationMethods"/> is <c>null</c>.</exception>
+        /// <exception cref="ArgumentException">No <paramref name="authenticationMethods"/> specified.</exception>
+        public ConnectionInfo(string host, string username, params AuthenticationMethod[] authenticationMethods)
+            : this(host, DefaultPort, username, ProxyTypes.None, null, 0, null, null, authenticationMethods)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ConnectionInfo"/> class.
+        /// </summary>
+        /// <param name="host">The host.</param>
+        /// <param name="port">The port.</param>
+        /// <param name="username">The username.</param>
+        /// <param name="authenticationMethods">The authentication methods.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="host"/> is <c>null</c>.</exception>
+        /// <exception cref="ArgumentException"><paramref name="username" /> is null, a zero-length string or contains only whitespace characters.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="port" /> is not within <see cref="F:System.Net.IPEndPoint.MinPort" /> and <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="authenticationMethods"/> is <c>null</c>.</exception>
+        /// <exception cref="ArgumentException">No <paramref name="authenticationMethods"/> specified.</exception>
+        public ConnectionInfo(string host, int port, string username, params AuthenticationMethod[] authenticationMethods)
+            : this(host, port, username, ProxyTypes.None, null, 0, null, null, authenticationMethods)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ConnectionInfo" /> class.
+        /// </summary>
+        /// <param name="host">Connection host.</param>
+        /// <param name="port">Connection port.</param>
+        /// <param name="username">Connection username.</param>
+        /// <param name="proxyType">Type of the proxy.</param>
+        /// <param name="proxyHost">The proxy host.</param>
+        /// <param name="proxyPort">The proxy port.</param>
+        /// <param name="proxyUsername">The proxy username.</param>
+        /// <param name="proxyPassword">The proxy password.</param>
+        /// <param name="authenticationMethods">The authentication methods.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="host"/> is <c>null</c>.</exception>
+        /// <exception cref="ArgumentException"><paramref name="username" /> is null, a zero-length string or contains only whitespace characters.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="port" /> is not within <see cref="F:System.Net.IPEndPoint.MinPort" /> and <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="proxyType"/> is not <see cref="ProxyTypes.None"/> and <paramref name="proxyHost" /> is <c>null</c>.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="proxyType"/> is not <see cref="ProxyTypes.None"/> and <paramref name="proxyPort" /> is not within <see cref="F:System.Net.IPEndPoint.MinPort" /> and <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="authenticationMethods"/> is <c>null</c>.</exception>
+        /// <exception cref="ArgumentException">No <paramref name="authenticationMethods"/> specified.</exception>
+        public ConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword, params AuthenticationMethod[] authenticationMethods)
+        {
+            if (host == null)
+                throw new ArgumentNullException("host");
+            port.ValidatePort("port");
+
+            if (username == null)
+                throw new ArgumentNullException("username");
+            if (username.All(char.IsWhiteSpace))
+                throw new ArgumentException("Cannot be empty or contain only whitespace.", "username");
+
+            if (proxyType != ProxyTypes.None)
+            {
+                if (proxyHost == null)
+                    throw new ArgumentNullException("proxyHost");
+                proxyPort.ValidatePort("proxyPort");
+            }
+
+            if (authenticationMethods == null)
+                throw new ArgumentNullException("authenticationMethods");
+            if (authenticationMethods.Length == 0)
+                throw new ArgumentException("At least one authentication method should be specified.", "authenticationMethods");
+
+            //  Set default connection values
+            Timeout = TimeSpan.FromSeconds(30);
+            RetryAttempts = 10;
+            MaxSessions = 10;
+            Encoding = Encoding.UTF8;
+
+            KeyExchangeAlgorithms = new Dictionary<string, Type>
+                {
+                    {"diffie-hellman-group-exchange-sha256", typeof (KeyExchangeDiffieHellmanGroupExchangeSha256)},
+                    {"diffie-hellman-group-exchange-sha1", typeof (KeyExchangeDiffieHellmanGroupExchangeSha1)},
+                    {"diffie-hellman-group14-sha1", typeof (KeyExchangeDiffieHellmanGroup14Sha1)},
+                    {"diffie-hellman-group1-sha1", typeof (KeyExchangeDiffieHellmanGroup1Sha1)},
+                    //{"ecdh-sha2-nistp256", typeof(KeyExchangeEllipticCurveDiffieHellman)},
+                    //{"ecdh-sha2-nistp256", typeof(...)},
+                    //{"ecdh-sha2-nistp384", typeof(...)},
+                    //{"ecdh-sha2-nistp521", typeof(...)},
+                    //"gss-group1-sha1-toWM5Slw5Ew8Mqkay+al2g==" - WinSSHD
+                    //"gss-gex-sha1-toWM5Slw5Ew8Mqkay+al2g==" - WinSSHD
+                };
+
+            Encryptions = new Dictionary<string, CipherInfo>
+                {
+                    {"aes256-ctr", new CipherInfo(256, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))},
+                    {"3des-cbc", new CipherInfo(192, (key, iv) => new TripleDesCipher(key, new CbcCipherMode(iv), null))},
+                    {"aes128-cbc", new CipherInfo(128, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))},
+                    {"aes192-cbc", new CipherInfo(192, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))},
+                    {"aes256-cbc", new CipherInfo(256, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))},
+                    {"blowfish-cbc", new CipherInfo(128, (key, iv) => new BlowfishCipher(key, new CbcCipherMode(iv), null))},
+                    {"twofish-cbc", new CipherInfo(256, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))},
+                    {"twofish192-cbc", new CipherInfo(192, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))},
+                    {"twofish128-cbc", new CipherInfo(128, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))},
+                    {"twofish256-cbc", new CipherInfo(256, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))},
+                    ////{"serpent256-cbc", typeof(CipherSerpent256CBC)},
+                    ////{"serpent192-cbc", typeof(...)},
+                    ////{"serpent128-cbc", typeof(...)},
+                    {"arcfour", new CipherInfo(128, (key, iv) => new Arc4Cipher(key, false))},
+                    {"arcfour128", new CipherInfo(128, (key, iv) => new Arc4Cipher(key, true))},
+                    {"arcfour256", new CipherInfo(256, (key, iv) => new Arc4Cipher(key, true))},
+                    ////{"idea-cbc", typeof(...)},
+                    {"cast128-cbc", new CipherInfo(128, (key, iv) => new CastCipher(key, new CbcCipherMode(iv), null))},
+                    ////{"rijndael-cbc@lysator.liu.se", typeof(...)},                
+                    {"aes128-ctr", new CipherInfo(128, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))},
+                    {"aes192-ctr", new CipherInfo(192, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))},
+                };
+
+            HmacAlgorithms = new Dictionary<string, HashInfo>
+                {
+                    {"hmac-md5", new HashInfo(16*8, HashAlgorithmFactory.CreateHMACMD5)},
+                    {"hmac-md5-96", new HashInfo(16*8, key => HashAlgorithmFactory.CreateHMACMD5(key, 96))},
+                    {"hmac-sha1", new HashInfo(20*8, HashAlgorithmFactory.CreateHMACSHA1)},
+                    {"hmac-sha1-96", new HashInfo(20*8, key => HashAlgorithmFactory.CreateHMACSHA1(key, 96))},
+                    {"hmac-sha2-256", new HashInfo(32*8, HashAlgorithmFactory.CreateHMACSHA256)},
+                    {"hmac-sha2-256-96", new HashInfo(32*8, key => HashAlgorithmFactory.CreateHMACSHA256(key, 96))},
+                    {"hmac-sha2-512", new HashInfo(64 * 8, HashAlgorithmFactory.CreateHMACSHA512)},
+                    {"hmac-sha2-512-96", new HashInfo(64 * 8,  key => HashAlgorithmFactory.CreateHMACSHA512(key, 96))},
+                    //{"umac-64@openssh.com", typeof(HMacSha1)},
+                    {"hmac-ripemd160", new HashInfo(160, HashAlgorithmFactory.CreateHMACRIPEMD160)},
+                    {"hmac-ripemd160@openssh.com", new HashInfo(160, HashAlgorithmFactory.CreateHMACRIPEMD160)},
+                    //{"none", typeof(...)},
+                };
+
+            HostKeyAlgorithms = new Dictionary<string, Func<byte[], KeyHostAlgorithm>>
+                {
+                    {"ssh-rsa", data => new KeyHostAlgorithm("ssh-rsa", new RsaKey(), data)},
+                    {"ssh-dss", data => new KeyHostAlgorithm("ssh-dss", new DsaKey(), data)},
+                    //{"ecdsa-sha2-nistp256 "}
+                    //{"x509v3-sign-rsa", () => { ... },
+                    //{"x509v3-sign-dss", () => { ... },
+                    //{"spki-sign-rsa", () => { ... },
+                    //{"spki-sign-dss", () => { ... },
+                    //{"pgp-sign-rsa", () => { ... },
+                    //{"pgp-sign-dss", () => { ... },
+                };
+
+            CompressionAlgorithms = new Dictionary<string, Type>
+                {
+                    //{"zlib@openssh.com", typeof(ZlibOpenSsh)}, 
+                    //{"zlib", typeof(Zlib)}, 
+                    {"none", null},
+                };
+
+            ChannelRequests = new Dictionary<string, RequestInfo>
+                {
+                    {EnvironmentVariableRequestInfo.Name, new EnvironmentVariableRequestInfo()},
+                    {ExecRequestInfo.Name, new ExecRequestInfo()},
+                    {ExitSignalRequestInfo.Name, new ExitSignalRequestInfo()},
+                    {ExitStatusRequestInfo.Name, new ExitStatusRequestInfo()},
+                    {PseudoTerminalRequestInfo.Name, new PseudoTerminalRequestInfo()},
+                    {ShellRequestInfo.Name, new ShellRequestInfo()},
+                    {SignalRequestInfo.Name, new SignalRequestInfo()},
+                    {SubsystemRequestInfo.Name, new SubsystemRequestInfo()},
+                    {WindowChangeRequestInfo.Name, new WindowChangeRequestInfo()},
+                    {X11ForwardingRequestInfo.Name, new X11ForwardingRequestInfo()},
+                    {XonXoffRequestInfo.Name, new XonXoffRequestInfo()},
+                    {EndOfWriteRequestInfo.Name, new EndOfWriteRequestInfo()},
+                    {KeepAliveRequestInfo.Name, new KeepAliveRequestInfo()},
+                };
+
+            Host = host;
+            Port = port;
+            Username = username;
+
+            ProxyType = proxyType;
+            ProxyHost = proxyHost;
+            ProxyPort = proxyPort;
+            ProxyUsername = proxyUsername;
+            ProxyPassword = proxyPassword;
+
+            AuthenticationMethods = authenticationMethods;
+        }
+
+        /// <summary>
+        /// Authenticates the specified session.
+        /// </summary>
+        /// <param name="session">The session to be authenticated.</param>
+        /// <param name="serviceFactory">The factory to use for creating new services.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="session"/> is null.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="serviceFactory"/> is <c>null</c>.</exception>
+        /// <exception cref="SshAuthenticationException">No suitable authentication method found to complete authentication, or permission denied.</exception>
+        internal void Authenticate(ISession session, IServiceFactory serviceFactory)
+        {
+            if (serviceFactory == null)
+                throw new ArgumentNullException("serviceFactory");
+
+            IsAuthenticated = false;
+            var clientAuthentication = serviceFactory.CreateClientAuthentication();
+            clientAuthentication.Authenticate(this, session);
+            IsAuthenticated = true;
+        }
+
+        /// <summary>
+        /// Signals that an authentication banner message was received from the server.
+        /// </summary>
+        /// <param name="sender">The session in which the banner message was received.</param>
+        /// <param name="e">The banner message.{</param>
+        void IConnectionInfoInternal.UserAuthenticationBannerReceived(object sender, MessageEventArgs<BannerMessage> e)
+        {
+            var authenticationBanner = AuthenticationBanner;
+            if (authenticationBanner != null)
+            {
+                authenticationBanner(this,
+                    new AuthenticationBannerEventArgs(Username, e.Message.Message, e.Message.Language));
+            }
+        }
+
+        IAuthenticationMethod IConnectionInfoInternal.CreateNoneAuthenticationMethod()
+        {
+            return new NoneAuthenticationMethod(Username);
+        }
+
+        IList<IAuthenticationMethod> IConnectionInfoInternal.AuthenticationMethods
+        {
+            get { return AuthenticationMethods.Cast<IAuthenticationMethod>().ToList(); }
+        }
+    }
+}

+ 31 - 31
src/Renci.SshNet/Documentation/Renci.SshNet.content

@@ -1,32 +1,32 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Topics>
-  <Topic id="43d0362a-d340-4c2e-acc8-96d666ec2727" visible="True" isExpanded="true" title="SSH.NET Library">
-    <Topic id="6deba9ac-263a-4db7-bcc3-1a36c6aebd00" visible="True" noFile="true" isExpanded="true" isSelected="true" title="Programming Guide">
-      <Topic id="ef6ffc84-f410-4682-9366-e9fe2a73ea52" visible="True" title="Overview" />
-      <Topic id="356eeabc-aafa-4a2a-a9ab-5247b9658296" visible="True" title="Connecting to the server" tocTitle="Connection">
-        <Topic id="b7b599b2-8bc2-4276-b9a2-d73eee2426ab" visible="True" title="Using password to connect" tocTitle="Password" />
-        <Topic id="c233e412-0ea1-422f-8337-e5d1231b71e5" visible="True" title="Using private key to connects" tocTitle="Private Key" />
-        <Topic id="281ac0c3-0d6c-4bf2-ae64-db6862d6fff5" visible="True" title="Interactive" />
-      </Topic>
-      <Topic id="bb9dec7b-fe99-46f4-8ee9-92936a976730" visible="True" title="Error Handling" />
-      <Topic id="37443441-b0d5-444f-a2d0-330ad8b95995" visible="True" title="SshClient">
-        <Topic id="2337d96d-7638-438e-b980-96e87b807265" visible="True" title="Commands" />
-        <Topic id="f4ce1bdd-403f-45ec-a622-86c05a4bd913" visible="True" title="Port Forwarding" />
-        <Topic id="86bd5fce-2370-4730-b956-364885f7ed6a" visible="True" title="Shell" />
-      </Topic>
-      <Topic id="8a496881-8cba-4347-8a57-8c047fc04be9" visible="True" noFile="true" title="SftpClient">
-        <Topic id="20a326ed-82f7-4586-844c-b3da4a82c2cd" visible="True" />
-        <Topic id="96751e69-1f9f-417f-8532-c8344b9e98c8" visible="True" title="SFTP Operations" />
-        <Topic id="4f283f0d-d2b7-4927-ae65-f08910756d5c" visible="True" />
-        <Topic id="9f109050-db57-43a3-a1ab-866e0de5dc10" visible="True" />
-      </Topic>
-      <Topic id="c75434ce-77e7-4bb1-b4d6-91df0323f7ac" visible="True" noFile="true" title="ScpClient">
-        <Topic id="09cd9117-2327-423a-8952-cf6d6f56b71d" visible="True" />
-      </Topic>
-      <Topic id="9c263af4-7dde-4635-a6b9-48dcbb72ba99" visible="True" noFile="true" isExpanded="true" title="NetConfClient">
-        <Topic id="9aff6aff-8781-481c-be0c-132e1391f01d" visible="True" />
-      </Topic>
-    </Topic>
-    <Topic id="8e553ec7-3a42-4bd1-9252-b9b3c957b454" visible="True" apiParentMode="InsertAsChild" title="Programming Reference" />
-  </Topic>
+<?xml version="1.0" encoding="utf-8"?>
+<Topics>
+  <Topic id="43d0362a-d340-4c2e-acc8-96d666ec2727" visible="True" isExpanded="true" title="SSH.NET Library">
+    <Topic id="6deba9ac-263a-4db7-bcc3-1a36c6aebd00" visible="True" noFile="true" isExpanded="true" isSelected="true" title="Programming Guide">
+      <Topic id="ef6ffc84-f410-4682-9366-e9fe2a73ea52" visible="True" title="Overview" />
+      <Topic id="356eeabc-aafa-4a2a-a9ab-5247b9658296" visible="True" title="Connecting to the server" tocTitle="Connection">
+        <Topic id="b7b599b2-8bc2-4276-b9a2-d73eee2426ab" visible="True" title="Using password to connect" tocTitle="Password" />
+        <Topic id="c233e412-0ea1-422f-8337-e5d1231b71e5" visible="True" title="Using private key to connects" tocTitle="Private Key" />
+        <Topic id="281ac0c3-0d6c-4bf2-ae64-db6862d6fff5" visible="True" title="Interactive" />
+      </Topic>
+      <Topic id="bb9dec7b-fe99-46f4-8ee9-92936a976730" visible="True" title="Error Handling" />
+      <Topic id="37443441-b0d5-444f-a2d0-330ad8b95995" visible="True" title="SshClient">
+        <Topic id="2337d96d-7638-438e-b980-96e87b807265" visible="True" title="Commands" />
+        <Topic id="f4ce1bdd-403f-45ec-a622-86c05a4bd913" visible="True" title="Port Forwarding" />
+        <Topic id="86bd5fce-2370-4730-b956-364885f7ed6a" visible="True" title="Shell" />
+      </Topic>
+      <Topic id="8a496881-8cba-4347-8a57-8c047fc04be9" visible="True" noFile="true" title="SftpClient">
+        <Topic id="20a326ed-82f7-4586-844c-b3da4a82c2cd" visible="True" />
+        <Topic id="96751e69-1f9f-417f-8532-c8344b9e98c8" visible="True" title="SFTP Operations" />
+        <Topic id="4f283f0d-d2b7-4927-ae65-f08910756d5c" visible="True" />
+        <Topic id="9f109050-db57-43a3-a1ab-866e0de5dc10" visible="True" />
+      </Topic>
+      <Topic id="c75434ce-77e7-4bb1-b4d6-91df0323f7ac" visible="True" noFile="true" title="ScpClient">
+        <Topic id="09cd9117-2327-423a-8952-cf6d6f56b71d" visible="True" />
+      </Topic>
+      <Topic id="9c263af4-7dde-4635-a6b9-48dcbb72ba99" visible="True" noFile="true" isExpanded="true" title="NetConfClient">
+        <Topic id="9aff6aff-8781-481c-be0c-132e1391f01d" visible="True" />
+      </Topic>
+    </Topic>
+    <Topic id="8e553ec7-3a42-4bd1-9252-b9b3c957b454" visible="True" apiParentMode="InsertAsChild" title="Programming Reference" />
+  </Topic>
 </Topics>

+ 57 - 57
src/Renci.SshNet/Documentation/SshNet.shfbproj

@@ -1,63 +1,63 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
-  <PropertyGroup>
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
+  <PropertyGroup>
     <!-- The configuration and platform will be used to determine which
          assemblies to include from solution and project documentation
-         sources -->
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <SchemaVersion>2.0</SchemaVersion>
-    <ProjectGuid>{f4b5a704-a7e7-4719-a343-ede32568762b}</ProjectGuid>
-    <SHFBSchemaVersion>1.9.5.0</SHFBSchemaVersion>
+         sources -->
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{f4b5a704-a7e7-4719-a343-ede32568762b}</ProjectGuid>
+    <SHFBSchemaVersion>1.9.5.0</SHFBSchemaVersion>
     <!-- AssemblyName, Name, and RootNamespace are not used by SHFB but Visual
-         Studio adds them anyway -->
-    <AssemblyName>Documentation</AssemblyName>
-    <RootNamespace>Documentation</RootNamespace>
-    <Name>Documentation</Name>
-    <!-- SHFB properties -->
-    <OutputPath>.\Help\</OutputPath>
-    <HtmlHelpName>SshNet.Help</HtmlHelpName>
-    <Language>en-US</Language>
-    <SyntaxFilters>Standard</SyntaxFilters>
-    <SdkLinkTarget>Blank</SdkLinkTarget>
-    <RootNamespaceContainer>False</RootNamespaceContainer>
-    <PresentationStyle>VS2010</PresentationStyle>
-    <Preliminary>False</Preliminary>
-    <NamingMethod>Guid</NamingMethod>
-    <HelpTitle>SSH .NET Client Library Documentation</HelpTitle>
-    <ContentPlacement>AboveNamespaces</ContentPlacement>
-    <DocumentationSources>
-      <DocumentationSource sourceFile="..\bin\Debug\Renci.SshNet.dll" xmlns="" />
-<DocumentationSource sourceFile="..\bin\Debug\Renci.SshNet.xml" xmlns="" /></DocumentationSources>
-    <BuildAssemblerVerbosity>OnlyWarningsAndErrors</BuildAssemblerVerbosity>
-    <HelpFileFormat>HtmlHelp1</HelpFileFormat>
-    <IndentHtml>False</IndentHtml>
-    <FrameworkVersion>.NET Framework 4.0</FrameworkVersion>
-    <KeepLogFile>True</KeepLogFile>
-    <DisableCodeBlockComponent>False</DisableCodeBlockComponent>
-    <CppCommentsFixup>False</CppCommentsFixup>
-    <CleanIntermediates>True</CleanIntermediates>
-    <ComponentConfigurations />
-  </PropertyGroup>
+         Studio adds them anyway -->
+    <AssemblyName>Documentation</AssemblyName>
+    <RootNamespace>Documentation</RootNamespace>
+    <Name>Documentation</Name>
+    <!-- SHFB properties -->
+    <OutputPath>.\Help\</OutputPath>
+    <HtmlHelpName>SshNet.Help</HtmlHelpName>
+    <Language>en-US</Language>
+    <SyntaxFilters>Standard</SyntaxFilters>
+    <SdkLinkTarget>Blank</SdkLinkTarget>
+    <RootNamespaceContainer>False</RootNamespaceContainer>
+    <PresentationStyle>VS2010</PresentationStyle>
+    <Preliminary>False</Preliminary>
+    <NamingMethod>Guid</NamingMethod>
+    <HelpTitle>SSH .NET Client Library Documentation</HelpTitle>
+    <ContentPlacement>AboveNamespaces</ContentPlacement>
+    <DocumentationSources>
+      <DocumentationSource sourceFile="..\bin\Debug\Renci.SshNet.dll" xmlns="" />
+<DocumentationSource sourceFile="..\bin\Debug\Renci.SshNet.xml" xmlns="" /></DocumentationSources>
+    <BuildAssemblerVerbosity>OnlyWarningsAndErrors</BuildAssemblerVerbosity>
+    <HelpFileFormat>HtmlHelp1</HelpFileFormat>
+    <IndentHtml>False</IndentHtml>
+    <FrameworkVersion>.NET Framework 4.0</FrameworkVersion>
+    <KeepLogFile>True</KeepLogFile>
+    <DisableCodeBlockComponent>False</DisableCodeBlockComponent>
+    <CppCommentsFixup>False</CppCommentsFixup>
+    <CleanIntermediates>True</CleanIntermediates>
+    <ComponentConfigurations />
+  </PropertyGroup>
   <!-- There are no properties for these groups.  AnyCPU needs to appear in
        order for Visual Studio to perform the build.  The others are optional
-       common platform types that may appear. -->
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|Win32' ">
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|Win32' ">
-  </PropertyGroup>
-  <!-- Import the SHFB build targets -->
-  <Import Project="$(SHFBROOT)\SandcastleHelpFileBuilder.targets" />
+       common platform types that may appear. -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|Win32' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|Win32' ">
+  </PropertyGroup>
+  <!-- Import the SHFB build targets -->
+  <Import Project="$(SHFBROOT)\SandcastleHelpFileBuilder.targets" />
 </Project>

+ 57 - 57
src/Renci.SshNet/ExpectAction.cs

@@ -1,57 +1,57 @@
-using System;
-using System.Text.RegularExpressions;
-
-namespace Renci.SshNet
-{
-    /// <summary>
-    /// Specifies behavior for expected expression
-    /// </summary>
-    public class ExpectAction
-    {
-        /// <summary>
-        /// Gets the expected regular expression.
-        /// </summary>
-        public Regex Expect { get; private set; }
-
-        /// <summary>
-        /// Gets the action to perform when expected expression is found.
-        /// </summary>
-        public Action<string> Action { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ExpectAction"/> class.
-        /// </summary>
-        /// <param name="expect">The expect regular expression.</param>
-        /// <param name="action">The action to perform.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="expect"/> or <paramref name="action"/> is null.</exception>
-        public ExpectAction(Regex expect, Action<string> action)
-        {
-            if (expect == null)
-                throw new ArgumentNullException("expect");
-
-            if (action == null)
-                throw new ArgumentNullException("action");
-
-            Expect = expect;
-            Action = action;
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ExpectAction"/> class.
-        /// </summary>
-        /// <param name="expect">The expect expression.</param>
-        /// <param name="action">The action to perform.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="expect"/> or <paramref name="action"/> is null.</exception>
-        public ExpectAction(string expect, Action<string> action)
-        {
-            if (expect == null)
-                throw new ArgumentNullException("expect");
-
-            if (action == null)
-                throw new ArgumentNullException("action");
-
-            Expect = new Regex(Regex.Escape(expect));
-            Action = action;
-        }
-    }
-}
+using System;
+using System.Text.RegularExpressions;
+
+namespace Renci.SshNet
+{
+    /// <summary>
+    /// Specifies behavior for expected expression
+    /// </summary>
+    public class ExpectAction
+    {
+        /// <summary>
+        /// Gets the expected regular expression.
+        /// </summary>
+        public Regex Expect { get; private set; }
+
+        /// <summary>
+        /// Gets the action to perform when expected expression is found.
+        /// </summary>
+        public Action<string> Action { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ExpectAction"/> class.
+        /// </summary>
+        /// <param name="expect">The expect regular expression.</param>
+        /// <param name="action">The action to perform.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="expect"/> or <paramref name="action"/> is null.</exception>
+        public ExpectAction(Regex expect, Action<string> action)
+        {
+            if (expect == null)
+                throw new ArgumentNullException("expect");
+
+            if (action == null)
+                throw new ArgumentNullException("action");
+
+            Expect = expect;
+            Action = action;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ExpectAction"/> class.
+        /// </summary>
+        /// <param name="expect">The expect expression.</param>
+        /// <param name="action">The action to perform.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="expect"/> or <paramref name="action"/> is null.</exception>
+        public ExpectAction(string expect, Action<string> action)
+        {
+            if (expect == null)
+                throw new ArgumentNullException("expect");
+
+            if (action == null)
+                throw new ArgumentNullException("action");
+
+            Expect = new Regex(Regex.Escape(expect));
+            Action = action;
+        }
+    }
+}

+ 21 - 21
src/Renci.SshNet/ExpectAsyncResult.cs

@@ -1,21 +1,21 @@
-using Renci.SshNet.Common;
-using System;
-
-namespace Renci.SshNet
-{
-    /// <summary>
-    /// Provides additional information for asynchronous command execution
-    /// </summary>
-    public class ExpectAsyncResult : AsyncResult<string>
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ExpectAsyncResult" /> class.
-        /// </summary>
-        /// <param name="asyncCallback">The async callback.</param>
-        /// <param name="state">The state.</param>
-        internal ExpectAsyncResult(AsyncCallback asyncCallback, Object state)
-            : base(asyncCallback, state)
-        {
-        }
-    }
-}
+using Renci.SshNet.Common;
+using System;
+
+namespace Renci.SshNet
+{
+    /// <summary>
+    /// Provides additional information for asynchronous command execution
+    /// </summary>
+    public class ExpectAsyncResult : AsyncResult<string>
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ExpectAsyncResult" /> class.
+        /// </summary>
+        /// <param name="asyncCallback">The async callback.</param>
+        /// <param name="state">The state.</param>
+        internal ExpectAsyncResult(AsyncCallback asyncCallback, Object state)
+            : base(asyncCallback, state)
+        {
+        }
+    }
+}

+ 174 - 174
src/Renci.SshNet/ForwardedPort.cs

@@ -1,174 +1,174 @@
-using System;
-using Renci.SshNet.Common;
-
-namespace Renci.SshNet
-{
-    /// <summary>
-    /// Base class for port forwarding functionality.
-    /// </summary>
-    public abstract class ForwardedPort : IForwardedPort
-    {
-        /// <summary>
-        /// Gets or sets the session.
-        /// </summary>
-        /// <value>
-        /// The session.
-        /// </value>
-        internal ISession Session { get; set; }
-
-        /// <summary>
-        /// The <see cref="Closing"/> event occurs as the forwarded port is being stopped.
-        /// </summary>
-        internal event EventHandler Closing;
-
-        /// <summary>
-        /// The <see cref="IForwardedPort.Closing"/> event occurs as the forwarded port is being stopped.
-        /// </summary>
-        event EventHandler IForwardedPort.Closing
-        {
-            add { Closing += value; }
-            remove { Closing -= value; }
-        }
-
-        /// <summary>
-        /// Gets or sets a value indicating whether port forwarding is started.
-        /// </summary>
-        /// <value>
-        /// <c>true</c> if port forwarding is started; otherwise, <c>false</c>.
-        /// </value>
-        public abstract bool IsStarted { get; }
-
-        /// <summary>
-        /// Occurs when an exception is thrown.
-        /// </summary>
-        public event EventHandler<ExceptionEventArgs> Exception;
-
-        /// <summary>
-        /// Occurs when a port forwarding request is received.
-        /// </summary>
-        public event EventHandler<PortForwardEventArgs> RequestReceived;
-
-        /// <summary>
-        /// Starts port forwarding.
-        /// </summary>
-        public virtual void Start()
-        {
-            CheckDisposed();
-
-            if (IsStarted)
-                throw new InvalidOperationException("Forwarded port is already started.");
-            if (Session == null)
-                throw new InvalidOperationException("Forwarded port is not added to a client.");
-            if (!Session.IsConnected)
-                throw new SshConnectionException("Client not connected.");
-
-            Session.ErrorOccured += Session_ErrorOccured;
-            StartPort();
-        }
-
-        /// <summary>
-        /// Stops port forwarding.
-        /// </summary>
-        public virtual void Stop()
-        {
-            CheckDisposed();
-
-            if (!IsStarted)
-                return;
-
-            StopPort(Session.ConnectionInfo.Timeout);
-        }
-
-        /// <summary>
-        /// Starts port forwarding.
-        /// </summary>
-        protected abstract void StartPort();
-
-        /// <summary>
-        /// Stops port forwarding, and waits for the specified timeout until all pending
-        /// requests are processed.
-        /// </summary>
-        /// <param name="timeout">The maximum amount of time to wait for pending requests to finish processing.</param>
-        protected virtual void StopPort(TimeSpan timeout)
-        {
-            RaiseClosing();
-
-            if (Session != null)
-            {
-                Session.ErrorOccured -= Session_ErrorOccured;
-            }
-        }
-
-        /// <summary>
-        /// Releases unmanaged and - optionally - managed resources
-        /// </summary>
-        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
-        protected virtual void Dispose(bool disposing)
-        {
-            if (disposing)
-            {
-                if (Session != null)
-                {
-                    Session.ErrorOccured -= Session_ErrorOccured;
-                    StopPort(Session.ConnectionInfo.Timeout);
-                    Session = null;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Ensures the current instance is not disposed.
-        /// </summary>
-        /// <exception cref="ObjectDisposedException">The current instance is disposed.</exception>
-        protected abstract void CheckDisposed();
-
-        /// <summary>
-        /// Raises <see cref="Renci.SshNet.ForwardedPort.Exception"/> event.
-        /// </summary>
-        /// <param name="exception">The exception.</param>
-        protected void RaiseExceptionEvent(Exception exception)
-        {
-            var handlers = Exception;
-            if (handlers != null)
-            {
-                handlers(this, new ExceptionEventArgs(exception));
-            }
-        }
-
-        /// <summary>
-        /// Raises <see cref="Renci.SshNet.ForwardedPort.RequestReceived"/> event.
-        /// </summary>
-        /// <param name="host">Request originator host.</param>
-        /// <param name="port">Request originator port.</param>
-        protected void RaiseRequestReceived(string host, uint port)
-        {
-            var handlers = RequestReceived;
-            if (handlers != null)
-            {
-                handlers(this, new PortForwardEventArgs(host, port));
-            }
-        }
-
-        /// <summary>
-        /// Raises the <see cref="IForwardedPort.Closing"/> event.
-        /// </summary>
-        private void RaiseClosing()
-        {
-            var handlers = Closing;
-            if (handlers != null)
-            {
-                handlers(this, EventArgs.Empty);
-            }
-        }
-
-        /// <summary>
-        /// Handles session ErrorOccured event.
-        /// </summary>
-        /// <param name="sender">The source of the event.</param>
-        /// <param name="e">The <see cref="ExceptionEventArgs"/> instance containing the event data.</param>
-        private void Session_ErrorOccured(object sender, ExceptionEventArgs e)
-        {
-            RaiseExceptionEvent(e.Exception);
-        }
-    }
-}
+using System;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet
+{
+    /// <summary>
+    /// Base class for port forwarding functionality.
+    /// </summary>
+    public abstract class ForwardedPort : IForwardedPort
+    {
+        /// <summary>
+        /// Gets or sets the session.
+        /// </summary>
+        /// <value>
+        /// The session.
+        /// </value>
+        internal ISession Session { get; set; }
+
+        /// <summary>
+        /// The <see cref="Closing"/> event occurs as the forwarded port is being stopped.
+        /// </summary>
+        internal event EventHandler Closing;
+
+        /// <summary>
+        /// The <see cref="IForwardedPort.Closing"/> event occurs as the forwarded port is being stopped.
+        /// </summary>
+        event EventHandler IForwardedPort.Closing
+        {
+            add { Closing += value; }
+            remove { Closing -= value; }
+        }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether port forwarding is started.
+        /// </summary>
+        /// <value>
+        /// <c>true</c> if port forwarding is started; otherwise, <c>false</c>.
+        /// </value>
+        public abstract bool IsStarted { get; }
+
+        /// <summary>
+        /// Occurs when an exception is thrown.
+        /// </summary>
+        public event EventHandler<ExceptionEventArgs> Exception;
+
+        /// <summary>
+        /// Occurs when a port forwarding request is received.
+        /// </summary>
+        public event EventHandler<PortForwardEventArgs> RequestReceived;
+
+        /// <summary>
+        /// Starts port forwarding.
+        /// </summary>
+        public virtual void Start()
+        {
+            CheckDisposed();
+
+            if (IsStarted)
+                throw new InvalidOperationException("Forwarded port is already started.");
+            if (Session == null)
+                throw new InvalidOperationException("Forwarded port is not added to a client.");
+            if (!Session.IsConnected)
+                throw new SshConnectionException("Client not connected.");
+
+            Session.ErrorOccured += Session_ErrorOccured;
+            StartPort();
+        }
+
+        /// <summary>
+        /// Stops port forwarding.
+        /// </summary>
+        public virtual void Stop()
+        {
+            CheckDisposed();
+
+            if (!IsStarted)
+                return;
+
+            StopPort(Session.ConnectionInfo.Timeout);
+        }
+
+        /// <summary>
+        /// Starts port forwarding.
+        /// </summary>
+        protected abstract void StartPort();
+
+        /// <summary>
+        /// Stops port forwarding, and waits for the specified timeout until all pending
+        /// requests are processed.
+        /// </summary>
+        /// <param name="timeout">The maximum amount of time to wait for pending requests to finish processing.</param>
+        protected virtual void StopPort(TimeSpan timeout)
+        {
+            RaiseClosing();
+
+            if (Session != null)
+            {
+                Session.ErrorOccured -= Session_ErrorOccured;
+            }
+        }
+
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources
+        /// </summary>
+        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                if (Session != null)
+                {
+                    Session.ErrorOccured -= Session_ErrorOccured;
+                    StopPort(Session.ConnectionInfo.Timeout);
+                    Session = null;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Ensures the current instance is not disposed.
+        /// </summary>
+        /// <exception cref="ObjectDisposedException">The current instance is disposed.</exception>
+        protected abstract void CheckDisposed();
+
+        /// <summary>
+        /// Raises <see cref="Renci.SshNet.ForwardedPort.Exception"/> event.
+        /// </summary>
+        /// <param name="exception">The exception.</param>
+        protected void RaiseExceptionEvent(Exception exception)
+        {
+            var handlers = Exception;
+            if (handlers != null)
+            {
+                handlers(this, new ExceptionEventArgs(exception));
+            }
+        }
+
+        /// <summary>
+        /// Raises <see cref="Renci.SshNet.ForwardedPort.RequestReceived"/> event.
+        /// </summary>
+        /// <param name="host">Request originator host.</param>
+        /// <param name="port">Request originator port.</param>
+        protected void RaiseRequestReceived(string host, uint port)
+        {
+            var handlers = RequestReceived;
+            if (handlers != null)
+            {
+                handlers(this, new PortForwardEventArgs(host, port));
+            }
+        }
+
+        /// <summary>
+        /// Raises the <see cref="IForwardedPort.Closing"/> event.
+        /// </summary>
+        private void RaiseClosing()
+        {
+            var handlers = Closing;
+            if (handlers != null)
+            {
+                handlers(this, EventArgs.Empty);
+            }
+        }
+
+        /// <summary>
+        /// Handles session ErrorOccured event.
+        /// </summary>
+        /// <param name="sender">The source of the event.</param>
+        /// <param name="e">The <see cref="ExceptionEventArgs"/> instance containing the event data.</param>
+        private void Session_ErrorOccured(object sender, ExceptionEventArgs e)
+        {
+            RaiseExceptionEvent(e.Exception);
+        }
+    }
+}

+ 645 - 645
src/Renci.SshNet/ForwardedPortDynamic.NET.cs

@@ -1,645 +1,645 @@
-using System;
-using System.Diagnostics;
-using System.Linq;
-using System.Text;
-using System.Net;
-using System.Net.Sockets;
-using System.Threading;
-using Renci.SshNet.Abstractions;
-using Renci.SshNet.Channels;
-using Renci.SshNet.Common;
-
-namespace Renci.SshNet
-{
-    public partial class ForwardedPortDynamic
-    {
-        private Socket _listener;
-        private int _pendingRequests;
-
-#if FEATURE_SOCKET_EAP
-        private ManualResetEvent _stoppingListener;
-#endif // FEATURE_SOCKET_EAP
-
-        partial void InternalStart()
-        {
-            var ip = IPAddress.Any;
-            if (!string.IsNullOrEmpty(BoundHost))
-            {
-                ip = DnsAbstraction.GetHostAddresses(BoundHost)[0];
-            }
-
-            var ep = new IPEndPoint(ip, (int) BoundPort);
-
-            _listener = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
-            // TODO: decide if we want to have blocking socket
-#if FEATURE_SOCKET_SETSOCKETOPTION
-            _listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
-            _listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true);
-#endif //FEATURE_SOCKET_SETSOCKETOPTION
-            _listener.Bind(ep);
-            _listener.Listen(5);
-
-            Session.ErrorOccured += Session_ErrorOccured;
-            Session.Disconnected += Session_Disconnected;
-
-            _listenerCompleted = new ManualResetEvent(false);
-
-            ThreadAbstraction.ExecuteThread(() =>
-                {
-                    try
-                    {
-#if FEATURE_SOCKET_EAP
-                        _stoppingListener = new ManualResetEvent(false);
-
-                        StartAccept();
-
-                        _stoppingListener.WaitOne();
-#elif FEATURE_SOCKET_APM
-                        while (true)
-                        {
-                            // accept new inbound connection
-                            var asyncResult = _listener.BeginAccept(AcceptCallback, _listener);
-                            // wait for the connection to be established
-                            asyncResult.AsyncWaitHandle.WaitOne();
-                        }
-                    }
-                    catch (ObjectDisposedException)
-                    {
-                        // BeginAccept will throw an ObjectDisposedException when the
-                        // socket is closed
-#elif FEATURE_SOCKET_TAP
-#error Accepting new socket connections is not implemented.
-#else
-#error Accepting new socket connections is not implemented.
-#endif
-                    }
-                    catch (Exception ex)
-                    {
-                        RaiseExceptionEvent(ex);
-                    }
-                    finally
-                    {
-                        if (Session != null)
-                        {
-                            Session.ErrorOccured -= Session_ErrorOccured;
-                            Session.Disconnected -= Session_Disconnected;
-                        }
-
-                        // mark listener stopped
-                        _listenerCompleted.Set();
-                    }
-                });
-        }
-
-        private void Session_Disconnected(object sender, EventArgs e)
-        {
-            StopListener();
-        }
-
-        private void Session_ErrorOccured(object sender, ExceptionEventArgs e)
-        {
-            StopListener();
-        }
-
-#if FEATURE_SOCKET_EAP
-        private void StartAccept()
-        {
-            var args = new SocketAsyncEventArgs();
-            args.Completed += AcceptCompleted;
-
-            if (!_listener.AcceptAsync(args))
-            {
-                AcceptCompleted(null, args);
-            }
-        }
-
-        private void AcceptCompleted(object sender, SocketAsyncEventArgs acceptAsyncEventArgs)
-        {
-            if (acceptAsyncEventArgs.SocketError != SocketError.Success)
-            {
-                StartAccept();
-                acceptAsyncEventArgs.AcceptSocket.Dispose();
-                return;
-            }
-
-            StartAccept();
-
-            ProcessAccept(acceptAsyncEventArgs.AcceptSocket);
-        }
-#elif FEATURE_SOCKET_APM
-        private void AcceptCallback(IAsyncResult ar)
-        {
-            // Get the socket that handles the client request
-            var serverSocket = (Socket) ar.AsyncState;
-
-            Socket clientSocket;
-
-            try
-            {
-                clientSocket = serverSocket.EndAccept(ar);
-            }
-            catch (ObjectDisposedException)
-            {
-                // when the socket is closed, an ObjectDisposedException is thrown
-                // by Socket.EndAccept(IAsyncResult)
-                return;
-            }
-
-            ProcessAccept(clientSocket);
-        }
-#endif
-
-        private void ProcessAccept(Socket remoteSocket)
-        {
-            Interlocked.Increment(ref _pendingRequests);
-
-#if DEBUG_GERT
-            Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | " + remoteSocket.RemoteEndPoint + " | ForwardedPortDynamic.ProcessAccept | " + DateTime.Now.ToString("hh:mm:ss.fff"));
-#endif // DEBUG_GERT
-
-            try
-            {
-#if FEATURE_SOCKET_SETSOCKETOPTION
-                remoteSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
-                remoteSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true);
-#endif //FEATURE_SOCKET_SETSOCKETOPTION
-
-                using (var channel = Session.CreateChannelDirectTcpip())
-                {
-                    channel.Exception += Channel_Exception;
-
-                    try
-                    {
-                        if (!HandleSocks(channel, remoteSocket, Session.ConnectionInfo.Timeout))
-                        {
-                            CloseSocket(remoteSocket);
-                            return;
-                        }
-
-                        // start receiving from client socket (and sending to server)
-                        channel.Bind();
-                    }
-#if DEBUG_GERT
-                    catch (SocketException ex)
-                    {
-                        Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | " + ex.SocketErrorCode + " | " + DateTime.Now.ToString("hh:mm:ss.fff") + " | " + ex);
-                    }
-#endif // DEBUG_GERT
-                    finally
-                    {
-                        channel.Close();
-                    }
-                }
-            }
-            catch (SocketException ex)
-            {
-                // ignore exception thrown by interrupting the blocking receive as part of closing
-                // the forwarded port
-                if (ex.SocketErrorCode != SocketError.Interrupted)
-                {
-#if DEBUG_GERT
-                    RaiseExceptionEvent(new Exception("ID: " + Thread.CurrentThread.ManagedThreadId, ex));
-#else
-                    RaiseExceptionEvent(ex);
-#endif // DEBUG_GERT
-                }
-                CloseSocket(remoteSocket);
-            }
-            catch (Exception exp)
-            {
-#if DEBUG_GERT
-                Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | " + exp + " | " + DateTime.Now.ToString("hh:mm:ss.fff"));
-#endif // DEBUG_GERT
-                RaiseExceptionEvent(exp);
-                CloseSocket(remoteSocket);
-            }
-            finally
-            {
-                Interlocked.Decrement(ref _pendingRequests);
-            }
-        }
-
-        private bool HandleSocks(IChannelDirectTcpip channel, Socket remoteSocket, TimeSpan timeout)
-        {
-            // create eventhandler which is to be invoked to interrupt a blocking receive
-            // when we're closing the forwarded port
-            EventHandler closeClientSocket = (_, args) => CloseSocket(remoteSocket);
-
-            Closing += closeClientSocket;
-
-            try
-            {
-#if DEBUG_GERT
-                Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | Before ReadByte for version | " + DateTime.Now.ToString("hh:mm:ss.fff"));
-#endif // DEBUG_GERT
-
-                var version = SocketAbstraction.ReadByte(remoteSocket, timeout);
-                if (version == -1)
-                {
-                    return false;
-                }
-
-#if DEBUG_GERT
-                Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | After ReadByte for version | " + DateTime.Now.ToString("hh:mm:ss.fff"));
-#endif // DEBUG_GERT
-
-                if (version == 4)
-                {
-                    return HandleSocks4(remoteSocket, channel, timeout);
-                }
-                else if (version == 5)
-                {
-                    return HandleSocks5(remoteSocket, channel, timeout);
-                }
-                else
-                {
-                    throw new NotSupportedException(string.Format("SOCKS version {0} is not supported.", version));
-                }
-            }
-            finally
-            {
-                // interrupt of blocking receive is now handled by channel (SOCKS4 and SOCKS5)
-                // or no longer necessary
-                Closing -= closeClientSocket;
-            }
-
-        }
-
-        private static void CloseSocket(Socket socket)
-        {
-#if DEBUG_GERT
-            Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | ForwardedPortDynamic.CloseSocket | " + DateTime.Now.ToString("hh:mm:ss.fff"));
-#endif // DEBUG_GERT
-
-            if (socket.Connected)
-            {
-                socket.Shutdown(SocketShutdown.Both);
-                socket.Dispose();
-            }
-        }
-
-        partial void StopListener()
-        {
-            //  if the port is not started then there's nothing to stop
-            if (!IsStarted)
-                return;
-
-#if FEATURE_SOCKET_EAP
-            _stoppingListener.Set();
-#endif // FEATURE_SOCKET_EAP
-
-            // close listener socket
-            _listener.Dispose();
-            // wait for listener loop to finish
-            _listenerCompleted.WaitOne();
-        }
-
-        /// <summary>
-        /// Waits for pending requests to finish, and channels to close.
-        /// </summary>
-        /// <param name="timeout">The maximum time to wait for the forwarded port to stop.</param>
-        partial void InternalStop(TimeSpan timeout)
-        {
-            if (timeout == TimeSpan.Zero)
-                return;
-
-            var stopWatch = new Stopwatch();
-            stopWatch.Start();
-
-            // break out of loop when one of the following conditions are met:
-            // * the forwarded port is restarted
-            // * all pending requests have been processed and corresponding channel are closed
-            // * the specified timeout has elapsed
-            while (!IsStarted)
-            {
-                // break out of loop when all pending requests have been processed
-                if (Interlocked.CompareExchange(ref _pendingRequests, 0, 0) == 0)
-                    break;
-                // break out of loop when specified timeout has elapsed
-                if (stopWatch.Elapsed >= timeout && timeout != SshNet.Session.InfiniteTimeSpan)
-                    break;
-                // give channels time to process pending requests
-                ThreadAbstraction.Sleep(50);
-            }
-
-            stopWatch.Stop();
-        }
-
-        partial void InternalDispose(bool disposing)
-        {
-            if (disposing)
-            {
-                if (_listener != null)
-                {
-                    _listener.Dispose();
-                    _listener = null;
-                }
-
-#if FEATURE_SOCKET_EAP
-                if (_stoppingListener != null)
-                {
-                    _stoppingListener.Dispose();
-                    _stoppingListener = null;
-                }
-#endif // FEATURE_SOCKET_EAP
-            }
-        }
-
-        private bool HandleSocks4(Socket socket, IChannelDirectTcpip channel, TimeSpan timeout)
-        {
-            var commandCode = SocketAbstraction.ReadByte(socket, timeout);
-            if (commandCode == 0)
-            {
-                // SOCKS client closed connection
-                return false;
-            }
-
-            //  TODO:   See what need to be done depends on the code
-
-            var portBuffer = new byte[2];
-            if (SocketAbstraction.Read(socket, portBuffer, 0, portBuffer.Length, timeout) == 0)
-            {
-                // SOCKS client closed connection
-                return false;
-            }
-
-            var port = (uint)(portBuffer[0] * 256 + portBuffer[1]);
-
-            var ipBuffer = new byte[4];
-            if (SocketAbstraction.Read(socket, ipBuffer, 0, ipBuffer.Length, timeout) == 0)
-            {
-                // SOCKS client closed connection
-                return false;
-            }
-
-            var ipAddress = new IPAddress(ipBuffer);
-
-            var username = ReadString(socket, timeout);
-            if (username == null)
-            {
-                // SOCKS client closed connection
-                return false;
-            }
-
-            var host = ipAddress.ToString();
-
-            RaiseRequestReceived(host, port);
-
-            channel.Open(host, port, this, socket);
-
-            SocketAbstraction.SendByte(socket, 0x00);
-
-            if (channel.IsOpen)
-            {
-                SocketAbstraction.SendByte(socket, 0x5a);
-                SocketAbstraction.Send(socket, portBuffer, 0, portBuffer.Length);
-                SocketAbstraction.Send(socket, ipBuffer, 0, ipBuffer.Length);
-                return true;
-            }
-
-            // signal that request was rejected or failed
-            SocketAbstraction.SendByte(socket, 0x5b);
-            return false;
-        }
-
-        private bool HandleSocks5(Socket socket, IChannelDirectTcpip channel, TimeSpan timeout)
-        {
-#if DEBUG_GERT
-            Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " |  Handling Socks5: " + socket.LocalEndPoint +  " | " + socket.RemoteEndPoint + " | " + DateTime.Now.ToString("hh:mm:ss.fff"));
-#endif // DEBUG_GERT
-
-            var authenticationMethodsCount = SocketAbstraction.ReadByte(socket, timeout);
-            if (authenticationMethodsCount == -1)
-            {
-                // SOCKS client closed connection
-                return false;
-            }
-
-#if DEBUG_GERT
-            Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " |  After ReadByte for authenticationMethodsCount | " + DateTime.Now.ToString("hh:mm:ss.fff"));
-#endif // DEBUG_GERT
-
-            var authenticationMethods = new byte[authenticationMethodsCount];
-            if (SocketAbstraction.Read(socket, authenticationMethods, 0, authenticationMethods.Length, timeout) == 0)
-            {
-                // SOCKS client closed connection
-                return false;
-            }
-
-#if DEBUG_GERT
-            Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " |  After Read for authenticationMethods | " + DateTime.Now.ToString("hh:mm:ss.fff"));
-#endif // DEBUG_GERT
-
-            if (authenticationMethods.Min() == 0)
-            {
-                // no user authentication is one of the authentication methods supported
-                // by the SOCKS client
-                SocketAbstraction.Send(socket, new byte[] { 0x05, 0x00 }, 0, 2);
-
-#if DEBUG_GERT
-                Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " |  After Send for authenticationMethods 0 | " + DateTime.Now.ToString("hh:mm:ss.fff"));
-#endif // DEBUG_GERT
-            }
-            else
-            {
-                // the SOCKS client requires authentication, which we currently do not support
-                SocketAbstraction.Send(socket, new byte[] { 0x05, 0xFF }, 0, 2);
-
-                // we continue business as usual but expect the client to close the connection
-                // so one of the subsequent reads should return -1 signaling that the client
-                // has effectively closed the connection
-#if DEBUG_GERT
-                Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " |  After Send for authenticationMethods 2 | " + DateTime.Now.ToString("hh:mm:ss.fff"));
-#endif // DEBUG_GERT
-            }
-
-            var version = SocketAbstraction.ReadByte(socket, timeout);
-            if (version == -1)
-            {
-                // SOCKS client closed connection
-                return false;
-            }
-
-            if (version != 5)
-                throw new ProxyException("SOCKS5: Version 5 is expected.");
-
-            var commandCode = SocketAbstraction.ReadByte(socket, timeout);
-            if (commandCode == -1)
-            {
-                // SOCKS client closed connection
-                return false;
-            }
-
-            var reserved = SocketAbstraction.ReadByte(socket, timeout);
-            if (reserved == -1)
-            {
-                // SOCKS client closed connection
-                return false;
-            }
-
-            if (reserved != 0)
-            {
-                throw new ProxyException("SOCKS5: 0 is expected for reserved byte.");
-            }
-
-            var addressType = SocketAbstraction.ReadByte(socket, timeout);
-            if (addressType == -1)
-            {
-                // SOCKS client closed connection
-                return false;
-            }
-
-            IPAddress ipAddress;
-            byte[] addressBuffer;
-            switch (addressType)
-            {
-                case 0x01:
-                    {
-                        addressBuffer = new byte[4];
-                        if (SocketAbstraction.Read(socket, addressBuffer, 0, 4, timeout) == 0)
-                        {
-                            // SOCKS client closed connection
-                            return false;
-                        }
-
-                        ipAddress = new IPAddress(addressBuffer);
-                    }
-                    break;
-                case 0x03:
-                    {
-                        var length = SocketAbstraction.ReadByte(socket, timeout);
-                        addressBuffer = new byte[length];
-                        if (SocketAbstraction.Read(socket, addressBuffer, 0, addressBuffer.Length, timeout) == 0)
-                        {
-                            // SOCKS client closed connection
-                            return false;
-                        }
-
-                        ipAddress = IPAddress.Parse(SshData.Ascii.GetString(addressBuffer));
-
-                        //var hostName = new Common.ASCIIEncoding().GetString(addressBuffer);
-
-                        //ipAddress = Dns.GetHostEntry(hostName).AddressList[0];
-                    }
-                    break;
-                case 0x04:
-                    {
-                        addressBuffer = new byte[16];
-                        if (SocketAbstraction.Read(socket, addressBuffer, 0, 16, timeout) == 0)
-                        {
-                            // SOCKS client closed connection
-                            return false;
-                        }
-
-                        ipAddress = new IPAddress(addressBuffer);
-                    }
-                    break;
-                default:
-                    throw new ProxyException(string.Format("SOCKS5: Address type '{0}' is not supported.", addressType));
-            }
-
-            var portBuffer = new byte[2];
-            if (SocketAbstraction.Read(socket, portBuffer, 0, portBuffer.Length, timeout) == 0)
-            {
-                // SOCKS client closed connection
-                return false;
-            }
-
-            var port = (uint)(portBuffer[0] * 256 + portBuffer[1]);
-            var host = ipAddress.ToString();
-
-            RaiseRequestReceived(host, port);
-
-#if DEBUG_GERT
-            Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " |  Before channel open | " + DateTime.Now.ToString("hh:mm:ss.fff"));
-
-            var stopWatch = new Stopwatch();
-            stopWatch.Start();
-#endif // DEBUG_GERT
-
-            channel.Open(host, port, this, socket);
-
-#if DEBUG_GERT
-            stopWatch.Stop();
-
-            Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " |  After channel open | " + DateTime.Now.ToString("hh:mm:ss.fff") + " => " + stopWatch.ElapsedMilliseconds);
-#endif // DEBUG_GERT
-
-            SocketAbstraction.SendByte(socket, 0x05);
-
-
-            if (channel.IsOpen)
-            {
-                SocketAbstraction.SendByte(socket, 0x00);
-            }
-            else
-            {
-                SocketAbstraction.SendByte(socket, 0x01);
-            }
-
-            // reserved
-            SocketAbstraction.SendByte(socket, 0x00);
-
-            if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
-            {
-                SocketAbstraction.SendByte(socket, 0x01);
-            }
-            else if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
-            {
-                SocketAbstraction.SendByte(socket, 0x04);
-            }
-            else
-            {
-                throw new NotSupportedException("Not supported address family.");
-            }
-
-            var addressBytes = ipAddress.GetAddressBytes();
-            SocketAbstraction.Send(socket, addressBytes, 0, addressBytes.Length);
-            SocketAbstraction.Send(socket, portBuffer, 0, portBuffer.Length);
-
-            return true;
-        }
-
-        private void Channel_Exception(object sender, ExceptionEventArgs e)
-        {
-#if DEBUG_GERT
-            Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | Channel_Exception | " +
-                              DateTime.Now.ToString("hh:mm:ss.fff"));
-#endif // DEBUG_GERT
-            RaiseExceptionEvent(e.Exception);
-        }
-
-        /// <summary>
-        /// Reads a null terminated string from a socket.
-        /// </summary>
-        /// <param name="socket">The <see cref="Socket"/> to read from.</param>
-        /// <param name="timeout">The timeout to apply to individual reads.</param>
-        /// <returns>
-        /// The <see cref="string"/> read, or <c>null</c> when the socket was closed.
-        /// </returns>
-        private static string ReadString(Socket socket, TimeSpan timeout)
-        {
-            var text = new StringBuilder();
-            var buffer = new byte[1];
-            while (true)
-            {
-                if (SocketAbstraction.Read(socket, buffer, 0, 1, timeout) == 0)
-                {
-                    // SOCKS client closed connection
-                    return null;
-                }
-
-                var byteRead = buffer[0];
-                if (byteRead == 0)
-                {
-                    // end of the string
-                    break;
-                }
-
-                var c = (char) byteRead;
-                text.Append(c);
-            }
-            return text.ToString();
-        }
-    }
-}
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+using Renci.SshNet.Abstractions;
+using Renci.SshNet.Channels;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet
+{
+    public partial class ForwardedPortDynamic
+    {
+        private Socket _listener;
+        private int _pendingRequests;
+
+#if FEATURE_SOCKET_EAP
+        private ManualResetEvent _stoppingListener;
+#endif // FEATURE_SOCKET_EAP
+
+        partial void InternalStart()
+        {
+            var ip = IPAddress.Any;
+            if (!string.IsNullOrEmpty(BoundHost))
+            {
+                ip = DnsAbstraction.GetHostAddresses(BoundHost)[0];
+            }
+
+            var ep = new IPEndPoint(ip, (int) BoundPort);
+
+            _listener = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
+            // TODO: decide if we want to have blocking socket
+#if FEATURE_SOCKET_SETSOCKETOPTION
+            _listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
+            _listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true);
+#endif //FEATURE_SOCKET_SETSOCKETOPTION
+            _listener.Bind(ep);
+            _listener.Listen(5);
+
+            Session.ErrorOccured += Session_ErrorOccured;
+            Session.Disconnected += Session_Disconnected;
+
+            _listenerCompleted = new ManualResetEvent(false);
+
+            ThreadAbstraction.ExecuteThread(() =>
+                {
+                    try
+                    {
+#if FEATURE_SOCKET_EAP
+                        _stoppingListener = new ManualResetEvent(false);
+
+                        StartAccept();
+
+                        _stoppingListener.WaitOne();
+#elif FEATURE_SOCKET_APM
+                        while (true)
+                        {
+                            // accept new inbound connection
+                            var asyncResult = _listener.BeginAccept(AcceptCallback, _listener);
+                            // wait for the connection to be established
+                            asyncResult.AsyncWaitHandle.WaitOne();
+                        }
+                    }
+                    catch (ObjectDisposedException)
+                    {
+                        // BeginAccept will throw an ObjectDisposedException when the
+                        // socket is closed
+#elif FEATURE_SOCKET_TAP
+#error Accepting new socket connections is not implemented.
+#else
+#error Accepting new socket connections is not implemented.
+#endif
+                    }
+                    catch (Exception ex)
+                    {
+                        RaiseExceptionEvent(ex);
+                    }
+                    finally
+                    {
+                        if (Session != null)
+                        {
+                            Session.ErrorOccured -= Session_ErrorOccured;
+                            Session.Disconnected -= Session_Disconnected;
+                        }
+
+                        // mark listener stopped
+                        _listenerCompleted.Set();
+                    }
+                });
+        }
+
+        private void Session_Disconnected(object sender, EventArgs e)
+        {
+            StopListener();
+        }
+
+        private void Session_ErrorOccured(object sender, ExceptionEventArgs e)
+        {
+            StopListener();
+        }
+
+#if FEATURE_SOCKET_EAP
+        private void StartAccept()
+        {
+            var args = new SocketAsyncEventArgs();
+            args.Completed += AcceptCompleted;
+
+            if (!_listener.AcceptAsync(args))
+            {
+                AcceptCompleted(null, args);
+            }
+        }
+
+        private void AcceptCompleted(object sender, SocketAsyncEventArgs acceptAsyncEventArgs)
+        {
+            if (acceptAsyncEventArgs.SocketError != SocketError.Success)
+            {
+                StartAccept();
+                acceptAsyncEventArgs.AcceptSocket.Dispose();
+                return;
+            }
+
+            StartAccept();
+
+            ProcessAccept(acceptAsyncEventArgs.AcceptSocket);
+        }
+#elif FEATURE_SOCKET_APM
+        private void AcceptCallback(IAsyncResult ar)
+        {
+            // Get the socket that handles the client request
+            var serverSocket = (Socket) ar.AsyncState;
+
+            Socket clientSocket;
+
+            try
+            {
+                clientSocket = serverSocket.EndAccept(ar);
+            }
+            catch (ObjectDisposedException)
+            {
+                // when the socket is closed, an ObjectDisposedException is thrown
+                // by Socket.EndAccept(IAsyncResult)
+                return;
+            }
+
+            ProcessAccept(clientSocket);
+        }
+#endif
+
+        private void ProcessAccept(Socket remoteSocket)
+        {
+            Interlocked.Increment(ref _pendingRequests);
+
+#if DEBUG_GERT
+            Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | " + remoteSocket.RemoteEndPoint + " | ForwardedPortDynamic.ProcessAccept | " + DateTime.Now.ToString("hh:mm:ss.fff"));
+#endif // DEBUG_GERT
+
+            try
+            {
+#if FEATURE_SOCKET_SETSOCKETOPTION
+                remoteSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
+                remoteSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true);
+#endif //FEATURE_SOCKET_SETSOCKETOPTION
+
+                using (var channel = Session.CreateChannelDirectTcpip())
+                {
+                    channel.Exception += Channel_Exception;
+
+                    try
+                    {
+                        if (!HandleSocks(channel, remoteSocket, Session.ConnectionInfo.Timeout))
+                        {
+                            CloseSocket(remoteSocket);
+                            return;
+                        }
+
+                        // start receiving from client socket (and sending to server)
+                        channel.Bind();
+                    }
+#if DEBUG_GERT
+                    catch (SocketException ex)
+                    {
+                        Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | " + ex.SocketErrorCode + " | " + DateTime.Now.ToString("hh:mm:ss.fff") + " | " + ex);
+                    }
+#endif // DEBUG_GERT
+                    finally
+                    {
+                        channel.Close();
+                    }
+                }
+            }
+            catch (SocketException ex)
+            {
+                // ignore exception thrown by interrupting the blocking receive as part of closing
+                // the forwarded port
+                if (ex.SocketErrorCode != SocketError.Interrupted)
+                {
+#if DEBUG_GERT
+                    RaiseExceptionEvent(new Exception("ID: " + Thread.CurrentThread.ManagedThreadId, ex));
+#else
+                    RaiseExceptionEvent(ex);
+#endif // DEBUG_GERT
+                }
+                CloseSocket(remoteSocket);
+            }
+            catch (Exception exp)
+            {
+#if DEBUG_GERT
+                Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | " + exp + " | " + DateTime.Now.ToString("hh:mm:ss.fff"));
+#endif // DEBUG_GERT
+                RaiseExceptionEvent(exp);
+                CloseSocket(remoteSocket);
+            }
+            finally
+            {
+                Interlocked.Decrement(ref _pendingRequests);
+            }
+        }
+
+        private bool HandleSocks(IChannelDirectTcpip channel, Socket remoteSocket, TimeSpan timeout)
+        {
+            // create eventhandler which is to be invoked to interrupt a blocking receive
+            // when we're closing the forwarded port
+            EventHandler closeClientSocket = (_, args) => CloseSocket(remoteSocket);
+
+            Closing += closeClientSocket;
+
+            try
+            {
+#if DEBUG_GERT
+                Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | Before ReadByte for version | " + DateTime.Now.ToString("hh:mm:ss.fff"));
+#endif // DEBUG_GERT
+
+                var version = SocketAbstraction.ReadByte(remoteSocket, timeout);
+                if (version == -1)
+                {
+                    return false;
+                }
+
+#if DEBUG_GERT
+                Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | After ReadByte for version | " + DateTime.Now.ToString("hh:mm:ss.fff"));
+#endif // DEBUG_GERT
+
+                if (version == 4)
+                {
+                    return HandleSocks4(remoteSocket, channel, timeout);
+                }
+                else if (version == 5)
+                {
+                    return HandleSocks5(remoteSocket, channel, timeout);
+                }
+                else
+                {
+                    throw new NotSupportedException(string.Format("SOCKS version {0} is not supported.", version));
+                }
+            }
+            finally
+            {
+                // interrupt of blocking receive is now handled by channel (SOCKS4 and SOCKS5)
+                // or no longer necessary
+                Closing -= closeClientSocket;
+            }
+
+        }
+
+        private static void CloseSocket(Socket socket)
+        {
+#if DEBUG_GERT
+            Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | ForwardedPortDynamic.CloseSocket | " + DateTime.Now.ToString("hh:mm:ss.fff"));
+#endif // DEBUG_GERT
+
+            if (socket.Connected)
+            {
+                socket.Shutdown(SocketShutdown.Both);
+                socket.Dispose();
+            }
+        }
+
+        partial void StopListener()
+        {
+            //  if the port is not started then there's nothing to stop
+            if (!IsStarted)
+                return;
+
+#if FEATURE_SOCKET_EAP
+            _stoppingListener.Set();
+#endif // FEATURE_SOCKET_EAP
+
+            // close listener socket
+            _listener.Dispose();
+            // wait for listener loop to finish
+            _listenerCompleted.WaitOne();
+        }
+
+        /// <summary>
+        /// Waits for pending requests to finish, and channels to close.
+        /// </summary>
+        /// <param name="timeout">The maximum time to wait for the forwarded port to stop.</param>
+        partial void InternalStop(TimeSpan timeout)
+        {
+            if (timeout == TimeSpan.Zero)
+                return;
+
+            var stopWatch = new Stopwatch();
+            stopWatch.Start();
+
+            // break out of loop when one of the following conditions are met:
+            // * the forwarded port is restarted
+            // * all pending requests have been processed and corresponding channel are closed
+            // * the specified timeout has elapsed
+            while (!IsStarted)
+            {
+                // break out of loop when all pending requests have been processed
+                if (Interlocked.CompareExchange(ref _pendingRequests, 0, 0) == 0)
+                    break;
+                // break out of loop when specified timeout has elapsed
+                if (stopWatch.Elapsed >= timeout && timeout != SshNet.Session.InfiniteTimeSpan)
+                    break;
+                // give channels time to process pending requests
+                ThreadAbstraction.Sleep(50);
+            }
+
+            stopWatch.Stop();
+        }
+
+        partial void InternalDispose(bool disposing)
+        {
+            if (disposing)
+            {
+                if (_listener != null)
+                {
+                    _listener.Dispose();
+                    _listener = null;
+                }
+
+#if FEATURE_SOCKET_EAP
+                if (_stoppingListener != null)
+                {
+                    _stoppingListener.Dispose();
+                    _stoppingListener = null;
+                }
+#endif // FEATURE_SOCKET_EAP
+            }
+        }
+
+        private bool HandleSocks4(Socket socket, IChannelDirectTcpip channel, TimeSpan timeout)
+        {
+            var commandCode = SocketAbstraction.ReadByte(socket, timeout);
+            if (commandCode == 0)
+            {
+                // SOCKS client closed connection
+                return false;
+            }
+
+            //  TODO:   See what need to be done depends on the code
+
+            var portBuffer = new byte[2];
+            if (SocketAbstraction.Read(socket, portBuffer, 0, portBuffer.Length, timeout) == 0)
+            {
+                // SOCKS client closed connection
+                return false;
+            }
+
+            var port = (uint)(portBuffer[0] * 256 + portBuffer[1]);
+
+            var ipBuffer = new byte[4];
+            if (SocketAbstraction.Read(socket, ipBuffer, 0, ipBuffer.Length, timeout) == 0)
+            {
+                // SOCKS client closed connection
+                return false;
+            }
+
+            var ipAddress = new IPAddress(ipBuffer);
+
+            var username = ReadString(socket, timeout);
+            if (username == null)
+            {
+                // SOCKS client closed connection
+                return false;
+            }
+
+            var host = ipAddress.ToString();
+
+            RaiseRequestReceived(host, port);
+
+            channel.Open(host, port, this, socket);
+
+            SocketAbstraction.SendByte(socket, 0x00);
+
+            if (channel.IsOpen)
+            {
+                SocketAbstraction.SendByte(socket, 0x5a);
+                SocketAbstraction.Send(socket, portBuffer, 0, portBuffer.Length);
+                SocketAbstraction.Send(socket, ipBuffer, 0, ipBuffer.Length);
+                return true;
+            }
+
+            // signal that request was rejected or failed
+            SocketAbstraction.SendByte(socket, 0x5b);
+            return false;
+        }
+
+        private bool HandleSocks5(Socket socket, IChannelDirectTcpip channel, TimeSpan timeout)
+        {
+#if DEBUG_GERT
+            Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " |  Handling Socks5: " + socket.LocalEndPoint +  " | " + socket.RemoteEndPoint + " | " + DateTime.Now.ToString("hh:mm:ss.fff"));
+#endif // DEBUG_GERT
+
+            var authenticationMethodsCount = SocketAbstraction.ReadByte(socket, timeout);
+            if (authenticationMethodsCount == -1)
+            {
+                // SOCKS client closed connection
+                return false;
+            }
+
+#if DEBUG_GERT
+            Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " |  After ReadByte for authenticationMethodsCount | " + DateTime.Now.ToString("hh:mm:ss.fff"));
+#endif // DEBUG_GERT
+
+            var authenticationMethods = new byte[authenticationMethodsCount];
+            if (SocketAbstraction.Read(socket, authenticationMethods, 0, authenticationMethods.Length, timeout) == 0)
+            {
+                // SOCKS client closed connection
+                return false;
+            }
+
+#if DEBUG_GERT
+            Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " |  After Read for authenticationMethods | " + DateTime.Now.ToString("hh:mm:ss.fff"));
+#endif // DEBUG_GERT
+
+            if (authenticationMethods.Min() == 0)
+            {
+                // no user authentication is one of the authentication methods supported
+                // by the SOCKS client
+                SocketAbstraction.Send(socket, new byte[] { 0x05, 0x00 }, 0, 2);
+
+#if DEBUG_GERT
+                Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " |  After Send for authenticationMethods 0 | " + DateTime.Now.ToString("hh:mm:ss.fff"));
+#endif // DEBUG_GERT
+            }
+            else
+            {
+                // the SOCKS client requires authentication, which we currently do not support
+                SocketAbstraction.Send(socket, new byte[] { 0x05, 0xFF }, 0, 2);
+
+                // we continue business as usual but expect the client to close the connection
+                // so one of the subsequent reads should return -1 signaling that the client
+                // has effectively closed the connection
+#if DEBUG_GERT
+                Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " |  After Send for authenticationMethods 2 | " + DateTime.Now.ToString("hh:mm:ss.fff"));
+#endif // DEBUG_GERT
+            }
+
+            var version = SocketAbstraction.ReadByte(socket, timeout);
+            if (version == -1)
+            {
+                // SOCKS client closed connection
+                return false;
+            }
+
+            if (version != 5)
+                throw new ProxyException("SOCKS5: Version 5 is expected.");
+
+            var commandCode = SocketAbstraction.ReadByte(socket, timeout);
+            if (commandCode == -1)
+            {
+                // SOCKS client closed connection
+                return false;
+            }
+
+            var reserved = SocketAbstraction.ReadByte(socket, timeout);
+            if (reserved == -1)
+            {
+                // SOCKS client closed connection
+                return false;
+            }
+
+            if (reserved != 0)
+            {
+                throw new ProxyException("SOCKS5: 0 is expected for reserved byte.");
+            }
+
+            var addressType = SocketAbstraction.ReadByte(socket, timeout);
+            if (addressType == -1)
+            {
+                // SOCKS client closed connection
+                return false;
+            }
+
+            IPAddress ipAddress;
+            byte[] addressBuffer;
+            switch (addressType)
+            {
+                case 0x01:
+                    {
+                        addressBuffer = new byte[4];
+                        if (SocketAbstraction.Read(socket, addressBuffer, 0, 4, timeout) == 0)
+                        {
+                            // SOCKS client closed connection
+                            return false;
+                        }
+
+                        ipAddress = new IPAddress(addressBuffer);
+                    }
+                    break;
+                case 0x03:
+                    {
+                        var length = SocketAbstraction.ReadByte(socket, timeout);
+                        addressBuffer = new byte[length];
+                        if (SocketAbstraction.Read(socket, addressBuffer, 0, addressBuffer.Length, timeout) == 0)
+                        {
+                            // SOCKS client closed connection
+                            return false;
+                        }
+
+                        ipAddress = IPAddress.Parse(SshData.Ascii.GetString(addressBuffer));
+
+                        //var hostName = new Common.ASCIIEncoding().GetString(addressBuffer);
+
+                        //ipAddress = Dns.GetHostEntry(hostName).AddressList[0];
+                    }
+                    break;
+                case 0x04:
+                    {
+                        addressBuffer = new byte[16];
+                        if (SocketAbstraction.Read(socket, addressBuffer, 0, 16, timeout) == 0)
+                        {
+                            // SOCKS client closed connection
+                            return false;
+                        }
+
+                        ipAddress = new IPAddress(addressBuffer);
+                    }
+                    break;
+                default:
+                    throw new ProxyException(string.Format("SOCKS5: Address type '{0}' is not supported.", addressType));
+            }
+
+            var portBuffer = new byte[2];
+            if (SocketAbstraction.Read(socket, portBuffer, 0, portBuffer.Length, timeout) == 0)
+            {
+                // SOCKS client closed connection
+                return false;
+            }
+
+            var port = (uint)(portBuffer[0] * 256 + portBuffer[1]);
+            var host = ipAddress.ToString();
+
+            RaiseRequestReceived(host, port);
+
+#if DEBUG_GERT
+            Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " |  Before channel open | " + DateTime.Now.ToString("hh:mm:ss.fff"));
+
+            var stopWatch = new Stopwatch();
+            stopWatch.Start();
+#endif // DEBUG_GERT
+
+            channel.Open(host, port, this, socket);
+
+#if DEBUG_GERT
+            stopWatch.Stop();
+
+            Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " |  After channel open | " + DateTime.Now.ToString("hh:mm:ss.fff") + " => " + stopWatch.ElapsedMilliseconds);
+#endif // DEBUG_GERT
+
+            SocketAbstraction.SendByte(socket, 0x05);
+
+
+            if (channel.IsOpen)
+            {
+                SocketAbstraction.SendByte(socket, 0x00);
+            }
+            else
+            {
+                SocketAbstraction.SendByte(socket, 0x01);
+            }
+
+            // reserved
+            SocketAbstraction.SendByte(socket, 0x00);
+
+            if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
+            {
+                SocketAbstraction.SendByte(socket, 0x01);
+            }
+            else if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
+            {
+                SocketAbstraction.SendByte(socket, 0x04);
+            }
+            else
+            {
+                throw new NotSupportedException("Not supported address family.");
+            }
+
+            var addressBytes = ipAddress.GetAddressBytes();
+            SocketAbstraction.Send(socket, addressBytes, 0, addressBytes.Length);
+            SocketAbstraction.Send(socket, portBuffer, 0, portBuffer.Length);
+
+            return true;
+        }
+
+        private void Channel_Exception(object sender, ExceptionEventArgs e)
+        {
+#if DEBUG_GERT
+            Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | Channel_Exception | " +
+                              DateTime.Now.ToString("hh:mm:ss.fff"));
+#endif // DEBUG_GERT
+            RaiseExceptionEvent(e.Exception);
+        }
+
+        /// <summary>
+        /// Reads a null terminated string from a socket.
+        /// </summary>
+        /// <param name="socket">The <see cref="Socket"/> to read from.</param>
+        /// <param name="timeout">The timeout to apply to individual reads.</param>
+        /// <returns>
+        /// The <see cref="string"/> read, or <c>null</c> when the socket was closed.
+        /// </returns>
+        private static string ReadString(Socket socket, TimeSpan timeout)
+        {
+            var text = new StringBuilder();
+            var buffer = new byte[1];
+            while (true)
+            {
+                if (SocketAbstraction.Read(socket, buffer, 0, 1, timeout) == 0)
+                {
+                    // SOCKS client closed connection
+                    return null;
+                }
+
+                var byteRead = buffer[0];
+                if (byteRead == 0)
+                {
+                    // end of the string
+                    break;
+                }
+
+                var c = (char) byteRead;
+                text.Append(c);
+            }
+            return text.ToString();
+        }
+    }
+}

+ 163 - 163
src/Renci.SshNet/ForwardedPortDynamic.cs

@@ -1,163 +1,163 @@
-using System;
-using System.Threading;
-
-namespace Renci.SshNet
-{
-    /// <summary>
-    /// Provides functionality for forwarding connections from the client to destination servers via the SSH server,
-    /// also known as dynamic port forwarding.
-    /// </summary>
-    public partial class ForwardedPortDynamic : ForwardedPort
-    {
-        private EventWaitHandle _listenerCompleted;
-
-        /// <summary>
-        /// Gets the bound host.
-        /// </summary>
-        public string BoundHost { get; private set; }
-
-        /// <summary>
-        /// Gets the bound port.
-        /// </summary>
-        public uint BoundPort { get; private set; }
-
-        /// <summary>
-        /// Gets or sets a value indicating whether port forwarding is started.
-        /// </summary>
-        /// <value>
-        /// <c>true</c> if port forwarding is started; otherwise, <c>false</c>.
-        /// </value>
-        public override bool IsStarted
-        {
-            get { return _listenerCompleted != null && !_listenerCompleted.WaitOne(0); }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ForwardedPortDynamic"/> class.
-        /// </summary>
-        /// <param name="port">The port.</param>
-        public ForwardedPortDynamic(uint port)
-            : this(string.Empty, port)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ForwardedPortDynamic"/> class.
-        /// </summary>
-        /// <param name="host">The host.</param>
-        /// <param name="port">The port.</param>
-        public ForwardedPortDynamic(string host, uint port)
-        {
-            BoundHost = host;
-            BoundPort = port;
-        }
-
-        /// <summary>
-        /// Starts local port forwarding.
-        /// </summary>
-        protected override void StartPort()
-        {
-            InternalStart();
-        }
-
-        /// <summary>
-        /// Stops local port forwarding, and waits for the specified timeout until all pending
-        /// requests are processed.
-        /// </summary>
-        /// <param name="timeout">The maximum amount of time to wait for pending requests to finish processing.</param>
-        protected override void StopPort(TimeSpan timeout)
-        {
-            if (IsStarted)
-            {
-                // prevent new requests from getting processed before we signal existing
-                // channels that the port is closing
-                StopListener();
-                // signal existing channels that the port is closing
-                base.StopPort(timeout);
-            }
-            // wait for open channels to close
-            InternalStop(timeout);
-        }
-
-        /// <summary>
-        /// Ensures the current instance is not disposed.
-        /// </summary>
-        /// <exception cref="ObjectDisposedException">The current instance is disposed.</exception>
-        protected override void CheckDisposed()
-        {
-            if (_isDisposed)
-                throw new ObjectDisposedException(GetType().FullName);
-        }
-
-        partial void InternalStart();
-
-        /// <summary>
-        /// Stops the listener.
-        /// </summary>
-        partial void StopListener();
-
-        /// <summary>
-        /// Waits for pending requests to finish, and channels to close.
-        /// </summary>
-        /// <param name="timeout">The maximum time to wait for the forwarded port to stop.</param>
-        partial void InternalStop(TimeSpan timeout);
-
-        #region IDisposable Members
-
-        /// <summary>
-        /// Holds a value indicating whether the current instance is disposed.
-        /// </summary>
-        /// <value>
-        /// <c>true</c> if the current instance is disposed; otherwise, <c>false</c>.
-        /// </value>
-        private bool _isDisposed;
-
-        /// <summary>
-        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
-        /// </summary>
-        public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
-
-        partial void InternalDispose(bool disposing);
-
-        /// <summary>
-        /// Releases unmanaged and - optionally - managed resources
-        /// </summary>
-        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
-        protected override void Dispose(bool disposing)
-        {
-            if (_isDisposed)
-                return;
-
-            base.Dispose(disposing);
-
-            if (disposing)
-            {
-                var listenerCompleted = _listenerCompleted;
-                if (listenerCompleted != null)
-                {
-                    listenerCompleted.Dispose();
-                    _listenerCompleted = null;
-                }
-            }
-
-            InternalDispose(disposing);
-
-            _isDisposed = true;
-        }
-
-        /// <summary>
-        /// Releases unmanaged resources and performs other cleanup operations before the
-        /// <see cref="ForwardedPortDynamic"/> is reclaimed by garbage collection.
-        /// </summary>
-        ~ForwardedPortDynamic()
-        {
-            Dispose(false);
-        }
-
-        #endregion
-    }
-}
+using System;
+using System.Threading;
+
+namespace Renci.SshNet
+{
+    /// <summary>
+    /// Provides functionality for forwarding connections from the client to destination servers via the SSH server,
+    /// also known as dynamic port forwarding.
+    /// </summary>
+    public partial class ForwardedPortDynamic : ForwardedPort
+    {
+        private EventWaitHandle _listenerCompleted;
+
+        /// <summary>
+        /// Gets the bound host.
+        /// </summary>
+        public string BoundHost { get; private set; }
+
+        /// <summary>
+        /// Gets the bound port.
+        /// </summary>
+        public uint BoundPort { get; private set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether port forwarding is started.
+        /// </summary>
+        /// <value>
+        /// <c>true</c> if port forwarding is started; otherwise, <c>false</c>.
+        /// </value>
+        public override bool IsStarted
+        {
+            get { return _listenerCompleted != null && !_listenerCompleted.WaitOne(0); }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ForwardedPortDynamic"/> class.
+        /// </summary>
+        /// <param name="port">The port.</param>
+        public ForwardedPortDynamic(uint port)
+            : this(string.Empty, port)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ForwardedPortDynamic"/> class.
+        /// </summary>
+        /// <param name="host">The host.</param>
+        /// <param name="port">The port.</param>
+        public ForwardedPortDynamic(string host, uint port)
+        {
+            BoundHost = host;
+            BoundPort = port;
+        }
+
+        /// <summary>
+        /// Starts local port forwarding.
+        /// </summary>
+        protected override void StartPort()
+        {
+            InternalStart();
+        }
+
+        /// <summary>
+        /// Stops local port forwarding, and waits for the specified timeout until all pending
+        /// requests are processed.
+        /// </summary>
+        /// <param name="timeout">The maximum amount of time to wait for pending requests to finish processing.</param>
+        protected override void StopPort(TimeSpan timeout)
+        {
+            if (IsStarted)
+            {
+                // prevent new requests from getting processed before we signal existing
+                // channels that the port is closing
+                StopListener();
+                // signal existing channels that the port is closing
+                base.StopPort(timeout);
+            }
+            // wait for open channels to close
+            InternalStop(timeout);
+        }
+
+        /// <summary>
+        /// Ensures the current instance is not disposed.
+        /// </summary>
+        /// <exception cref="ObjectDisposedException">The current instance is disposed.</exception>
+        protected override void CheckDisposed()
+        {
+            if (_isDisposed)
+                throw new ObjectDisposedException(GetType().FullName);
+        }
+
+        partial void InternalStart();
+
+        /// <summary>
+        /// Stops the listener.
+        /// </summary>
+        partial void StopListener();
+
+        /// <summary>
+        /// Waits for pending requests to finish, and channels to close.
+        /// </summary>
+        /// <param name="timeout">The maximum time to wait for the forwarded port to stop.</param>
+        partial void InternalStop(TimeSpan timeout);
+
+        #region IDisposable Members
+
+        /// <summary>
+        /// Holds a value indicating whether the current instance is disposed.
+        /// </summary>
+        /// <value>
+        /// <c>true</c> if the current instance is disposed; otherwise, <c>false</c>.
+        /// </value>
+        private bool _isDisposed;
+
+        /// <summary>
+        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+        /// </summary>
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        partial void InternalDispose(bool disposing);
+
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources
+        /// </summary>
+        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (_isDisposed)
+                return;
+
+            base.Dispose(disposing);
+
+            if (disposing)
+            {
+                var listenerCompleted = _listenerCompleted;
+                if (listenerCompleted != null)
+                {
+                    listenerCompleted.Dispose();
+                    _listenerCompleted = null;
+                }
+            }
+
+            InternalDispose(disposing);
+
+            _isDisposed = true;
+        }
+
+        /// <summary>
+        /// Releases unmanaged resources and performs other cleanup operations before the
+        /// <see cref="ForwardedPortDynamic"/> is reclaimed by garbage collection.
+        /// </summary>
+        ~ForwardedPortDynamic()
+        {
+            Dispose(false);
+        }
+
+        #endregion
+    }
+}

+ 257 - 257
src/Renci.SshNet/ForwardedPortLocal.NET.cs

@@ -1,257 +1,257 @@
-using System;
-using System.Diagnostics;
-using System.Net.Sockets;
-using System.Net;
-using System.Threading;
-using Renci.SshNet.Abstractions;
-using Renci.SshNet.Common;
-
-namespace Renci.SshNet
-{
-    /// <summary>
-    /// Provides functionality for local port forwarding
-    /// </summary>
-    public partial class ForwardedPortLocal
-    {
-        private Socket _listener;
-        private int _pendingRequests;
-
-#if FEATURE_SOCKET_EAP
-        private ManualResetEvent _stoppingListener;
-#endif // FEATURE_SOCKET_EAP
-
-        partial void InternalStart()
-        {
-            var addr = DnsAbstraction.GetHostAddresses(BoundHost)[0];
-            var ep = new IPEndPoint(addr, (int) BoundPort);
-
-            _listener = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
-            // TODO: decide if we want to have blocking socket
-#if FEATURE_SOCKET_SETSOCKETOPTION
-            _listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true);
-#endif // FEATURE_SOCKET_SETSOCKETOPTION
-            _listener.Bind(ep);
-            _listener.Listen(1);
-
-            // update bound port (in case original was passed as zero)
-            BoundPort = (uint)((IPEndPoint)_listener.LocalEndPoint).Port;
-
-            Session.ErrorOccured += Session_ErrorOccured;
-            Session.Disconnected += Session_Disconnected;
-
-            _listenerTaskCompleted = new ManualResetEvent(false);
-
-            ThreadAbstraction.ExecuteThread(() =>
-                {
-                    try
-                    {
-#if FEATURE_SOCKET_EAP
-                        _stoppingListener = new ManualResetEvent(false);
-                        StartAccept();
-                        _stoppingListener.WaitOne();
-#elif FEATURE_SOCKET_APM
-                        while (true)
-                        {
-                            // accept new inbound connection
-                            var asyncResult = _listener.BeginAccept(AcceptCallback, _listener);
-                            // wait for the connection to be established
-                            asyncResult.AsyncWaitHandle.WaitOne();
-                        }
-#elif FEATURE_SOCKET_TAP
-#error Accepting new socket connections is not implemented.
-#else
-#error Accepting new socket connections is not implemented.
-#endif
-                    }
-                    catch (ObjectDisposedException)
-                    {
-                        // BeginAccept will throw an ObjectDisposedException when the
-                        // socket is closed
-                    }
-                    catch (Exception ex)
-                    {
-                        RaiseExceptionEvent(ex);
-                    }
-                    finally
-                    {
-                        // mark listener stopped
-                        _listenerTaskCompleted.Set();
-                    }
-                });
-        }
-
-#if FEATURE_SOCKET_EAP
-        private void StartAccept()
-        {
-            var args = new SocketAsyncEventArgs();
-            args.Completed += AcceptCompleted;
-
-            if (!_listener.AcceptAsync(args))
-            {
-                AcceptCompleted(null, args);
-            }
-        }
-
-        private void AcceptCompleted(object sender, SocketAsyncEventArgs acceptAsyncEventArgs)
-        {
-            if (acceptAsyncEventArgs.SocketError != SocketError.Success)
-            {
-                StartAccept();
-                acceptAsyncEventArgs.AcceptSocket.Dispose();
-                return;
-            }
-
-            StartAccept();
-
-            ProcessAccept(acceptAsyncEventArgs.AcceptSocket);
-        }
-#elif FEATURE_SOCKET_APM
-        private void AcceptCallback(IAsyncResult ar)
-        {
-            // Get the socket that handles the client request
-            var serverSocket = (Socket) ar.AsyncState;
-
-            Socket clientSocket;
-
-            try
-            {
-                clientSocket = serverSocket.EndAccept(ar);
-            }
-            catch (ObjectDisposedException)
-            {
-                // when the socket is closed, an ObjectDisposedException is thrown
-                // by Socket.EndAccept(IAsyncResult)
-                return;
-            }
-
-            ProcessAccept(clientSocket);
-        }
-#endif
-
-        private void ProcessAccept(Socket clientSocket)
-        {
-            Interlocked.Increment(ref _pendingRequests);
-
-            try
-            {
-#if FEATURE_SOCKET_SETSOCKETOPTION
-                clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
-                clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true);
-#endif //FEATURE_SOCKET_SETSOCKETOPTION
-
-                var originatorEndPoint = (IPEndPoint) clientSocket.RemoteEndPoint;
-
-                RaiseRequestReceived(originatorEndPoint.Address.ToString(),
-                    (uint)originatorEndPoint.Port);
-
-                using (var channel = Session.CreateChannelDirectTcpip())
-                {
-                    channel.Exception += Channel_Exception;
-                    channel.Open(Host, Port, this, clientSocket);
-                    channel.Bind();
-                    channel.Close();
-                }
-            }
-            catch (Exception exp)
-            {
-                RaiseExceptionEvent(exp);
-                CloseSocket(clientSocket);
-            }
-            finally
-            {
-                Interlocked.Decrement(ref _pendingRequests);
-            }
-        }
-
-        private static void CloseSocket(Socket socket)
-        {
-            if (socket.Connected)
-            {
-                socket.Shutdown(SocketShutdown.Both);
-                socket.Dispose();
-            }
-        }
-
-        partial void InternalStop(TimeSpan timeout)
-        {
-            if (timeout == TimeSpan.Zero)
-                return;
-
-            var stopWatch = new Stopwatch();
-            stopWatch.Start();
-
-            while (true)
-            {
-                // break out of loop when all pending requests have been processed
-                if (Interlocked.CompareExchange(ref _pendingRequests, 0, 0) == 0)
-                    break;
-                // break out of loop when specified timeout has elapsed
-                if (stopWatch.Elapsed >= timeout && timeout != SshNet.Session.InfiniteTimeSpan)
-                    break;
-                // give channels time to process pending requests
-                ThreadAbstraction.Sleep(50);
-            }
-
-            stopWatch.Stop();
-        }
-
-        /// <summary>
-        /// Interrupts the listener, and waits for the listener loop to finish.
-        /// </summary>
-        /// <remarks>
-        /// When the forwarded port is stopped, then any further action is skipped.
-        /// </remarks>
-        partial void StopListener()
-        {
-            if (!IsStarted)
-                return;
-
-            Session.Disconnected -= Session_Disconnected;
-            Session.ErrorOccured -= Session_ErrorOccured;
-
-#if FEATURE_SOCKET_EAP
-            _stoppingListener.Set();
-#endif // FEATURE_SOCKET_EAP
-
-            // close listener socket
-            _listener.Dispose();
-            // wait for listener loop to finish
-            _listenerTaskCompleted.WaitOne();
-        }
-
-        partial void InternalDispose(bool disposing)
-        {
-            if (disposing)
-            {
-                if (_listener != null)
-                {
-                    _listener.Dispose();
-                    _listener = null;
-                }
-
-#if FEATURE_SOCKET_EAP
-                if (_stoppingListener != null)
-                {
-                    _stoppingListener.Dispose();
-                    _stoppingListener = null;
-                }
-#endif // FEATURE_SOCKET_EAP
-            }
-        }
-
-        private void Session_ErrorOccured(object sender, ExceptionEventArgs e)
-        {
-            StopListener();
-        }
-
-        private void Session_Disconnected(object sender, EventArgs e)
-        {
-            StopListener();
-        }
-
-        private void Channel_Exception(object sender, ExceptionEventArgs e)
-        {
-            RaiseExceptionEvent(e.Exception);
-        }
-    }
-}
+using System;
+using System.Diagnostics;
+using System.Net.Sockets;
+using System.Net;
+using System.Threading;
+using Renci.SshNet.Abstractions;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet
+{
+    /// <summary>
+    /// Provides functionality for local port forwarding
+    /// </summary>
+    public partial class ForwardedPortLocal
+    {
+        private Socket _listener;
+        private int _pendingRequests;
+
+#if FEATURE_SOCKET_EAP
+        private ManualResetEvent _stoppingListener;
+#endif // FEATURE_SOCKET_EAP
+
+        partial void InternalStart()
+        {
+            var addr = DnsAbstraction.GetHostAddresses(BoundHost)[0];
+            var ep = new IPEndPoint(addr, (int) BoundPort);
+
+            _listener = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
+            // TODO: decide if we want to have blocking socket
+#if FEATURE_SOCKET_SETSOCKETOPTION
+            _listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true);
+#endif // FEATURE_SOCKET_SETSOCKETOPTION
+            _listener.Bind(ep);
+            _listener.Listen(1);
+
+            // update bound port (in case original was passed as zero)
+            BoundPort = (uint)((IPEndPoint)_listener.LocalEndPoint).Port;
+
+            Session.ErrorOccured += Session_ErrorOccured;
+            Session.Disconnected += Session_Disconnected;
+
+            _listenerTaskCompleted = new ManualResetEvent(false);
+
+            ThreadAbstraction.ExecuteThread(() =>
+                {
+                    try
+                    {
+#if FEATURE_SOCKET_EAP
+                        _stoppingListener = new ManualResetEvent(false);
+                        StartAccept();
+                        _stoppingListener.WaitOne();
+#elif FEATURE_SOCKET_APM
+                        while (true)
+                        {
+                            // accept new inbound connection
+                            var asyncResult = _listener.BeginAccept(AcceptCallback, _listener);
+                            // wait for the connection to be established
+                            asyncResult.AsyncWaitHandle.WaitOne();
+                        }
+#elif FEATURE_SOCKET_TAP
+#error Accepting new socket connections is not implemented.
+#else
+#error Accepting new socket connections is not implemented.
+#endif
+                    }
+                    catch (ObjectDisposedException)
+                    {
+                        // BeginAccept will throw an ObjectDisposedException when the
+                        // socket is closed
+                    }
+                    catch (Exception ex)
+                    {
+                        RaiseExceptionEvent(ex);
+                    }
+                    finally
+                    {
+                        // mark listener stopped
+                        _listenerTaskCompleted.Set();
+                    }
+                });
+        }
+
+#if FEATURE_SOCKET_EAP
+        private void StartAccept()
+        {
+            var args = new SocketAsyncEventArgs();
+            args.Completed += AcceptCompleted;
+
+            if (!_listener.AcceptAsync(args))
+            {
+                AcceptCompleted(null, args);
+            }
+        }
+
+        private void AcceptCompleted(object sender, SocketAsyncEventArgs acceptAsyncEventArgs)
+        {
+            if (acceptAsyncEventArgs.SocketError != SocketError.Success)
+            {
+                StartAccept();
+                acceptAsyncEventArgs.AcceptSocket.Dispose();
+                return;
+            }
+
+            StartAccept();
+
+            ProcessAccept(acceptAsyncEventArgs.AcceptSocket);
+        }
+#elif FEATURE_SOCKET_APM
+        private void AcceptCallback(IAsyncResult ar)
+        {
+            // Get the socket that handles the client request
+            var serverSocket = (Socket) ar.AsyncState;
+
+            Socket clientSocket;
+
+            try
+            {
+                clientSocket = serverSocket.EndAccept(ar);
+            }
+            catch (ObjectDisposedException)
+            {
+                // when the socket is closed, an ObjectDisposedException is thrown
+                // by Socket.EndAccept(IAsyncResult)
+                return;
+            }
+
+            ProcessAccept(clientSocket);
+        }
+#endif
+
+        private void ProcessAccept(Socket clientSocket)
+        {
+            Interlocked.Increment(ref _pendingRequests);
+
+            try
+            {
+#if FEATURE_SOCKET_SETSOCKETOPTION
+                clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
+                clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true);
+#endif //FEATURE_SOCKET_SETSOCKETOPTION
+
+                var originatorEndPoint = (IPEndPoint) clientSocket.RemoteEndPoint;
+
+                RaiseRequestReceived(originatorEndPoint.Address.ToString(),
+                    (uint)originatorEndPoint.Port);
+
+                using (var channel = Session.CreateChannelDirectTcpip())
+                {
+                    channel.Exception += Channel_Exception;
+                    channel.Open(Host, Port, this, clientSocket);
+                    channel.Bind();
+                    channel.Close();
+                }
+            }
+            catch (Exception exp)
+            {
+                RaiseExceptionEvent(exp);
+                CloseSocket(clientSocket);
+            }
+            finally
+            {
+                Interlocked.Decrement(ref _pendingRequests);
+            }
+        }
+
+        private static void CloseSocket(Socket socket)
+        {
+            if (socket.Connected)
+            {
+                socket.Shutdown(SocketShutdown.Both);
+                socket.Dispose();
+            }
+        }
+
+        partial void InternalStop(TimeSpan timeout)
+        {
+            if (timeout == TimeSpan.Zero)
+                return;
+
+            var stopWatch = new Stopwatch();
+            stopWatch.Start();
+
+            while (true)
+            {
+                // break out of loop when all pending requests have been processed
+                if (Interlocked.CompareExchange(ref _pendingRequests, 0, 0) == 0)
+                    break;
+                // break out of loop when specified timeout has elapsed
+                if (stopWatch.Elapsed >= timeout && timeout != SshNet.Session.InfiniteTimeSpan)
+                    break;
+                // give channels time to process pending requests
+                ThreadAbstraction.Sleep(50);
+            }
+
+            stopWatch.Stop();
+        }
+
+        /// <summary>
+        /// Interrupts the listener, and waits for the listener loop to finish.
+        /// </summary>
+        /// <remarks>
+        /// When the forwarded port is stopped, then any further action is skipped.
+        /// </remarks>
+        partial void StopListener()
+        {
+            if (!IsStarted)
+                return;
+
+            Session.Disconnected -= Session_Disconnected;
+            Session.ErrorOccured -= Session_ErrorOccured;
+
+#if FEATURE_SOCKET_EAP
+            _stoppingListener.Set();
+#endif // FEATURE_SOCKET_EAP
+
+            // close listener socket
+            _listener.Dispose();
+            // wait for listener loop to finish
+            _listenerTaskCompleted.WaitOne();
+        }
+
+        partial void InternalDispose(bool disposing)
+        {
+            if (disposing)
+            {
+                if (_listener != null)
+                {
+                    _listener.Dispose();
+                    _listener = null;
+                }
+
+#if FEATURE_SOCKET_EAP
+                if (_stoppingListener != null)
+                {
+                    _stoppingListener.Dispose();
+                    _stoppingListener = null;
+                }
+#endif // FEATURE_SOCKET_EAP
+            }
+        }
+
+        private void Session_ErrorOccured(object sender, ExceptionEventArgs e)
+        {
+            StopListener();
+        }
+
+        private void Session_Disconnected(object sender, EventArgs e)
+        {
+            StopListener();
+        }
+
+        private void Channel_Exception(object sender, ExceptionEventArgs e)
+        {
+            RaiseExceptionEvent(e.Exception);
+        }
+    }
+}

+ 204 - 204
src/Renci.SshNet/ForwardedPortLocal.cs

@@ -1,204 +1,204 @@
-using System;
-using System.Threading;
-
-namespace Renci.SshNet
-{
-    /// <summary>
-    /// Provides functionality for local port forwarding
-    /// </summary>
-    public partial class ForwardedPortLocal : ForwardedPort, IDisposable
-    {
-        private EventWaitHandle _listenerTaskCompleted;
-
-        /// <summary>
-        /// Gets the bound host.
-        /// </summary>
-        public string BoundHost { get; private set; }
-
-        /// <summary>
-        /// Gets the bound port.
-        /// </summary>
-        public uint BoundPort { get; private set; }
-
-        /// <summary>
-        /// Gets the forwarded host.
-        /// </summary>
-        public string Host { get; private set; }
-
-        /// <summary>
-        /// Gets the forwarded port.
-        /// </summary>
-        public uint Port { get; private set; }
-
-        /// <summary>
-        /// Gets or sets a value indicating whether port forwarding is started.
-        /// </summary>
-        /// <value>
-        /// <c>true</c> if port forwarding is started; otherwise, <c>false</c>.
-        /// </value>
-        public override bool IsStarted
-        {
-            get { return _listenerTaskCompleted != null && !_listenerTaskCompleted.WaitOne(0); }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ForwardedPortLocal"/> class.
-        /// </summary>
-        /// <param name="boundPort">The bound port.</param>
-        /// <param name="host">The host.</param>
-        /// <param name="port">The port.</param>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="boundPort" /> is greater than <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
-        /// <exception cref="ArgumentNullException"><paramref name="host"/> is <c>null</c>.</exception>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="port" /> is greater than <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
-        /// <example>
-        ///     <code source="..\..\Renci.SshNet.Tests\Classes\ForwardedPortLocalTest.cs" region="Example SshClient AddForwardedPort Start Stop ForwardedPortLocal" language="C#" title="Local port forwarding" />
-        /// </example>
-        public ForwardedPortLocal(uint boundPort, string host, uint port)
-            : this(string.Empty, boundPort, host, port)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ForwardedPortLocal"/> class.
-        /// </summary>
-        /// <param name="boundHost">The bound host.</param>
-        /// <param name="host">The host.</param>
-        /// <param name="port">The port.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="boundHost"/> is <c>null</c>.</exception>
-        /// <exception cref="ArgumentNullException"><paramref name="host"/> is <c>null</c>.</exception>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="port" /> is greater than <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
-        public ForwardedPortLocal(string boundHost, string host, uint port)
-            : this(boundHost, 0, host, port) 
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ForwardedPortLocal"/> class.
-        /// </summary>
-        /// <param name="boundHost">The bound host.</param>
-        /// <param name="boundPort">The bound port.</param>
-        /// <param name="host">The host.</param>
-        /// <param name="port">The port.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="boundHost"/> is <c>null</c>.</exception>
-        /// <exception cref="ArgumentNullException"><paramref name="host"/> is <c>null</c>.</exception>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="boundPort" /> is greater than <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="port" /> is greater than <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
-        public ForwardedPortLocal(string boundHost, uint boundPort, string host, uint port)
-        {
-            if (boundHost == null)
-                throw new ArgumentNullException("boundHost");
-
-            if (host == null)
-                throw new ArgumentNullException("host");
-
-            boundPort.ValidatePort("boundPort");
-            port.ValidatePort("port");
-
-            BoundHost = boundHost;
-            BoundPort = boundPort;
-            Host = host;
-            Port = port;
-        }
-
-        /// <summary>
-        /// Starts local port forwarding.
-        /// </summary>
-        protected override void StartPort()
-        {
-            InternalStart();
-        }
-
-        /// <summary>
-        /// Stops local port forwarding, and waits for the specified timeout until all pending
-        /// requests are processed.
-        /// </summary>
-        /// <param name="timeout">The maximum amount of time to wait for pending requests to finish processing.</param>
-        protected override void StopPort(TimeSpan timeout)
-        {
-            if (IsStarted)
-            {
-                // prevent new requests from getting processed before we signal existing
-                // channels that the port is closing
-                StopListener();
-                // signal existing channels that the port is closing
-                base.StopPort(timeout);
-            }
-            // wait for open channels to close
-            InternalStop(timeout);
-        }
-
-        /// <summary>
-        /// Ensures the current instance is not disposed.
-        /// </summary>
-        /// <exception cref="ObjectDisposedException">The current instance is disposed.</exception>
-        protected override void CheckDisposed()
-        {
-            if (_isDisposed)
-                throw new ObjectDisposedException(GetType().FullName);
-        }
-
-        partial void InternalStart();
-
-        /// <summary>
-        /// Interrupts the listener, and waits for the listener loop to finish.
-        /// </summary>
-        /// <remarks>
-        /// When the forwarded port is stopped, then any further action is skipped.
-        /// </remarks>
-        partial void StopListener();
-
-        partial void InternalStop(TimeSpan timeout);
-
-        #region IDisposable Members
-
-        private bool _isDisposed;
-
-        /// <summary>
-        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
-        /// </summary>
-        public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
-
-        partial void InternalDispose(bool disposing);
-
-        /// <summary>
-        /// Releases unmanaged and - optionally - managed resources
-        /// </summary>
-        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
-        protected override void Dispose(bool disposing)
-        {
-            if (_isDisposed)
-                return;
-
-            base.Dispose(disposing);
-
-            if (disposing)
-            {
-                var listenerTaskCompleted = _listenerTaskCompleted;
-                if (listenerTaskCompleted != null)
-                {
-                    listenerTaskCompleted.Dispose();
-                    _listenerTaskCompleted = null;
-                }
-            }
-
-            InternalDispose(disposing);
-
-            _isDisposed = true;
-        }
-
-        /// <summary>
-        /// Releases unmanaged resources and performs other cleanup operations before the
-        /// <see cref="ForwardedPortLocal"/> is reclaimed by garbage collection.
-        /// </summary>
-        ~ForwardedPortLocal()
-        {
-            Dispose(false);
-        }
-
-        #endregion
-    }
-}
+using System;
+using System.Threading;
+
+namespace Renci.SshNet
+{
+    /// <summary>
+    /// Provides functionality for local port forwarding
+    /// </summary>
+    public partial class ForwardedPortLocal : ForwardedPort, IDisposable
+    {
+        private EventWaitHandle _listenerTaskCompleted;
+
+        /// <summary>
+        /// Gets the bound host.
+        /// </summary>
+        public string BoundHost { get; private set; }
+
+        /// <summary>
+        /// Gets the bound port.
+        /// </summary>
+        public uint BoundPort { get; private set; }
+
+        /// <summary>
+        /// Gets the forwarded host.
+        /// </summary>
+        public string Host { get; private set; }
+
+        /// <summary>
+        /// Gets the forwarded port.
+        /// </summary>
+        public uint Port { get; private set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether port forwarding is started.
+        /// </summary>
+        /// <value>
+        /// <c>true</c> if port forwarding is started; otherwise, <c>false</c>.
+        /// </value>
+        public override bool IsStarted
+        {
+            get { return _listenerTaskCompleted != null && !_listenerTaskCompleted.WaitOne(0); }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ForwardedPortLocal"/> class.
+        /// </summary>
+        /// <param name="boundPort">The bound port.</param>
+        /// <param name="host">The host.</param>
+        /// <param name="port">The port.</param>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="boundPort" /> is greater than <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="host"/> is <c>null</c>.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="port" /> is greater than <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
+        /// <example>
+        ///     <code source="..\..\Renci.SshNet.Tests\Classes\ForwardedPortLocalTest.cs" region="Example SshClient AddForwardedPort Start Stop ForwardedPortLocal" language="C#" title="Local port forwarding" />
+        /// </example>
+        public ForwardedPortLocal(uint boundPort, string host, uint port)
+            : this(string.Empty, boundPort, host, port)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ForwardedPortLocal"/> class.
+        /// </summary>
+        /// <param name="boundHost">The bound host.</param>
+        /// <param name="host">The host.</param>
+        /// <param name="port">The port.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="boundHost"/> is <c>null</c>.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="host"/> is <c>null</c>.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="port" /> is greater than <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
+        public ForwardedPortLocal(string boundHost, string host, uint port)
+            : this(boundHost, 0, host, port) 
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ForwardedPortLocal"/> class.
+        /// </summary>
+        /// <param name="boundHost">The bound host.</param>
+        /// <param name="boundPort">The bound port.</param>
+        /// <param name="host">The host.</param>
+        /// <param name="port">The port.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="boundHost"/> is <c>null</c>.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="host"/> is <c>null</c>.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="boundPort" /> is greater than <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="port" /> is greater than <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
+        public ForwardedPortLocal(string boundHost, uint boundPort, string host, uint port)
+        {
+            if (boundHost == null)
+                throw new ArgumentNullException("boundHost");
+
+            if (host == null)
+                throw new ArgumentNullException("host");
+
+            boundPort.ValidatePort("boundPort");
+            port.ValidatePort("port");
+
+            BoundHost = boundHost;
+            BoundPort = boundPort;
+            Host = host;
+            Port = port;
+        }
+
+        /// <summary>
+        /// Starts local port forwarding.
+        /// </summary>
+        protected override void StartPort()
+        {
+            InternalStart();
+        }
+
+        /// <summary>
+        /// Stops local port forwarding, and waits for the specified timeout until all pending
+        /// requests are processed.
+        /// </summary>
+        /// <param name="timeout">The maximum amount of time to wait for pending requests to finish processing.</param>
+        protected override void StopPort(TimeSpan timeout)
+        {
+            if (IsStarted)
+            {
+                // prevent new requests from getting processed before we signal existing
+                // channels that the port is closing
+                StopListener();
+                // signal existing channels that the port is closing
+                base.StopPort(timeout);
+            }
+            // wait for open channels to close
+            InternalStop(timeout);
+        }
+
+        /// <summary>
+        /// Ensures the current instance is not disposed.
+        /// </summary>
+        /// <exception cref="ObjectDisposedException">The current instance is disposed.</exception>
+        protected override void CheckDisposed()
+        {
+            if (_isDisposed)
+                throw new ObjectDisposedException(GetType().FullName);
+        }
+
+        partial void InternalStart();
+
+        /// <summary>
+        /// Interrupts the listener, and waits for the listener loop to finish.
+        /// </summary>
+        /// <remarks>
+        /// When the forwarded port is stopped, then any further action is skipped.
+        /// </remarks>
+        partial void StopListener();
+
+        partial void InternalStop(TimeSpan timeout);
+
+        #region IDisposable Members
+
+        private bool _isDisposed;
+
+        /// <summary>
+        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+        /// </summary>
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        partial void InternalDispose(bool disposing);
+
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources
+        /// </summary>
+        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (_isDisposed)
+                return;
+
+            base.Dispose(disposing);
+
+            if (disposing)
+            {
+                var listenerTaskCompleted = _listenerTaskCompleted;
+                if (listenerTaskCompleted != null)
+                {
+                    listenerTaskCompleted.Dispose();
+                    _listenerTaskCompleted = null;
+                }
+            }
+
+            InternalDispose(disposing);
+
+            _isDisposed = true;
+        }
+
+        /// <summary>
+        /// Releases unmanaged resources and performs other cleanup operations before the
+        /// <see cref="ForwardedPortLocal"/> is reclaimed by garbage collection.
+        /// </summary>
+        ~ForwardedPortLocal()
+        {
+            Dispose(false);
+        }
+
+        #endregion
+    }
+}

+ 339 - 339
src/Renci.SshNet/ForwardedPortRemote.cs

@@ -1,339 +1,339 @@
-using System;
-using System.Threading;
-using Renci.SshNet.Messages.Connection;
-using Renci.SshNet.Common;
-using System.Globalization;
-using System.Net;
-using Renci.SshNet.Abstractions;
-
-namespace Renci.SshNet
-{
-    /// <summary>
-    /// Provides functionality for remote port forwarding
-    /// </summary>
-    public class ForwardedPortRemote : ForwardedPort, IDisposable
-    {
-        private bool _requestStatus;
-
-        private EventWaitHandle _globalRequestResponse = new AutoResetEvent(false);
-        private int _pendingRequests;
-        private bool _isStarted;
-
-        /// <summary>
-        /// Gets or sets a value indicating whether port forwarding is started.
-        /// </summary>
-        /// <value>
-        /// <c>true</c> if port forwarding is started; otherwise, <c>false</c>.
-        /// </value>
-        public override bool IsStarted
-        {
-            get { return _isStarted; }
-        }
-
-        /// <summary>
-        /// Gets the bound host.
-        /// </summary>
-        public IPAddress BoundHostAddress { get; private set; }
-
-        /// <summary>
-        /// Gets the bound host.
-        /// </summary>
-        public string BoundHost
-        {
-            get
-            {
-                return BoundHostAddress.ToString();
-            }
-        }
-
-        /// <summary>
-        /// Gets the bound port.
-        /// </summary>
-        public uint BoundPort { get; private set; }
-
-        /// <summary>
-        /// Gets the forwarded host.
-        /// </summary>
-        public IPAddress HostAddress { get; private set; }
-
-        /// <summary>
-        /// Gets the forwarded host.
-        /// </summary>
-        public string Host
-        {
-            get
-            {
-                return HostAddress.ToString();
-            }
-        }
-
-        /// <summary>
-        /// Gets the forwarded port.
-        /// </summary>
-        public uint Port { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ForwardedPortRemote" /> class.
-        /// </summary>
-        /// <param name="boundHostAddress">The bound host address.</param>
-        /// <param name="boundPort">The bound port.</param>
-        /// <param name="hostAddress">The host address.</param>
-        /// <param name="port">The port.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="boundHostAddress"/> is <c>null</c>.</exception>
-        /// <exception cref="ArgumentNullException"><paramref name="hostAddress"/> is <c>null</c>.</exception>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="boundPort" /> is greater than <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="port" /> is greater than <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
-        public ForwardedPortRemote(IPAddress boundHostAddress, uint boundPort, IPAddress hostAddress, uint port)
-        {
-            if (boundHostAddress == null)
-                throw new ArgumentNullException("boundHostAddress");
-            if (hostAddress == null)
-                throw new ArgumentNullException("hostAddress");
-
-            boundPort.ValidatePort("boundPort");
-            port.ValidatePort("port");
-
-            BoundHostAddress = boundHostAddress;
-            BoundPort = boundPort;
-            HostAddress = hostAddress;
-            Port = port;
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ForwardedPortRemote"/> class.
-        /// </summary>
-        /// <param name="boundPort">The bound port.</param>
-        /// <param name="host">The host.</param>
-        /// <param name="port">The port.</param>
-        /// <example>
-        ///     <code source="..\..\Renci.SshNet.Tests\Classes\ForwardedPortRemoteTest.cs" region="Example SshClient AddForwardedPort Start Stop ForwardedPortRemote" language="C#" title="Remote port forwarding" />
-        /// </example>
-        public ForwardedPortRemote(uint boundPort, string host, uint port)
-            : this(string.Empty, boundPort, host, port)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ForwardedPortRemote"/> class.
-        /// </summary>
-        /// <param name="boundHost">The bound host.</param>
-        /// <param name="boundPort">The bound port.</param>
-        /// <param name="host">The host.</param>
-        /// <param name="port">The port.</param>
-        public ForwardedPortRemote(string boundHost, uint boundPort, string host, uint port)
-            : this(DnsAbstraction.GetHostAddresses(boundHost)[0],
-                   boundPort,
-                   DnsAbstraction.GetHostAddresses(host)[0],
-                   port)
-        {
-        }
-
-        /// <summary>
-        /// Starts remote port forwarding.
-        /// </summary>
-        protected override void StartPort()
-        {
-            Session.RegisterMessage("SSH_MSG_REQUEST_FAILURE");
-            Session.RegisterMessage("SSH_MSG_REQUEST_SUCCESS");
-            Session.RegisterMessage("SSH_MSG_CHANNEL_OPEN");
-
-            Session.RequestSuccessReceived += Session_RequestSuccess;
-            Session.RequestFailureReceived += Session_RequestFailure;
-            Session.ChannelOpenReceived += Session_ChannelOpening;
-
-            // send global request to start direct tcpip
-            Session.SendMessage(new GlobalRequestMessage(GlobalRequestName.TcpIpForward, true, BoundHost, BoundPort));
-            // wat for response on global request to start direct tcpip
-            Session.WaitOnHandle(_globalRequestResponse);
-
-            if (!_requestStatus)
-            {
-                // when the request to start port forward was rejected, then we're no longer
-                // interested in these events
-                Session.RequestSuccessReceived -= Session_RequestSuccess;
-                Session.RequestFailureReceived -= Session_RequestFailure;
-                Session.ChannelOpenReceived -= Session_ChannelOpening;
-
-                throw new SshException(string.Format(CultureInfo.CurrentCulture, "Port forwarding for '{0}' port '{1}' failed to start.", Host, Port));
-            }
-
-            _isStarted = true;
-        }
-
-        /// <summary>
-        /// Stops remote port forwarding.
-        /// </summary>
-        /// <param name="timeout">The maximum amount of time to wait for pending requests to finish processing.</param>
-        protected override void StopPort(TimeSpan timeout)
-        {
-            // if the port not started, then there's nothing to stop
-            if (!IsStarted)
-                return;
-
-            // mark forwarded port stopped, this also causes open of new channels to be rejected
-            _isStarted = false;
-
-            base.StopPort(timeout);
-
-            // send global request to cancel direct tcpip
-            Session.SendMessage(new GlobalRequestMessage(GlobalRequestName.CancelTcpIpForward, true, BoundHost, BoundPort));
-            // wait for response on global request to cancel direct tcpip or completion of message
-            // listener loop (in which case response on global request can never be received)
-            WaitHandle.WaitAny(new[] { _globalRequestResponse, Session.MessageListenerCompleted }, timeout);
-
-            // unsubscribe from session events as either the tcpip forward is cancelled at the
-            // server, or our session message loop has completed
-            Session.RequestSuccessReceived -= Session_RequestSuccess;
-            Session.RequestFailureReceived -= Session_RequestFailure;
-            Session.ChannelOpenReceived -= Session_ChannelOpening;
-
-            var startWaiting = DateTime.Now;
-
-            while (true)
-            {
-                // break out of loop when all pending requests have been processed
-                if (Interlocked.CompareExchange(ref _pendingRequests, 0, 0) == 0)
-                    break;
-                // determine time elapsed since waiting for pending requests to finish
-                var elapsed = DateTime.Now - startWaiting;
-                // break out of loop when specified timeout has elapsed
-                if (elapsed >= timeout && timeout != SshNet.Session.InfiniteTimeSpan)
-                    break;
-                // give channels time to process pending requests
-                ThreadAbstraction.Sleep(50);
-            }
-        }
-
-        /// <summary>
-        /// Ensures the current instance is not disposed.
-        /// </summary>
-        /// <exception cref="ObjectDisposedException">The current instance is disposed.</exception>
-        protected override void CheckDisposed()
-        {
-            if (_isDisposed)
-                throw new ObjectDisposedException(GetType().FullName);
-        }
-
-        private void Session_ChannelOpening(object sender, MessageEventArgs<ChannelOpenMessage> e)
-        {
-            var channelOpenMessage = e.Message;
-            var info = channelOpenMessage.Info as ForwardedTcpipChannelInfo;
-            if (info != null)
-            {
-                //  Ensure this is the corresponding request
-                if (info.ConnectedAddress == BoundHost && info.ConnectedPort == BoundPort)
-                {
-                    if (!_isStarted)
-                    {
-                        Session.SendMessage(new ChannelOpenFailureMessage(channelOpenMessage.LocalChannelNumber, "", ChannelOpenFailureMessage.AdministrativelyProhibited));
-                        return;
-                    }
-
-                    ThreadAbstraction.ExecuteThread(() =>
-                        {
-                            Interlocked.Increment(ref _pendingRequests);
-
-                            try
-                            {
-                                RaiseRequestReceived(info.OriginatorAddress, info.OriginatorPort);
-
-                                using (var channel = Session.CreateChannelForwardedTcpip(channelOpenMessage.LocalChannelNumber, channelOpenMessage.InitialWindowSize, channelOpenMessage.MaximumPacketSize))
-                                {
-                                    channel.Exception += Channel_Exception;
-                                    channel.Bind(new IPEndPoint(HostAddress, (int) Port), this);
-                                    channel.Close();
-                                }
-                            }
-                            catch (Exception exp)
-                            {
-                                RaiseExceptionEvent(exp);
-                            }
-                            finally
-                            {
-                                Interlocked.Decrement(ref _pendingRequests);
-                            }
-                        });
-                }
-            }
-        }
-
-        private void Channel_Exception(object sender, ExceptionEventArgs exceptionEventArgs)
-        {
-            RaiseExceptionEvent(exceptionEventArgs.Exception);
-        }
-
-        private void Session_RequestFailure(object sender, EventArgs e)
-        {
-            _requestStatus = false;
-            _globalRequestResponse.Set();
-        }
-
-        private void Session_RequestSuccess(object sender, MessageEventArgs<RequestSuccessMessage> e)
-        {
-            _requestStatus = true;
-            if (BoundPort == 0)
-            {
-                BoundPort = (e.Message.BoundPort == null) ? 0 : e.Message.BoundPort.Value;
-            }
-
-            _globalRequestResponse.Set();
-        }
-
-        #region IDisposable Members
-
-        private bool _isDisposed;
-
-        /// <summary>
-        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
-        /// </summary>
-        public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
-
-        /// <summary>
-        /// Releases unmanaged and - optionally - managed resources
-        /// </summary>
-        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
-        protected override void Dispose(bool disposing)
-        {
-            if (_isDisposed)
-                return;
-
-            base.Dispose(disposing);
-
-            if (disposing)
-            {
-                var session = Session;
-                if (session != null)
-                {
-                    session.RequestSuccessReceived -= Session_RequestSuccess;
-                    session.RequestFailureReceived -= Session_RequestFailure;
-                    session.ChannelOpenReceived -= Session_ChannelOpening;
-                    Session = null;
-                }
-
-                var globalRequestResponse = _globalRequestResponse;
-                if (globalRequestResponse != null)
-                {
-                    globalRequestResponse.Dispose();
-                    _globalRequestResponse = null;
-                }
-            }
-
-            _isDisposed = true;
-        }
-
-        /// <summary>
-        /// Releases unmanaged resources and performs other cleanup operations before the
-        /// <see cref="ForwardedPortRemote"/> is reclaimed by garbage collection.
-        /// </summary>
-        ~ForwardedPortRemote()
-        {
-            Dispose(false);
-        }
-
-        #endregion
-    }
-}
+using System;
+using System.Threading;
+using Renci.SshNet.Messages.Connection;
+using Renci.SshNet.Common;
+using System.Globalization;
+using System.Net;
+using Renci.SshNet.Abstractions;
+
+namespace Renci.SshNet
+{
+    /// <summary>
+    /// Provides functionality for remote port forwarding
+    /// </summary>
+    public class ForwardedPortRemote : ForwardedPort, IDisposable
+    {
+        private bool _requestStatus;
+
+        private EventWaitHandle _globalRequestResponse = new AutoResetEvent(false);
+        private int _pendingRequests;
+        private bool _isStarted;
+
+        /// <summary>
+        /// Gets or sets a value indicating whether port forwarding is started.
+        /// </summary>
+        /// <value>
+        /// <c>true</c> if port forwarding is started; otherwise, <c>false</c>.
+        /// </value>
+        public override bool IsStarted
+        {
+            get { return _isStarted; }
+        }
+
+        /// <summary>
+        /// Gets the bound host.
+        /// </summary>
+        public IPAddress BoundHostAddress { get; private set; }
+
+        /// <summary>
+        /// Gets the bound host.
+        /// </summary>
+        public string BoundHost
+        {
+            get
+            {
+                return BoundHostAddress.ToString();
+            }
+        }
+
+        /// <summary>
+        /// Gets the bound port.
+        /// </summary>
+        public uint BoundPort { get; private set; }
+
+        /// <summary>
+        /// Gets the forwarded host.
+        /// </summary>
+        public IPAddress HostAddress { get; private set; }
+
+        /// <summary>
+        /// Gets the forwarded host.
+        /// </summary>
+        public string Host
+        {
+            get
+            {
+                return HostAddress.ToString();
+            }
+        }
+
+        /// <summary>
+        /// Gets the forwarded port.
+        /// </summary>
+        public uint Port { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ForwardedPortRemote" /> class.
+        /// </summary>
+        /// <param name="boundHostAddress">The bound host address.</param>
+        /// <param name="boundPort">The bound port.</param>
+        /// <param name="hostAddress">The host address.</param>
+        /// <param name="port">The port.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="boundHostAddress"/> is <c>null</c>.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="hostAddress"/> is <c>null</c>.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="boundPort" /> is greater than <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="port" /> is greater than <see cref="F:System.Net.IPEndPoint.MaxPort" />.</exception>
+        public ForwardedPortRemote(IPAddress boundHostAddress, uint boundPort, IPAddress hostAddress, uint port)
+        {
+            if (boundHostAddress == null)
+                throw new ArgumentNullException("boundHostAddress");
+            if (hostAddress == null)
+                throw new ArgumentNullException("hostAddress");
+
+            boundPort.ValidatePort("boundPort");
+            port.ValidatePort("port");
+
+            BoundHostAddress = boundHostAddress;
+            BoundPort = boundPort;
+            HostAddress = hostAddress;
+            Port = port;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ForwardedPortRemote"/> class.
+        /// </summary>
+        /// <param name="boundPort">The bound port.</param>
+        /// <param name="host">The host.</param>
+        /// <param name="port">The port.</param>
+        /// <example>
+        ///     <code source="..\..\Renci.SshNet.Tests\Classes\ForwardedPortRemoteTest.cs" region="Example SshClient AddForwardedPort Start Stop ForwardedPortRemote" language="C#" title="Remote port forwarding" />
+        /// </example>
+        public ForwardedPortRemote(uint boundPort, string host, uint port)
+            : this(string.Empty, boundPort, host, port)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ForwardedPortRemote"/> class.
+        /// </summary>
+        /// <param name="boundHost">The bound host.</param>
+        /// <param name="boundPort">The bound port.</param>
+        /// <param name="host">The host.</param>
+        /// <param name="port">The port.</param>
+        public ForwardedPortRemote(string boundHost, uint boundPort, string host, uint port)
+            : this(DnsAbstraction.GetHostAddresses(boundHost)[0],
+                   boundPort,
+                   DnsAbstraction.GetHostAddresses(host)[0],
+                   port)
+        {
+        }
+
+        /// <summary>
+        /// Starts remote port forwarding.
+        /// </summary>
+        protected override void StartPort()
+        {
+            Session.RegisterMessage("SSH_MSG_REQUEST_FAILURE");
+            Session.RegisterMessage("SSH_MSG_REQUEST_SUCCESS");
+            Session.RegisterMessage("SSH_MSG_CHANNEL_OPEN");
+
+            Session.RequestSuccessReceived += Session_RequestSuccess;
+            Session.RequestFailureReceived += Session_RequestFailure;
+            Session.ChannelOpenReceived += Session_ChannelOpening;
+
+            // send global request to start direct tcpip
+            Session.SendMessage(new GlobalRequestMessage(GlobalRequestName.TcpIpForward, true, BoundHost, BoundPort));
+            // wat for response on global request to start direct tcpip
+            Session.WaitOnHandle(_globalRequestResponse);
+
+            if (!_requestStatus)
+            {
+                // when the request to start port forward was rejected, then we're no longer
+                // interested in these events
+                Session.RequestSuccessReceived -= Session_RequestSuccess;
+                Session.RequestFailureReceived -= Session_RequestFailure;
+                Session.ChannelOpenReceived -= Session_ChannelOpening;
+
+                throw new SshException(string.Format(CultureInfo.CurrentCulture, "Port forwarding for '{0}' port '{1}' failed to start.", Host, Port));
+            }
+
+            _isStarted = true;
+        }
+
+        /// <summary>
+        /// Stops remote port forwarding.
+        /// </summary>
+        /// <param name="timeout">The maximum amount of time to wait for pending requests to finish processing.</param>
+        protected override void StopPort(TimeSpan timeout)
+        {
+            // if the port not started, then there's nothing to stop
+            if (!IsStarted)
+                return;
+
+            // mark forwarded port stopped, this also causes open of new channels to be rejected
+            _isStarted = false;
+
+            base.StopPort(timeout);
+
+            // send global request to cancel direct tcpip
+            Session.SendMessage(new GlobalRequestMessage(GlobalRequestName.CancelTcpIpForward, true, BoundHost, BoundPort));
+            // wait for response on global request to cancel direct tcpip or completion of message
+            // listener loop (in which case response on global request can never be received)
+            WaitHandle.WaitAny(new[] { _globalRequestResponse, Session.MessageListenerCompleted }, timeout);
+
+            // unsubscribe from session events as either the tcpip forward is cancelled at the
+            // server, or our session message loop has completed
+            Session.RequestSuccessReceived -= Session_RequestSuccess;
+            Session.RequestFailureReceived -= Session_RequestFailure;
+            Session.ChannelOpenReceived -= Session_ChannelOpening;
+
+            var startWaiting = DateTime.Now;
+
+            while (true)
+            {
+                // break out of loop when all pending requests have been processed
+                if (Interlocked.CompareExchange(ref _pendingRequests, 0, 0) == 0)
+                    break;
+                // determine time elapsed since waiting for pending requests to finish
+                var elapsed = DateTime.Now - startWaiting;
+                // break out of loop when specified timeout has elapsed
+                if (elapsed >= timeout && timeout != SshNet.Session.InfiniteTimeSpan)
+                    break;
+                // give channels time to process pending requests
+                ThreadAbstraction.Sleep(50);
+            }
+        }
+
+        /// <summary>
+        /// Ensures the current instance is not disposed.
+        /// </summary>
+        /// <exception cref="ObjectDisposedException">The current instance is disposed.</exception>
+        protected override void CheckDisposed()
+        {
+            if (_isDisposed)
+                throw new ObjectDisposedException(GetType().FullName);
+        }
+
+        private void Session_ChannelOpening(object sender, MessageEventArgs<ChannelOpenMessage> e)
+        {
+            var channelOpenMessage = e.Message;
+            var info = channelOpenMessage.Info as ForwardedTcpipChannelInfo;
+            if (info != null)
+            {
+                //  Ensure this is the corresponding request
+                if (info.ConnectedAddress == BoundHost && info.ConnectedPort == BoundPort)
+                {
+                    if (!_isStarted)
+                    {
+                        Session.SendMessage(new ChannelOpenFailureMessage(channelOpenMessage.LocalChannelNumber, "", ChannelOpenFailureMessage.AdministrativelyProhibited));
+                        return;
+                    }
+
+                    ThreadAbstraction.ExecuteThread(() =>
+                        {
+                            Interlocked.Increment(ref _pendingRequests);
+
+                            try
+                            {
+                                RaiseRequestReceived(info.OriginatorAddress, info.OriginatorPort);
+
+                                using (var channel = Session.CreateChannelForwardedTcpip(channelOpenMessage.LocalChannelNumber, channelOpenMessage.InitialWindowSize, channelOpenMessage.MaximumPacketSize))
+                                {
+                                    channel.Exception += Channel_Exception;
+                                    channel.Bind(new IPEndPoint(HostAddress, (int) Port), this);
+                                    channel.Close();
+                                }
+                            }
+                            catch (Exception exp)
+                            {
+                                RaiseExceptionEvent(exp);
+                            }
+                            finally
+                            {
+                                Interlocked.Decrement(ref _pendingRequests);
+                            }
+                        });
+                }
+            }
+        }
+
+        private void Channel_Exception(object sender, ExceptionEventArgs exceptionEventArgs)
+        {
+            RaiseExceptionEvent(exceptionEventArgs.Exception);
+        }
+
+        private void Session_RequestFailure(object sender, EventArgs e)
+        {
+            _requestStatus = false;
+            _globalRequestResponse.Set();
+        }
+
+        private void Session_RequestSuccess(object sender, MessageEventArgs<RequestSuccessMessage> e)
+        {
+            _requestStatus = true;
+            if (BoundPort == 0)
+            {
+                BoundPort = (e.Message.BoundPort == null) ? 0 : e.Message.BoundPort.Value;
+            }
+
+            _globalRequestResponse.Set();
+        }
+
+        #region IDisposable Members
+
+        private bool _isDisposed;
+
+        /// <summary>
+        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+        /// </summary>
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources
+        /// </summary>
+        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (_isDisposed)
+                return;
+
+            base.Dispose(disposing);
+
+            if (disposing)
+            {
+                var session = Session;
+                if (session != null)
+                {
+                    session.RequestSuccessReceived -= Session_RequestSuccess;
+                    session.RequestFailureReceived -= Session_RequestFailure;
+                    session.ChannelOpenReceived -= Session_ChannelOpening;
+                    Session = null;
+                }
+
+                var globalRequestResponse = _globalRequestResponse;
+                if (globalRequestResponse != null)
+                {
+                    globalRequestResponse.Dispose();
+                    _globalRequestResponse = null;
+                }
+            }
+
+            _isDisposed = true;
+        }
+
+        /// <summary>
+        /// Releases unmanaged resources and performs other cleanup operations before the
+        /// <see cref="ForwardedPortRemote"/> is reclaimed by garbage collection.
+        /// </summary>
+        ~ForwardedPortRemote()
+        {
+            Dispose(false);
+        }
+
+        #endregion
+    }
+}

+ 35 - 35
src/Renci.SshNet/HashInfo.cs

@@ -1,35 +1,35 @@
-using System;
-using System.Security.Cryptography;
-
-namespace Renci.SshNet
-{
-    /// <summary>
-    /// Holds information about key size and cipher to use
-    /// </summary>
-    public class HashInfo
-    {
-        /// <summary>
-        /// Gets the size of the key.
-        /// </summary>
-        /// <value>
-        /// The size of the key.
-        /// </value>
-        public int KeySize { get; private set; }
-
-        /// <summary>
-        /// Gets the cipher.
-        /// </summary>
-        public Func<byte[], HashAlgorithm> HashAlgorithm { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="CipherInfo"/> class.
-        /// </summary>
-        /// <param name="keySize">Size of the key.</param>
-        /// <param name="hash">The hash algorithm to use for a given key.</param>
-        public HashInfo(int keySize, Func<byte[], HashAlgorithm> hash)
-        {
-            KeySize = keySize;
-            HashAlgorithm = key => (hash(key.Take(KeySize / 8)));
-        }
-    }
-}
+using System;
+using System.Security.Cryptography;
+
+namespace Renci.SshNet
+{
+    /// <summary>
+    /// Holds information about key size and cipher to use
+    /// </summary>
+    public class HashInfo
+    {
+        /// <summary>
+        /// Gets the size of the key.
+        /// </summary>
+        /// <value>
+        /// The size of the key.
+        /// </value>
+        public int KeySize { get; private set; }
+
+        /// <summary>
+        /// Gets the cipher.
+        /// </summary>
+        public Func<byte[], HashAlgorithm> HashAlgorithm { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="CipherInfo"/> class.
+        /// </summary>
+        /// <param name="keySize">Size of the key.</param>
+        /// <param name="hash">The hash algorithm to use for a given key.</param>
+        public HashInfo(int keySize, Func<byte[], HashAlgorithm> hash)
+        {
+            KeySize = keySize;
+            HashAlgorithm = key => (hash(key.Take(KeySize / 8)));
+        }
+    }
+}

+ 35 - 35
src/Renci.SshNet/IAuthenticationMethod.cs

@@ -1,35 +1,35 @@
-using System.Collections.Generic;
-
-namespace Renci.SshNet
-{
-    /// <summary>
-    /// Base interface for authentication of a session using a given method.
-    /// </summary>
-    internal interface IAuthenticationMethod
-    {
-        /// <summary>
-        /// Authenticates the specified session.
-        /// </summary>
-        /// <param name="session">The session to authenticate.</param>
-        /// <returns>
-        /// The result of the authentication process.
-        /// </returns>
-        AuthenticationResult Authenticate(ISession session);
-
-        /// <summary>
-        /// Gets the list of allowed authentications.
-        /// </summary>
-        /// <value>
-        /// The list of allowed authentications.
-        /// </value>
-        IList<string> AllowedAuthentications { get; }
-
-        /// <summary>
-        /// Gets the name of the authentication method.
-        /// </summary>
-        /// <value>
-        /// The name of the authentication method.
-        /// </value>
-        string Name { get; }
-    }
-}
+using System.Collections.Generic;
+
+namespace Renci.SshNet
+{
+    /// <summary>
+    /// Base interface for authentication of a session using a given method.
+    /// </summary>
+    internal interface IAuthenticationMethod
+    {
+        /// <summary>
+        /// Authenticates the specified session.
+        /// </summary>
+        /// <param name="session">The session to authenticate.</param>
+        /// <returns>
+        /// The result of the authentication process.
+        /// </returns>
+        AuthenticationResult Authenticate(ISession session);
+
+        /// <summary>
+        /// Gets the list of allowed authentications.
+        /// </summary>
+        /// <value>
+        /// The list of allowed authentications.
+        /// </value>
+        IList<string> AllowedAuthentications { get; }
+
+        /// <summary>
+        /// Gets the name of the authentication method.
+        /// </summary>
+        /// <value>
+        /// The name of the authentication method.
+        /// </value>
+        string Name { get; }
+    }
+}

+ 7 - 7
src/Renci.SshNet/IClientAuthentication.cs

@@ -1,7 +1,7 @@
-namespace Renci.SshNet
-{
-    internal interface IClientAuthentication
-    {
-        void Authenticate(IConnectionInfoInternal connectionInfo, ISession session);
-    }
-}
+namespace Renci.SshNet
+{
+    internal interface IClientAuthentication
+    {
+        void Authenticate(IConnectionInfoInternal connectionInfo, ISession session);
+    }
+}

+ 83 - 83
src/Renci.SshNet/IConnectionInfo.cs

@@ -1,83 +1,83 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using Renci.SshNet.Common;
-using Renci.SshNet.Messages.Authentication;
-using Renci.SshNet.Messages.Connection;
-
-namespace Renci.SshNet
-{
-    internal interface IConnectionInfoInternal : IConnectionInfo
-    {
-        /// <summary>
-        /// Signals that an authentication banner message was received from the server.
-        /// </summary>
-        /// <param name="sender">The session in which the banner message was received.</param>
-        /// <param name="e">The banner message.{</param>
-        void UserAuthenticationBannerReceived(object sender, MessageEventArgs<BannerMessage> e);
-
-        /// <summary>
-        /// Gets the supported authentication methods for this connection.
-        /// </summary>
-        /// <value>
-        /// The supported authentication methods for this connection.
-        /// </value>
-        IList<IAuthenticationMethod> AuthenticationMethods { get; }
-
-        /// <summary>
-        /// Creates a <see cref="NoneAuthenticationMethod"/> for the credentials represented
-        /// by the current <see cref="IConnectionInfo"/>.
-        /// </summary>
-        /// <returns>
-        /// A <see cref="NoneAuthenticationMethod"/> for the credentials represented by the
-        /// current <see cref="IConnectionInfo"/>.
-        /// </returns>
-        IAuthenticationMethod CreateNoneAuthenticationMethod();
-    }
-
-    /// <summary>
-    /// Represents remote connection information.
-    /// </summary>
-    internal interface IConnectionInfo
-    {
-        /// <summary>
-        /// Gets the supported channel requests for this connection.
-        /// </summary>
-        /// <value>
-        /// The supported channel requests for this connection.
-        /// </value>
-        IDictionary<string, RequestInfo> ChannelRequests { get; }
-
-        /// <summary>
-        /// Gets the character encoding.
-        /// </summary>
-        /// <value>
-        /// The character encoding.
-        /// </value>
-        Encoding Encoding { get; }
-
-        /// <summary>
-        /// Gets the number of retry attempts when session channel creation failed.
-        /// </summary>
-        /// <value>
-        /// The number of retry attempts when session channel creation failed.
-        /// </value>
-        int RetryAttempts { get; }
-
-        /// <summary>
-        /// Gets or sets connection timeout.
-        /// </summary>
-        /// <value>
-        /// The connection timeout. The default value is 30 seconds.
-        /// </value>
-        /// <example>
-        ///   <code source="..\..\Renci.SshNet.Tests\Classes\SshClientTest.cs" region="Example SshClient Connect Timeout" language="C#" title="Specify connection timeout" />
-        /// </example>
-        TimeSpan Timeout { get; }
-
-        /// <summary>
-        /// Occurs when authentication banner is sent by the server.
-        /// </summary>
-        event EventHandler<AuthenticationBannerEventArgs> AuthenticationBanner;
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Renci.SshNet.Common;
+using Renci.SshNet.Messages.Authentication;
+using Renci.SshNet.Messages.Connection;
+
+namespace Renci.SshNet
+{
+    internal interface IConnectionInfoInternal : IConnectionInfo
+    {
+        /// <summary>
+        /// Signals that an authentication banner message was received from the server.
+        /// </summary>
+        /// <param name="sender">The session in which the banner message was received.</param>
+        /// <param name="e">The banner message.{</param>
+        void UserAuthenticationBannerReceived(object sender, MessageEventArgs<BannerMessage> e);
+
+        /// <summary>
+        /// Gets the supported authentication methods for this connection.
+        /// </summary>
+        /// <value>
+        /// The supported authentication methods for this connection.
+        /// </value>
+        IList<IAuthenticationMethod> AuthenticationMethods { get; }
+
+        /// <summary>
+        /// Creates a <see cref="NoneAuthenticationMethod"/> for the credentials represented
+        /// by the current <see cref="IConnectionInfo"/>.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="NoneAuthenticationMethod"/> for the credentials represented by the
+        /// current <see cref="IConnectionInfo"/>.
+        /// </returns>
+        IAuthenticationMethod CreateNoneAuthenticationMethod();
+    }
+
+    /// <summary>
+    /// Represents remote connection information.
+    /// </summary>
+    internal interface IConnectionInfo
+    {
+        /// <summary>
+        /// Gets the supported channel requests for this connection.
+        /// </summary>
+        /// <value>
+        /// The supported channel requests for this connection.
+        /// </value>
+        IDictionary<string, RequestInfo> ChannelRequests { get; }
+
+        /// <summary>
+        /// Gets the character encoding.
+        /// </summary>
+        /// <value>
+        /// The character encoding.
+        /// </value>
+        Encoding Encoding { get; }
+
+        /// <summary>
+        /// Gets the number of retry attempts when session channel creation failed.
+        /// </summary>
+        /// <value>
+        /// The number of retry attempts when session channel creation failed.
+        /// </value>
+        int RetryAttempts { get; }
+
+        /// <summary>
+        /// Gets or sets connection timeout.
+        /// </summary>
+        /// <value>
+        /// The connection timeout. The default value is 30 seconds.
+        /// </value>
+        /// <example>
+        ///   <code source="..\..\Renci.SshNet.Tests\Classes\SshClientTest.cs" region="Example SshClient Connect Timeout" language="C#" title="Specify connection timeout" />
+        /// </example>
+        TimeSpan Timeout { get; }
+
+        /// <summary>
+        /// Occurs when authentication banner is sent by the server.
+        /// </summary>
+        event EventHandler<AuthenticationBannerEventArgs> AuthenticationBanner;
+    }
+}

+ 15 - 15
src/Renci.SshNet/IForwardedPort.cs

@@ -1,15 +1,15 @@
-using System;
-
-namespace Renci.SshNet
-{
-    /// <summary>
-    /// Supports port forwarding functionality.
-    /// </summary>
-    public interface IForwardedPort
-    {
-        /// <summary>
-        /// The <see cref="Closing"/> event occurs as the forwarded port is being stopped.
-        /// </summary>
-        event EventHandler Closing;
-    }
-}
+using System;
+
+namespace Renci.SshNet
+{
+    /// <summary>
+    /// Supports port forwarding functionality.
+    /// </summary>
+    public interface IForwardedPort
+    {
+        /// <summary>
+        /// The <see cref="Closing"/> event occurs as the forwarded port is being stopped.
+        /// </summary>
+        event EventHandler Closing;
+    }
+}

+ 19 - 19
src/Renci.SshNet/IServiceFactory.NET.cs

@@ -1,19 +1,19 @@
-using System;
-using Renci.SshNet.NetConf;
-
-namespace Renci.SshNet
-{
-    internal partial interface IServiceFactory
-    {
-        /// <summary>
-        /// Creates a new <see cref="INetConfSession"/> in a given <see cref="ISession"/>
-        /// and with the specified operation timeout.
-        /// </summary>
-        /// <param name="session">The <see cref="ISession"/> to create the <see cref="INetConfSession"/> in.</param>
-        /// <param name="operationTimeout">The operation timeout.</param>
-        /// <returns>
-        /// An <see cref="INetConfSession"/>.
-        /// </returns>
-        INetConfSession CreateNetConfSession(ISession session, TimeSpan operationTimeout);
-    }
-}
+using System;
+using Renci.SshNet.NetConf;
+
+namespace Renci.SshNet
+{
+    internal partial interface IServiceFactory
+    {
+        /// <summary>
+        /// Creates a new <see cref="INetConfSession"/> in a given <see cref="ISession"/>
+        /// and with the specified operation timeout.
+        /// </summary>
+        /// <param name="session">The <see cref="ISession"/> to create the <see cref="INetConfSession"/> in.</param>
+        /// <param name="operationTimeout">The operation timeout.</param>
+        /// <returns>
+        /// An <see cref="INetConfSession"/>.
+        /// </returns>
+        INetConfSession CreateNetConfSession(ISession session, TimeSpan operationTimeout);
+    }
+}

+ 61 - 61
src/Renci.SshNet/IServiceFactory.cs

@@ -1,61 +1,61 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using Renci.SshNet.Common;
-using Renci.SshNet.Security;
-using Renci.SshNet.Sftp;
-
-namespace Renci.SshNet
-{
-    /// <summary>
-    /// Factory for creating new services.
-    /// </summary>
-    internal partial interface IServiceFactory
-    {
-        IClientAuthentication CreateClientAuthentication();
-
-        /// <summary>
-        /// Creates a new <see cref="ISession"/> with the specified <see cref="ConnectionInfo"/>.
-        /// </summary>
-        /// <param name="connectionInfo">The <see cref="ConnectionInfo"/> to use for creating a new session.</param>
-        /// <returns>
-        /// An <see cref="ISession"/> for the specified <see cref="ConnectionInfo"/>.
-        /// </returns>
-        /// <exception cref="ArgumentNullException"><paramref name="connectionInfo"/> is <c>null</c>.</exception>
-        ISession CreateSession(ConnectionInfo connectionInfo);
-
-        /// <summary>
-        /// Creates a new <see cref="ISftpSession"/> in a given <see cref="ISession"/> and with
-        /// the specified operation timeout and encoding.
-        /// </summary>
-        /// <param name="session">The <see cref="ISession"/> to create the <see cref="ISftpSession"/> in.</param>
-        /// <param name="operationTimeout">The operation timeout.</param>
-        /// <param name="encoding">The encoding.</param>
-        /// <returns>
-        /// An <see cref="ISftpSession"/>.
-        /// </returns>
-        ISftpSession CreateSftpSession(ISession session, TimeSpan operationTimeout, Encoding encoding);
-
-        /// <summary>
-        /// Create a new <see cref="PipeStream"/>.
-        /// </summary>
-        /// <returns>
-        /// A <see cref="PipeStream"/>.
-        /// </returns>
-        PipeStream CreatePipeStream();
-
-        /// <summary>
-        /// Negotiates a key exchange algorithm, and creates a <see cref="IKeyExchange" /> for the negotiated
-        /// algorithm.
-        /// </summary>
-        /// <param name="clientAlgorithms">A <see cref="IDictionary{String, Type}"/> of the key exchange algorithms supported by the client where the key is the name of the algorithm, and the value is the type implementing this algorithm.</param>
-        /// <param name="serverAlgorithms">The names of the key exchange algorithms supported by the SSH server.</param>
-        /// <returns>
-        /// A <see cref="IKeyExchange"/> that was negotiated between client and server.
-        /// </returns>
-        /// <exception cref="ArgumentNullException"><paramref name="clientAlgorithms"/> is <c>null</c>.</exception>
-        /// <exception cref="ArgumentNullException"><paramref name="serverAlgorithms"/> is <c>null</c>.</exception>
-        /// <exception cref="SshConnectionException">No key exchange algorithm is supported by both client and server.</exception>
-        IKeyExchange CreateKeyExchange(IDictionary<string, Type> clientAlgorithms, string[] serverAlgorithms);
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Renci.SshNet.Common;
+using Renci.SshNet.Security;
+using Renci.SshNet.Sftp;
+
+namespace Renci.SshNet
+{
+    /// <summary>
+    /// Factory for creating new services.
+    /// </summary>
+    internal partial interface IServiceFactory
+    {
+        IClientAuthentication CreateClientAuthentication();
+
+        /// <summary>
+        /// Creates a new <see cref="ISession"/> with the specified <see cref="ConnectionInfo"/>.
+        /// </summary>
+        /// <param name="connectionInfo">The <see cref="ConnectionInfo"/> to use for creating a new session.</param>
+        /// <returns>
+        /// An <see cref="ISession"/> for the specified <see cref="ConnectionInfo"/>.
+        /// </returns>
+        /// <exception cref="ArgumentNullException"><paramref name="connectionInfo"/> is <c>null</c>.</exception>
+        ISession CreateSession(ConnectionInfo connectionInfo);
+
+        /// <summary>
+        /// Creates a new <see cref="ISftpSession"/> in a given <see cref="ISession"/> and with
+        /// the specified operation timeout and encoding.
+        /// </summary>
+        /// <param name="session">The <see cref="ISession"/> to create the <see cref="ISftpSession"/> in.</param>
+        /// <param name="operationTimeout">The operation timeout.</param>
+        /// <param name="encoding">The encoding.</param>
+        /// <returns>
+        /// An <see cref="ISftpSession"/>.
+        /// </returns>
+        ISftpSession CreateSftpSession(ISession session, TimeSpan operationTimeout, Encoding encoding);
+
+        /// <summary>
+        /// Create a new <see cref="PipeStream"/>.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="PipeStream"/>.
+        /// </returns>
+        PipeStream CreatePipeStream();
+
+        /// <summary>
+        /// Negotiates a key exchange algorithm, and creates a <see cref="IKeyExchange" /> for the negotiated
+        /// algorithm.
+        /// </summary>
+        /// <param name="clientAlgorithms">A <see cref="IDictionary{String, Type}"/> of the key exchange algorithms supported by the client where the key is the name of the algorithm, and the value is the type implementing this algorithm.</param>
+        /// <param name="serverAlgorithms">The names of the key exchange algorithms supported by the SSH server.</param>
+        /// <returns>
+        /// A <see cref="IKeyExchange"/> that was negotiated between client and server.
+        /// </returns>
+        /// <exception cref="ArgumentNullException"><paramref name="clientAlgorithms"/> is <c>null</c>.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="serverAlgorithms"/> is <c>null</c>.</exception>
+        /// <exception cref="SshConnectionException">No key exchange algorithm is supported by both client and server.</exception>
+        IKeyExchange CreateKeyExchange(IDictionary<string, Type> clientAlgorithms, string[] serverAlgorithms);
+    }
+}

+ 229 - 229
src/Renci.SshNet/ISession.cs

@@ -1,229 +1,229 @@
-using System;
-using System.Net.Sockets;
-using System.Threading;
-using Renci.SshNet.Channels;
-using Renci.SshNet.Common;
-using Renci.SshNet.Messages;
-using Renci.SshNet.Messages.Authentication;
-using Renci.SshNet.Messages.Connection;
-
-namespace Renci.SshNet
-{
-    /// <summary>
-    /// Provides functionality to connect and interact with SSH server.
-    /// </summary>
-    internal interface ISession : IDisposable
-    {
-        /// <summary>
-        /// Gets or sets the connection info.
-        /// </summary>
-        /// <value>The connection info.</value>
-        IConnectionInfo ConnectionInfo { get; }
-
-        /// <summary>
-        /// Gets a value indicating whether the session is connected.
-        /// </summary>
-        /// <value>
-        /// <c>true</c> if the session is connected; otherwise, <c>false</c>.
-        /// </value>
-        bool IsConnected { get; }
-
-        /// <summary>
-        /// Gets the session semaphore that controls session channels.
-        /// </summary>
-        /// <value>
-        /// The session semaphore.
-        /// </value>
-        SemaphoreLight SessionSemaphore { get; }
-
-        /// <summary>
-        /// Gets a <see cref="WaitHandle"/> that can be used to wait for the message listener loop to complete.
-        /// </summary>
-        /// <value>
-        /// A <see cref="WaitHandle"/> that can be used to wait for the message listener loop to complete, or
-        /// <c>null</c> when the session has not been connected.
-        /// </value>
-        WaitHandle MessageListenerCompleted { get; }
-
-        /// <summary>
-        /// Connects to the server.
-        /// </summary>
-        /// <exception cref="SocketException">Socket connection to the SSH server or proxy server could not be established, or an error occurred while resolving the hostname.</exception>
-        /// <exception cref="SshConnectionException">SSH session could not be established.</exception>
-        /// <exception cref="SshAuthenticationException">Authentication of SSH session failed.</exception>
-        /// <exception cref="ProxyException">Failed to establish proxy connection.</exception>
-        void Connect();
-
-        /// <summary>
-        /// Create a new SSH session channel.
-        /// </summary>
-        /// <returns>
-        /// A new SSH session channel.
-        /// </returns>
-        IChannelSession CreateChannelSession();
-
-        /// <summary>
-        /// Create a new channel for a locally forwarded TCP/IP port.
-        /// </summary>
-        /// <returns>
-        /// A new channel for a locally forwarded TCP/IP port.
-        /// </returns>
-        IChannelDirectTcpip CreateChannelDirectTcpip();
-
-        /// <summary>
-        /// Creates a "forwarded-tcpip" SSH channel.
-        /// </summary>
-        /// <returns>
-        /// A new "forwarded-tcpip" SSH channel.
-        /// </returns>
-        IChannelForwardedTcpip CreateChannelForwardedTcpip(uint remoteChannelNumber, uint remoteWindowSize, uint remoteChannelDataPacketSize);
-
-        /// <summary>
-        /// Disconnects from the server.
-        /// </summary>
-        /// <remarks>
-        /// This sends a <b>SSH_MSG_DISCONNECT</b> message to the server, waits for the
-        /// server to close the socket on its end and subsequently closes the client socket.
-        /// </remarks>
-        void Disconnect();
-
-        /// <summary>
-        /// Called when client is disconnecting from the server.
-        /// </summary>
-        void OnDisconnecting();
-
-        /// <summary>
-        /// Registers SSH message with the session.
-        /// </summary>
-        /// <param name="messageName">The name of the message to register with the session.</param>
-        void RegisterMessage(string messageName);
-
-        /// <summary>
-        /// Sends a message to the server.
-        /// </summary>
-        /// <param name="message">The message to send.</param>
-        /// <exception cref="SshConnectionException">The client is not connected.</exception>
-        /// <exception cref="SshOperationTimeoutException">The operation timed out.</exception>
-        /// <exception cref="InvalidOperationException">The size of the packet exceeds the maximum size defined by the protocol.</exception>
-        void SendMessage(Message message);
-
-        /// <summary>
-        /// Sends a message to the server.
-        /// </summary>
-        /// <param name="message">The message to send.</param>
-        /// <returns>
-        /// <c>true</c> if the message was sent to the server; otherwise, <c>false</c>.
-        /// </returns>
-        /// <exception cref="InvalidOperationException">The size of the packet exceeds the maximum size defined by the protocol.</exception>
-        /// <remarks>
-        /// This methods returns <c>false</c> when the attempt to send the message results in a
-        /// <see cref="SocketException"/> or a <see cref="SshException"/>.
-        /// </remarks>
-        bool TrySendMessage(Message message);
-
-        /// <summary>
-        /// Unregister SSH message from the session.
-        /// </summary>
-        /// <param name="messageName">The name of the message to unregister with the session.</param>
-        void UnRegisterMessage(string messageName);
-
-        /// <summary>
-        /// Waits for the specified handle or the exception handle for the receive thread
-        /// to signal within the connection timeout.
-        /// </summary>
-        /// <param name="waitHandle">The wait handle.</param>
-        /// <exception cref="SshConnectionException">A received package was invalid or failed the message integrity check.</exception>
-        /// <exception cref="SshOperationTimeoutException">None of the handles are signaled in time and the session is not disconnecting.</exception>
-        /// <exception cref="SocketException">A socket error was signaled while receiving messages from the server.</exception>
-        /// <remarks>
-        /// When neither handles are signaled in time and the session is not closing, then the
-        /// session is disconnected.
-        /// </remarks>
-        void WaitOnHandle(WaitHandle waitHandle);
-
-        /// <summary>
-        /// Occurs when <see cref="ChannelCloseMessage"/> message received
-        /// </summary>
-        event EventHandler<MessageEventArgs<ChannelCloseMessage>> ChannelCloseReceived;
-
-        /// <summary>
-        /// Occurs when <see cref="ChannelDataMessage"/> message received
-        /// </summary>
-        event EventHandler<MessageEventArgs<ChannelDataMessage>> ChannelDataReceived;
-
-        /// <summary>
-        /// Occurs when <see cref="ChannelEofMessage"/> message received
-        /// </summary>
-        event EventHandler<MessageEventArgs<ChannelEofMessage>> ChannelEofReceived;
-
-        /// <summary>
-        /// Occurs when <see cref="ChannelExtendedDataMessage"/> message received
-        /// </summary>
-        event EventHandler<MessageEventArgs<ChannelExtendedDataMessage>> ChannelExtendedDataReceived;
-
-        /// <summary>
-        /// Occurs when <see cref="ChannelFailureMessage"/> message received
-        /// </summary>
-        event EventHandler<MessageEventArgs<ChannelFailureMessage>> ChannelFailureReceived;
-
-        /// <summary>
-        /// Occurs when <see cref="ChannelOpenConfirmationMessage"/> message received
-        /// </summary>
-        event EventHandler<MessageEventArgs<ChannelOpenConfirmationMessage>> ChannelOpenConfirmationReceived;
-
-        /// <summary>
-        /// Occurs when <see cref="ChannelOpenFailureMessage"/> message received
-        /// </summary>
-        event EventHandler<MessageEventArgs<ChannelOpenFailureMessage>> ChannelOpenFailureReceived;
-
-        /// <summary>
-        /// Occurs when <see cref="ChannelOpenMessage"/> message received
-        /// </summary>
-        event EventHandler<MessageEventArgs<ChannelOpenMessage>> ChannelOpenReceived;
-
-        /// <summary>
-        /// Occurs when <see cref="ChannelRequestMessage"/> message received
-        /// </summary>
-        event EventHandler<MessageEventArgs<ChannelRequestMessage>> ChannelRequestReceived;
-
-        /// <summary>
-        /// Occurs when <see cref="ChannelSuccessMessage"/> message received
-        /// </summary>
-        event EventHandler<MessageEventArgs<ChannelSuccessMessage>> ChannelSuccessReceived;
-
-        /// <summary>
-        /// Occurs when <see cref="ChannelWindowAdjustMessage"/> message received
-        /// </summary>
-        event EventHandler<MessageEventArgs<ChannelWindowAdjustMessage>> ChannelWindowAdjustReceived;
-
-        /// <summary>
-        /// Occurs when session has been disconnected from the server.
-        /// </summary>
-        event EventHandler<EventArgs> Disconnected;
-
-        /// <summary>
-        /// Occurs when an error occurred.
-        /// </summary>
-        event EventHandler<ExceptionEventArgs> ErrorOccured;
-
-        /// <summary>
-        /// Occurs when host key received.
-        /// </summary>
-        event EventHandler<HostKeyEventArgs> HostKeyReceived;
-
-        /// <summary>
-        /// Occurs when <see cref="RequestSuccessMessage"/> message received
-        /// </summary>
-        event EventHandler<MessageEventArgs<RequestSuccessMessage>> RequestSuccessReceived;
-
-        /// <summary>
-        /// Occurs when <see cref="RequestFailureMessage"/> message received
-        /// </summary>
-        event EventHandler<MessageEventArgs<RequestFailureMessage>> RequestFailureReceived;
-
-        /// <summary>
-        /// Occurs when <see cref="BannerMessage"/> message is received from the server.
-        /// </summary>
-        event EventHandler<MessageEventArgs<BannerMessage>> UserAuthenticationBannerReceived;
-    }
-}
+using System;
+using System.Net.Sockets;
+using System.Threading;
+using Renci.SshNet.Channels;
+using Renci.SshNet.Common;
+using Renci.SshNet.Messages;
+using Renci.SshNet.Messages.Authentication;
+using Renci.SshNet.Messages.Connection;
+
+namespace Renci.SshNet
+{
+    /// <summary>
+    /// Provides functionality to connect and interact with SSH server.
+    /// </summary>
+    internal interface ISession : IDisposable
+    {
+        /// <summary>
+        /// Gets or sets the connection info.
+        /// </summary>
+        /// <value>The connection info.</value>
+        IConnectionInfo ConnectionInfo { get; }
+
+        /// <summary>
+        /// Gets a value indicating whether the session is connected.
+        /// </summary>
+        /// <value>
+        /// <c>true</c> if the session is connected; otherwise, <c>false</c>.
+        /// </value>
+        bool IsConnected { get; }
+
+        /// <summary>
+        /// Gets the session semaphore that controls session channels.
+        /// </summary>
+        /// <value>
+        /// The session semaphore.
+        /// </value>
+        SemaphoreLight SessionSemaphore { get; }
+
+        /// <summary>
+        /// Gets a <see cref="WaitHandle"/> that can be used to wait for the message listener loop to complete.
+        /// </summary>
+        /// <value>
+        /// A <see cref="WaitHandle"/> that can be used to wait for the message listener loop to complete, or
+        /// <c>null</c> when the session has not been connected.
+        /// </value>
+        WaitHandle MessageListenerCompleted { get; }
+
+        /// <summary>
+        /// Connects to the server.
+        /// </summary>
+        /// <exception cref="SocketException">Socket connection to the SSH server or proxy server could not be established, or an error occurred while resolving the hostname.</exception>
+        /// <exception cref="SshConnectionException">SSH session could not be established.</exception>
+        /// <exception cref="SshAuthenticationException">Authentication of SSH session failed.</exception>
+        /// <exception cref="ProxyException">Failed to establish proxy connection.</exception>
+        void Connect();
+
+        /// <summary>
+        /// Create a new SSH session channel.
+        /// </summary>
+        /// <returns>
+        /// A new SSH session channel.
+        /// </returns>
+        IChannelSession CreateChannelSession();
+
+        /// <summary>
+        /// Create a new channel for a locally forwarded TCP/IP port.
+        /// </summary>
+        /// <returns>
+        /// A new channel for a locally forwarded TCP/IP port.
+        /// </returns>
+        IChannelDirectTcpip CreateChannelDirectTcpip();
+
+        /// <summary>
+        /// Creates a "forwarded-tcpip" SSH channel.
+        /// </summary>
+        /// <returns>
+        /// A new "forwarded-tcpip" SSH channel.
+        /// </returns>
+        IChannelForwardedTcpip CreateChannelForwardedTcpip(uint remoteChannelNumber, uint remoteWindowSize, uint remoteChannelDataPacketSize);
+
+        /// <summary>
+        /// Disconnects from the server.
+        /// </summary>
+        /// <remarks>
+        /// This sends a <b>SSH_MSG_DISCONNECT</b> message to the server, waits for the
+        /// server to close the socket on its end and subsequently closes the client socket.
+        /// </remarks>
+        void Disconnect();
+
+        /// <summary>
+        /// Called when client is disconnecting from the server.
+        /// </summary>
+        void OnDisconnecting();
+
+        /// <summary>
+        /// Registers SSH message with the session.
+        /// </summary>
+        /// <param name="messageName">The name of the message to register with the session.</param>
+        void RegisterMessage(string messageName);
+
+        /// <summary>
+        /// Sends a message to the server.
+        /// </summary>
+        /// <param name="message">The message to send.</param>
+        /// <exception cref="SshConnectionException">The client is not connected.</exception>
+        /// <exception cref="SshOperationTimeoutException">The operation timed out.</exception>
+        /// <exception cref="InvalidOperationException">The size of the packet exceeds the maximum size defined by the protocol.</exception>
+        void SendMessage(Message message);
+
+        /// <summary>
+        /// Sends a message to the server.
+        /// </summary>
+        /// <param name="message">The message to send.</param>
+        /// <returns>
+        /// <c>true</c> if the message was sent to the server; otherwise, <c>false</c>.
+        /// </returns>
+        /// <exception cref="InvalidOperationException">The size of the packet exceeds the maximum size defined by the protocol.</exception>
+        /// <remarks>
+        /// This methods returns <c>false</c> when the attempt to send the message results in a
+        /// <see cref="SocketException"/> or a <see cref="SshException"/>.
+        /// </remarks>
+        bool TrySendMessage(Message message);
+
+        /// <summary>
+        /// Unregister SSH message from the session.
+        /// </summary>
+        /// <param name="messageName">The name of the message to unregister with the session.</param>
+        void UnRegisterMessage(string messageName);
+
+        /// <summary>
+        /// Waits for the specified handle or the exception handle for the receive thread
+        /// to signal within the connection timeout.
+        /// </summary>
+        /// <param name="waitHandle">The wait handle.</param>
+        /// <exception cref="SshConnectionException">A received package was invalid or failed the message integrity check.</exception>
+        /// <exception cref="SshOperationTimeoutException">None of the handles are signaled in time and the session is not disconnecting.</exception>
+        /// <exception cref="SocketException">A socket error was signaled while receiving messages from the server.</exception>
+        /// <remarks>
+        /// When neither handles are signaled in time and the session is not closing, then the
+        /// session is disconnected.
+        /// </remarks>
+        void WaitOnHandle(WaitHandle waitHandle);
+
+        /// <summary>
+        /// Occurs when <see cref="ChannelCloseMessage"/> message received
+        /// </summary>
+        event EventHandler<MessageEventArgs<ChannelCloseMessage>> ChannelCloseReceived;
+
+        /// <summary>
+        /// Occurs when <see cref="ChannelDataMessage"/> message received
+        /// </summary>
+        event EventHandler<MessageEventArgs<ChannelDataMessage>> ChannelDataReceived;
+
+        /// <summary>
+        /// Occurs when <see cref="ChannelEofMessage"/> message received
+        /// </summary>
+        event EventHandler<MessageEventArgs<ChannelEofMessage>> ChannelEofReceived;
+
+        /// <summary>
+        /// Occurs when <see cref="ChannelExtendedDataMessage"/> message received
+        /// </summary>
+        event EventHandler<MessageEventArgs<ChannelExtendedDataMessage>> ChannelExtendedDataReceived;
+
+        /// <summary>
+        /// Occurs when <see cref="ChannelFailureMessage"/> message received
+        /// </summary>
+        event EventHandler<MessageEventArgs<ChannelFailureMessage>> ChannelFailureReceived;
+
+        /// <summary>
+        /// Occurs when <see cref="ChannelOpenConfirmationMessage"/> message received
+        /// </summary>
+        event EventHandler<MessageEventArgs<ChannelOpenConfirmationMessage>> ChannelOpenConfirmationReceived;
+
+        /// <summary>
+        /// Occurs when <see cref="ChannelOpenFailureMessage"/> message received
+        /// </summary>
+        event EventHandler<MessageEventArgs<ChannelOpenFailureMessage>> ChannelOpenFailureReceived;
+
+        /// <summary>
+        /// Occurs when <see cref="ChannelOpenMessage"/> message received
+        /// </summary>
+        event EventHandler<MessageEventArgs<ChannelOpenMessage>> ChannelOpenReceived;
+
+        /// <summary>
+        /// Occurs when <see cref="ChannelRequestMessage"/> message received
+        /// </summary>
+        event EventHandler<MessageEventArgs<ChannelRequestMessage>> ChannelRequestReceived;
+
+        /// <summary>
+        /// Occurs when <see cref="ChannelSuccessMessage"/> message received
+        /// </summary>
+        event EventHandler<MessageEventArgs<ChannelSuccessMessage>> ChannelSuccessReceived;
+
+        /// <summary>
+        /// Occurs when <see cref="ChannelWindowAdjustMessage"/> message received
+        /// </summary>
+        event EventHandler<MessageEventArgs<ChannelWindowAdjustMessage>> ChannelWindowAdjustReceived;
+
+        /// <summary>
+        /// Occurs when session has been disconnected from the server.
+        /// </summary>
+        event EventHandler<EventArgs> Disconnected;
+
+        /// <summary>
+        /// Occurs when an error occurred.
+        /// </summary>
+        event EventHandler<ExceptionEventArgs> ErrorOccured;
+
+        /// <summary>
+        /// Occurs when host key received.
+        /// </summary>
+        event EventHandler<HostKeyEventArgs> HostKeyReceived;
+
+        /// <summary>
+        /// Occurs when <see cref="RequestSuccessMessage"/> message received
+        /// </summary>
+        event EventHandler<MessageEventArgs<RequestSuccessMessage>> RequestSuccessReceived;
+
+        /// <summary>
+        /// Occurs when <see cref="RequestFailureMessage"/> message received
+        /// </summary>
+        event EventHandler<MessageEventArgs<RequestFailureMessage>> RequestFailureReceived;
+
+        /// <summary>
+        /// Occurs when <see cref="BannerMessage"/> message is received from the server.
+        /// </summary>
+        event EventHandler<MessageEventArgs<BannerMessage>> UserAuthenticationBannerReceived;
+    }
+}

+ 42 - 42
src/Renci.SshNet/ISubsystemSession.cs

@@ -1,42 +1,42 @@
-using System;
-using System.Threading;
-using Renci.SshNet.Common;
-
-namespace Renci.SshNet
-{
-    /// <summary>
-    /// Base interface for SSH subsystem implementations.
-    /// </summary>
-    internal interface ISubsystemSession : IDisposable
-    {
-        /// <summary>
-        /// Gets a value indicating whether this session is open.
-        /// </summary>
-        /// <value>
-        /// <c>true</c> if this session is open; otherwise, <c>false</c>.
-        /// </value>
-        bool IsOpen { get; }
-
-        /// <summary>
-        /// Connects the subsystem using a new SSH channel session.
-        /// </summary>
-        /// <exception cref="InvalidOperationException">The session is already connected.</exception>
-        /// <exception cref="ObjectDisposedException">The method was called after the session was disposed.</exception>
-        void Connect();
-
-        /// <summary>
-        /// Disconnects the subsystem channel.
-        /// </summary>
-        void Disconnect();
-
-        /// <summary>
-        /// Waits a specified time for a given <see cref="WaitHandle"/> to get signaled.
-        /// </summary>
-        /// <param name="waitHandle">The handle to wait for.</param>
-        /// <param name="operationTimeout">The time to wait for <paramref name="waitHandle"/> to get signaled.</param>
-        /// <exception cref="SshException">The connection was closed by the server.</exception>
-        /// <exception cref="SshException">The channel was closed.</exception>
-        /// <exception cref="SshOperationTimeoutException">The handle did not get signaled within the specified <paramref name="operationTimeout"/>.</exception>
-        void WaitOnHandle(WaitHandle waitHandle, TimeSpan operationTimeout);
-    }
-}
+using System;
+using System.Threading;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet
+{
+    /// <summary>
+    /// Base interface for SSH subsystem implementations.
+    /// </summary>
+    internal interface ISubsystemSession : IDisposable
+    {
+        /// <summary>
+        /// Gets a value indicating whether this session is open.
+        /// </summary>
+        /// <value>
+        /// <c>true</c> if this session is open; otherwise, <c>false</c>.
+        /// </value>
+        bool IsOpen { get; }
+
+        /// <summary>
+        /// Connects the subsystem using a new SSH channel session.
+        /// </summary>
+        /// <exception cref="InvalidOperationException">The session is already connected.</exception>
+        /// <exception cref="ObjectDisposedException">The method was called after the session was disposed.</exception>
+        void Connect();
+
+        /// <summary>
+        /// Disconnects the subsystem channel.
+        /// </summary>
+        void Disconnect();
+
+        /// <summary>
+        /// Waits a specified time for a given <see cref="WaitHandle"/> to get signaled.
+        /// </summary>
+        /// <param name="waitHandle">The handle to wait for.</param>
+        /// <param name="operationTimeout">The time to wait for <paramref name="waitHandle"/> to get signaled.</param>
+        /// <exception cref="SshException">The connection was closed by the server.</exception>
+        /// <exception cref="SshException">The channel was closed.</exception>
+        /// <exception cref="SshOperationTimeoutException">The handle did not get signaled within the specified <paramref name="operationTimeout"/>.</exception>
+        void WaitOnHandle(WaitHandle waitHandle, TimeSpan operationTimeout);
+    }
+}

+ 181 - 181
src/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.cs

@@ -1,181 +1,181 @@
-using System;
-using System.Linq;
-using System.Threading;
-using Renci.SshNet.Abstractions;
-using Renci.SshNet.Messages;
-using Renci.SshNet.Messages.Authentication;
-using Renci.SshNet.Common;
-
-namespace Renci.SshNet
-{
-    /// <summary>
-    /// Provides functionality to perform keyboard interactive authentication.
-    /// </summary>
-    public class KeyboardInteractiveAuthenticationMethod : AuthenticationMethod, IDisposable
-    {
-        private AuthenticationResult _authenticationResult = AuthenticationResult.Failure;
-
-        private Session _session;
-        private EventWaitHandle _authenticationCompleted = new AutoResetEvent(false);
-        private Exception _exception;
-        private readonly RequestMessage _requestMessage;
-
-        /// <summary>
-        /// Gets authentication method name
-        /// </summary>
-        public override string Name
-        {
-            get { return _requestMessage.MethodName; }
-        }
-
-        /// <summary>
-        /// Occurs when server prompts for more authentication information.
-        /// </summary>
-        public event EventHandler<AuthenticationPromptEventArgs> AuthenticationPrompt;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="KeyboardInteractiveAuthenticationMethod"/> class.
-        /// </summary>
-        /// <param name="username">The username.</param>
-        /// <exception cref="ArgumentException"><paramref name="username"/> is whitespace or null.</exception>
-        public KeyboardInteractiveAuthenticationMethod(string username)
-            : base(username)
-        {
-            _requestMessage = new RequestMessageKeyboardInteractive(ServiceName.Connection, username);
-        }
-
-        /// <summary>
-        /// Authenticates the specified session.
-        /// </summary>
-        /// <param name="session">The session to authenticate.</param>
-        /// <returns>Result of authentication  process.</returns>
-        public override AuthenticationResult Authenticate(Session session)
-        {
-            _session = session;
-
-            session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
-            session.UserAuthenticationFailureReceived += Session_UserAuthenticationFailureReceived;
-            session.MessageReceived += Session_MessageReceived;
-
-            try
-            {
-                session.RegisterMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
-                session.SendMessage(_requestMessage);
-                session.WaitOnHandle(_authenticationCompleted);
-                session.UnRegisterMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
-            }
-            finally
-            {
-                session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
-                session.UserAuthenticationFailureReceived -= Session_UserAuthenticationFailureReceived;
-                session.MessageReceived -= Session_MessageReceived;
-            }
-
-            if (_exception != null)
-                throw _exception;
-
-            return _authenticationResult;
-        }
-
-        private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs<SuccessMessage> e)
-        {
-            _authenticationResult = AuthenticationResult.Success;
-
-            _authenticationCompleted.Set();
-        }
-
-        private void Session_UserAuthenticationFailureReceived(object sender, MessageEventArgs<FailureMessage> e)
-        {
-            if (e.Message.PartialSuccess)
-                _authenticationResult = AuthenticationResult.PartialSuccess;
-            else
-                _authenticationResult = AuthenticationResult.Failure;
-
-            // Copy allowed authentication methods
-            AllowedAuthentications = e.Message.AllowedAuthentications;
-
-            _authenticationCompleted.Set();
-        }
-
-        private void Session_MessageReceived(object sender, MessageEventArgs<Message> e)
-        {
-            var informationRequestMessage = e.Message as InformationRequestMessage;
-            if (informationRequestMessage != null)
-            {
-                var eventArgs = new AuthenticationPromptEventArgs(Username, informationRequestMessage.Instruction, informationRequestMessage.Language, informationRequestMessage.Prompts);
-
-                ThreadAbstraction.ExecuteThread(() =>
-                {
-                    try
-                    {
-                        if (AuthenticationPrompt != null)
-                        {
-                            AuthenticationPrompt(this, eventArgs);
-                        }
-
-                        var informationResponse = new InformationResponseMessage();
-
-                        foreach (var response in from r in eventArgs.Prompts orderby r.Id ascending select r.Response)
-                        {
-                            informationResponse.Responses.Add(response);
-                        }
-
-                        //  Send information response message
-                        _session.SendMessage(informationResponse);
-                    }
-                    catch (Exception exp)
-                    {
-                        _exception = exp;
-                        _authenticationCompleted.Set();
-                    }
-                });
-            }
-        }
-
-        #region IDisposable Members
-
-        private bool _isDisposed;
-
-        /// <summary>
-        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
-        /// </summary>
-        public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
-
-        /// <summary>
-        /// Releases unmanaged and - optionally - managed resources
-        /// </summary>
-        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
-        protected virtual void Dispose(bool disposing)
-        {
-            if (_isDisposed)
-                return;
-
-            if (disposing)
-            {
-                var authenticationCompleted = _authenticationCompleted;
-                if (authenticationCompleted != null)
-                {
-                    authenticationCompleted.Dispose();
-                    _authenticationCompleted = null;
-                }
-
-                _isDisposed = true;
-            }
-        }
-
-        /// <summary>
-        /// Releases unmanaged resources and performs other cleanup operations before the
-        /// <see cref="KeyboardInteractiveAuthenticationMethod"/> is reclaimed by garbage collection.
-        /// </summary>
-        ~KeyboardInteractiveAuthenticationMethod()
-        {
-            Dispose(false);
-        }
-
-        #endregion
-    }
-}
+using System;
+using System.Linq;
+using System.Threading;
+using Renci.SshNet.Abstractions;
+using Renci.SshNet.Messages;
+using Renci.SshNet.Messages.Authentication;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet
+{
+    /// <summary>
+    /// Provides functionality to perform keyboard interactive authentication.
+    /// </summary>
+    public class KeyboardInteractiveAuthenticationMethod : AuthenticationMethod, IDisposable
+    {
+        private AuthenticationResult _authenticationResult = AuthenticationResult.Failure;
+
+        private Session _session;
+        private EventWaitHandle _authenticationCompleted = new AutoResetEvent(false);
+        private Exception _exception;
+        private readonly RequestMessage _requestMessage;
+
+        /// <summary>
+        /// Gets authentication method name
+        /// </summary>
+        public override string Name
+        {
+            get { return _requestMessage.MethodName; }
+        }
+
+        /// <summary>
+        /// Occurs when server prompts for more authentication information.
+        /// </summary>
+        public event EventHandler<AuthenticationPromptEventArgs> AuthenticationPrompt;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="KeyboardInteractiveAuthenticationMethod"/> class.
+        /// </summary>
+        /// <param name="username">The username.</param>
+        /// <exception cref="ArgumentException"><paramref name="username"/> is whitespace or null.</exception>
+        public KeyboardInteractiveAuthenticationMethod(string username)
+            : base(username)
+        {
+            _requestMessage = new RequestMessageKeyboardInteractive(ServiceName.Connection, username);
+        }
+
+        /// <summary>
+        /// Authenticates the specified session.
+        /// </summary>
+        /// <param name="session">The session to authenticate.</param>
+        /// <returns>Result of authentication  process.</returns>
+        public override AuthenticationResult Authenticate(Session session)
+        {
+            _session = session;
+
+            session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
+            session.UserAuthenticationFailureReceived += Session_UserAuthenticationFailureReceived;
+            session.MessageReceived += Session_MessageReceived;
+
+            try
+            {
+                session.RegisterMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
+                session.SendMessage(_requestMessage);
+                session.WaitOnHandle(_authenticationCompleted);
+                session.UnRegisterMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
+            }
+            finally
+            {
+                session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
+                session.UserAuthenticationFailureReceived -= Session_UserAuthenticationFailureReceived;
+                session.MessageReceived -= Session_MessageReceived;
+            }
+
+            if (_exception != null)
+                throw _exception;
+
+            return _authenticationResult;
+        }
+
+        private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs<SuccessMessage> e)
+        {
+            _authenticationResult = AuthenticationResult.Success;
+
+            _authenticationCompleted.Set();
+        }
+
+        private void Session_UserAuthenticationFailureReceived(object sender, MessageEventArgs<FailureMessage> e)
+        {
+            if (e.Message.PartialSuccess)
+                _authenticationResult = AuthenticationResult.PartialSuccess;
+            else
+                _authenticationResult = AuthenticationResult.Failure;
+
+            // Copy allowed authentication methods
+            AllowedAuthentications = e.Message.AllowedAuthentications;
+
+            _authenticationCompleted.Set();
+        }
+
+        private void Session_MessageReceived(object sender, MessageEventArgs<Message> e)
+        {
+            var informationRequestMessage = e.Message as InformationRequestMessage;
+            if (informationRequestMessage != null)
+            {
+                var eventArgs = new AuthenticationPromptEventArgs(Username, informationRequestMessage.Instruction, informationRequestMessage.Language, informationRequestMessage.Prompts);
+
+                ThreadAbstraction.ExecuteThread(() =>
+                {
+                    try
+                    {
+                        if (AuthenticationPrompt != null)
+                        {
+                            AuthenticationPrompt(this, eventArgs);
+                        }
+
+                        var informationResponse = new InformationResponseMessage();
+
+                        foreach (var response in from r in eventArgs.Prompts orderby r.Id ascending select r.Response)
+                        {
+                            informationResponse.Responses.Add(response);
+                        }
+
+                        //  Send information response message
+                        _session.SendMessage(informationResponse);
+                    }
+                    catch (Exception exp)
+                    {
+                        _exception = exp;
+                        _authenticationCompleted.Set();
+                    }
+                });
+            }
+        }
+
+        #region IDisposable Members
+
+        private bool _isDisposed;
+
+        /// <summary>
+        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+        /// </summary>
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources
+        /// </summary>
+        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected virtual void Dispose(bool disposing)
+        {
+            if (_isDisposed)
+                return;
+
+            if (disposing)
+            {
+                var authenticationCompleted = _authenticationCompleted;
+                if (authenticationCompleted != null)
+                {
+                    authenticationCompleted.Dispose();
+                    _authenticationCompleted = null;
+                }
+
+                _isDisposed = true;
+            }
+        }
+
+        /// <summary>
+        /// Releases unmanaged resources and performs other cleanup operations before the
+        /// <see cref="KeyboardInteractiveAuthenticationMethod"/> is reclaimed by garbage collection.
+        /// </summary>
+        ~KeyboardInteractiveAuthenticationMethod()
+        {
+            Dispose(false);
+        }
+
+        #endregion
+    }
+}

+ 196 - 196
src/Renci.SshNet/KeyboardInteractiveConnectionInfo.cs

@@ -1,196 +1,196 @@
-using System;
-using System.Linq;
-using Renci.SshNet.Common;
-
-namespace Renci.SshNet
-{
-    /// <summary>
-    /// Provides connection information when keyboard interactive authentication method is used
-    /// </summary>
-    /// <example>
-    ///     <code source="..\..\Renci.SshNet.Tests\Classes\KeyboardInteractiveConnectionInfoTest.cs" region="Example KeyboardInteractiveConnectionInfo AuthenticationPrompt" language="C#" title="Connect using interactive method" />
-    /// </example>
-    public class KeyboardInteractiveConnectionInfo : ConnectionInfo, IDisposable
-    {
-        /// <summary>
-        /// Occurs when server prompts for more authentication information.
-        /// </summary>
-        /// <example>
-        ///     <code source="..\..\Renci.SshNet.Tests\Classes\KeyboardInteractiveConnectionInfoTest.cs" region="Example KeyboardInteractiveConnectionInfo AuthenticationPrompt" language="C#" title="Connect using interactive method" />
-        /// </example>
-        public event EventHandler<AuthenticationPromptEventArgs> AuthenticationPrompt;
-
-        //  TODO: DOCS Add exception documentation for this class.
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="KeyboardInteractiveConnectionInfo"/> class.
-        /// </summary>
-        /// <param name="host">The host.</param>
-        /// <param name="username">The username.</param>
-        public KeyboardInteractiveConnectionInfo(string host, string username)
-            : this(host, DefaultPort, username, ProxyTypes.None, string.Empty, 0, string.Empty, string.Empty)
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="KeyboardInteractiveConnectionInfo"/> class.
-        /// </summary>
-        /// <param name="host">The host.</param>
-        /// <param name="port">The port.</param>
-        /// <param name="username">The username.</param>
-        public KeyboardInteractiveConnectionInfo(string host, int port, string username)
-            : this(host, port, username, ProxyTypes.None, string.Empty, 0, string.Empty, string.Empty)
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="KeyboardInteractiveConnectionInfo"/> class.
-        /// </summary>
-        /// <param name="host">Connection host.</param>
-        /// <param name="port">Connection port.</param>
-        /// <param name="username">Connection username.</param>
-        /// <param name="proxyType">Type of the proxy.</param>
-        /// <param name="proxyHost">The proxy host.</param>
-        /// <param name="proxyPort">The proxy port.</param>
-        public KeyboardInteractiveConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort)
-            : this(host, port, username, proxyType, proxyHost, proxyPort, string.Empty, string.Empty)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="KeyboardInteractiveConnectionInfo"/> class.
-        /// </summary>
-        /// <param name="host">Connection host.</param>
-        /// <param name="port">Connection port.</param>
-        /// <param name="username">Connection username.</param>
-        /// <param name="proxyType">Type of the proxy.</param>
-        /// <param name="proxyHost">The proxy host.</param>
-        /// <param name="proxyPort">The proxy port.</param>
-        /// <param name="proxyUsername">The proxy username.</param>
-        public KeyboardInteractiveConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername)
-            : this(host, port, username, proxyType, proxyHost, proxyPort, proxyUsername, string.Empty)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="KeyboardInteractiveConnectionInfo"/> class.
-        /// </summary>
-        /// <param name="host">Connection host.</param>
-        /// <param name="username">Connection username.</param>
-        /// <param name="proxyType">Type of the proxy.</param>
-        /// <param name="proxyHost">The proxy host.</param>
-        /// <param name="proxyPort">The proxy port.</param>
-        public KeyboardInteractiveConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort)
-            : this(host, DefaultPort, username, proxyType, proxyHost, proxyPort, string.Empty, string.Empty)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="KeyboardInteractiveConnectionInfo"/> class.
-        /// </summary>
-        /// <param name="host">Connection host.</param>
-        /// <param name="username">Connection username.</param>
-        /// <param name="proxyType">Type of the proxy.</param>
-        /// <param name="proxyHost">The proxy host.</param>
-        /// <param name="proxyPort">The proxy port.</param>
-        /// <param name="proxyUsername">The proxy username.</param>
-        public KeyboardInteractiveConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername)
-            : this(host, DefaultPort, username, proxyType, proxyHost, proxyPort, proxyUsername, string.Empty)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="KeyboardInteractiveConnectionInfo"/> class.
-        /// </summary>
-        /// <param name="host">Connection host.</param>
-        /// <param name="username">Connection username.</param>
-        /// <param name="proxyType">Type of the proxy.</param>
-        /// <param name="proxyHost">The proxy host.</param>
-        /// <param name="proxyPort">The proxy port.</param>
-        /// <param name="proxyUsername">The proxy username.</param>
-        /// <param name="proxyPassword">The proxy password.</param>
-        public KeyboardInteractiveConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword)
-            : this(host, DefaultPort, username, proxyType, proxyHost, proxyPort, proxyUsername, proxyPassword)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="KeyboardInteractiveConnectionInfo"/> class.
-        /// </summary>
-        /// <param name="host">Connection host.</param>
-        /// <param name="port">Connection port.</param>
-        /// <param name="username">Connection username.</param>
-        /// <param name="proxyType">Type of the proxy.</param>
-        /// <param name="proxyHost">The proxy host.</param>
-        /// <param name="proxyPort">The proxy port.</param>
-        /// <param name="proxyUsername">The proxy username.</param>
-        /// <param name="proxyPassword">The proxy password.</param>
-        public KeyboardInteractiveConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword)
-            : base(host, port, username, proxyType, proxyHost, proxyPort, proxyUsername, proxyPassword, new KeyboardInteractiveAuthenticationMethod(username))
-        {
-            foreach (var authenticationMethod in AuthenticationMethods.OfType<KeyboardInteractiveAuthenticationMethod>())
-            {
-                authenticationMethod.AuthenticationPrompt += AuthenticationMethod_AuthenticationPrompt;
-            }
-
-        }
-
-        private void AuthenticationMethod_AuthenticationPrompt(object sender, AuthenticationPromptEventArgs e)
-        {
-            if (AuthenticationPrompt != null)
-            {
-                AuthenticationPrompt(sender, e);
-            }
-        }
-
-
-        #region IDisposable Members
-
-        private bool _isDisposed;
-
-        /// <summary>
-        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
-        /// </summary>
-        public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
-
-        /// <summary>
-        /// Releases unmanaged and - optionally - managed resources
-        /// </summary>
-        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
-        protected virtual void Dispose(bool disposing)
-        {
-            if (_isDisposed)
-                return;
-
-            if (disposing)
-            {
-                if (AuthenticationMethods != null)
-                {
-                    foreach (var authenticationMethods in AuthenticationMethods.OfType<IDisposable>())
-                    {
-                        authenticationMethods.Dispose();
-                    }
-                }
-
-                _isDisposed = true;
-            }
-        }
-
-        /// <summary>
-        /// Releases unmanaged resources and performs other cleanup operations before the
-        /// <see cref="KeyboardInteractiveConnectionInfo"/> is reclaimed by garbage collection.
-        /// </summary>
-        ~KeyboardInteractiveConnectionInfo()
-        {
-            Dispose(false);
-        }
-
-        #endregion
-    }
-}
+using System;
+using System.Linq;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet
+{
+    /// <summary>
+    /// Provides connection information when keyboard interactive authentication method is used
+    /// </summary>
+    /// <example>
+    ///     <code source="..\..\Renci.SshNet.Tests\Classes\KeyboardInteractiveConnectionInfoTest.cs" region="Example KeyboardInteractiveConnectionInfo AuthenticationPrompt" language="C#" title="Connect using interactive method" />
+    /// </example>
+    public class KeyboardInteractiveConnectionInfo : ConnectionInfo, IDisposable
+    {
+        /// <summary>
+        /// Occurs when server prompts for more authentication information.
+        /// </summary>
+        /// <example>
+        ///     <code source="..\..\Renci.SshNet.Tests\Classes\KeyboardInteractiveConnectionInfoTest.cs" region="Example KeyboardInteractiveConnectionInfo AuthenticationPrompt" language="C#" title="Connect using interactive method" />
+        /// </example>
+        public event EventHandler<AuthenticationPromptEventArgs> AuthenticationPrompt;
+
+        //  TODO: DOCS Add exception documentation for this class.
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="KeyboardInteractiveConnectionInfo"/> class.
+        /// </summary>
+        /// <param name="host">The host.</param>
+        /// <param name="username">The username.</param>
+        public KeyboardInteractiveConnectionInfo(string host, string username)
+            : this(host, DefaultPort, username, ProxyTypes.None, string.Empty, 0, string.Empty, string.Empty)
+        {
+
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="KeyboardInteractiveConnectionInfo"/> class.
+        /// </summary>
+        /// <param name="host">The host.</param>
+        /// <param name="port">The port.</param>
+        /// <param name="username">The username.</param>
+        public KeyboardInteractiveConnectionInfo(string host, int port, string username)
+            : this(host, port, username, ProxyTypes.None, string.Empty, 0, string.Empty, string.Empty)
+        {
+
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="KeyboardInteractiveConnectionInfo"/> class.
+        /// </summary>
+        /// <param name="host">Connection host.</param>
+        /// <param name="port">Connection port.</param>
+        /// <param name="username">Connection username.</param>
+        /// <param name="proxyType">Type of the proxy.</param>
+        /// <param name="proxyHost">The proxy host.</param>
+        /// <param name="proxyPort">The proxy port.</param>
+        public KeyboardInteractiveConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort)
+            : this(host, port, username, proxyType, proxyHost, proxyPort, string.Empty, string.Empty)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="KeyboardInteractiveConnectionInfo"/> class.
+        /// </summary>
+        /// <param name="host">Connection host.</param>
+        /// <param name="port">Connection port.</param>
+        /// <param name="username">Connection username.</param>
+        /// <param name="proxyType">Type of the proxy.</param>
+        /// <param name="proxyHost">The proxy host.</param>
+        /// <param name="proxyPort">The proxy port.</param>
+        /// <param name="proxyUsername">The proxy username.</param>
+        public KeyboardInteractiveConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername)
+            : this(host, port, username, proxyType, proxyHost, proxyPort, proxyUsername, string.Empty)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="KeyboardInteractiveConnectionInfo"/> class.
+        /// </summary>
+        /// <param name="host">Connection host.</param>
+        /// <param name="username">Connection username.</param>
+        /// <param name="proxyType">Type of the proxy.</param>
+        /// <param name="proxyHost">The proxy host.</param>
+        /// <param name="proxyPort">The proxy port.</param>
+        public KeyboardInteractiveConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort)
+            : this(host, DefaultPort, username, proxyType, proxyHost, proxyPort, string.Empty, string.Empty)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="KeyboardInteractiveConnectionInfo"/> class.
+        /// </summary>
+        /// <param name="host">Connection host.</param>
+        /// <param name="username">Connection username.</param>
+        /// <param name="proxyType">Type of the proxy.</param>
+        /// <param name="proxyHost">The proxy host.</param>
+        /// <param name="proxyPort">The proxy port.</param>
+        /// <param name="proxyUsername">The proxy username.</param>
+        public KeyboardInteractiveConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername)
+            : this(host, DefaultPort, username, proxyType, proxyHost, proxyPort, proxyUsername, string.Empty)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="KeyboardInteractiveConnectionInfo"/> class.
+        /// </summary>
+        /// <param name="host">Connection host.</param>
+        /// <param name="username">Connection username.</param>
+        /// <param name="proxyType">Type of the proxy.</param>
+        /// <param name="proxyHost">The proxy host.</param>
+        /// <param name="proxyPort">The proxy port.</param>
+        /// <param name="proxyUsername">The proxy username.</param>
+        /// <param name="proxyPassword">The proxy password.</param>
+        public KeyboardInteractiveConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword)
+            : this(host, DefaultPort, username, proxyType, proxyHost, proxyPort, proxyUsername, proxyPassword)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="KeyboardInteractiveConnectionInfo"/> class.
+        /// </summary>
+        /// <param name="host">Connection host.</param>
+        /// <param name="port">Connection port.</param>
+        /// <param name="username">Connection username.</param>
+        /// <param name="proxyType">Type of the proxy.</param>
+        /// <param name="proxyHost">The proxy host.</param>
+        /// <param name="proxyPort">The proxy port.</param>
+        /// <param name="proxyUsername">The proxy username.</param>
+        /// <param name="proxyPassword">The proxy password.</param>
+        public KeyboardInteractiveConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword)
+            : base(host, port, username, proxyType, proxyHost, proxyPort, proxyUsername, proxyPassword, new KeyboardInteractiveAuthenticationMethod(username))
+        {
+            foreach (var authenticationMethod in AuthenticationMethods.OfType<KeyboardInteractiveAuthenticationMethod>())
+            {
+                authenticationMethod.AuthenticationPrompt += AuthenticationMethod_AuthenticationPrompt;
+            }
+
+        }
+
+        private void AuthenticationMethod_AuthenticationPrompt(object sender, AuthenticationPromptEventArgs e)
+        {
+            if (AuthenticationPrompt != null)
+            {
+                AuthenticationPrompt(sender, e);
+            }
+        }
+
+
+        #region IDisposable Members
+
+        private bool _isDisposed;
+
+        /// <summary>
+        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+        /// </summary>
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources
+        /// </summary>
+        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected virtual void Dispose(bool disposing)
+        {
+            if (_isDisposed)
+                return;
+
+            if (disposing)
+            {
+                if (AuthenticationMethods != null)
+                {
+                    foreach (var authenticationMethods in AuthenticationMethods.OfType<IDisposable>())
+                    {
+                        authenticationMethods.Dispose();
+                    }
+                }
+
+                _isDisposed = true;
+            }
+        }
+
+        /// <summary>
+        /// Releases unmanaged resources and performs other cleanup operations before the
+        /// <see cref="KeyboardInteractiveConnectionInfo"/> is reclaimed by garbage collection.
+        /// </summary>
+        ~KeyboardInteractiveConnectionInfo()
+        {
+            Dispose(false);
+        }
+
+        #endregion
+    }
+}

+ 29 - 29
src/Renci.SshNet/MessageEventArgs.cs

@@ -1,29 +1,29 @@
-using System;
-
-namespace Renci.SshNet
-{
-    /// <summary>
-    /// Provides data for message events.
-    /// </summary>
-    /// <typeparam name="T">Message type</typeparam>
-    public class MessageEventArgs<T> : EventArgs
-    {
-        /// <summary>
-        /// Gets the message.
-        /// </summary>
-        public T Message { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="MessageEventArgs&lt;T&gt;"/> class.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="message"/> is null.</exception>
-        public MessageEventArgs(T message)
-        {
-            if (message == null)
-                throw new ArgumentNullException("message");
-
-            Message = message;
-        }
-    }
-}
+using System;
+
+namespace Renci.SshNet
+{
+    /// <summary>
+    /// Provides data for message events.
+    /// </summary>
+    /// <typeparam name="T">Message type</typeparam>
+    public class MessageEventArgs<T> : EventArgs
+    {
+        /// <summary>
+        /// Gets the message.
+        /// </summary>
+        public T Message { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="MessageEventArgs&lt;T&gt;"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="message"/> is null.</exception>
+        public MessageEventArgs(T message)
+        {
+            if (message == null)
+                throw new ArgumentNullException("message");
+
+            Message = message;
+        }
+    }
+}

+ 65 - 65
src/Renci.SshNet/Messages/Authentication/BannerMessage.cs

@@ -1,65 +1,65 @@
-namespace Renci.SshNet.Messages.Authentication
-{
-    /// <summary>
-    /// Represents SSH_MSG_USERAUTH_BANNER message.
-    /// </summary>
-    [Message("SSH_MSG_USERAUTH_BANNER", 53)]
-    public class BannerMessage : Message
-    {
-        private byte[] _message;
-        private byte[] _language;
-
-        /// <summary>
-        /// Gets banner message.
-        /// </summary>
-        public string Message
-        {
-            get { return Utf8.GetString(_message, 0, _message.Length); }
-        }
-
-        /// <summary>
-        /// Gets banner language.
-        /// </summary>
-        public string Language
-        {
-            get { return Utf8.GetString(_language, 0, _language.Length); }
-        }
-
-        /// <summary>
-        /// Gets the size of the message in bytes.
-        /// </summary>
-        /// <value>
-        /// The size of the messages in bytes.
-        /// </value>
-        protected override int BufferCapacity
-        {
-            get
-            {
-                var capacity = base.BufferCapacity;
-                capacity += 4; // Message length
-                capacity += _message.Length; // Message
-                capacity += 4; // Language length
-                capacity += _language.Length; // Language
-                return capacity;
-            }
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be loaded.
-        /// </summary>
-        protected override void LoadData()
-        {
-            _message = ReadBinary();
-            _language = ReadBinary();
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be saved.
-        /// </summary>
-        protected override void SaveData()
-        {
-            WriteBinaryString(_message);
-            WriteBinaryString(_language);
-        }
-    }
-}
+namespace Renci.SshNet.Messages.Authentication
+{
+    /// <summary>
+    /// Represents SSH_MSG_USERAUTH_BANNER message.
+    /// </summary>
+    [Message("SSH_MSG_USERAUTH_BANNER", 53)]
+    public class BannerMessage : Message
+    {
+        private byte[] _message;
+        private byte[] _language;
+
+        /// <summary>
+        /// Gets banner message.
+        /// </summary>
+        public string Message
+        {
+            get { return Utf8.GetString(_message, 0, _message.Length); }
+        }
+
+        /// <summary>
+        /// Gets banner language.
+        /// </summary>
+        public string Language
+        {
+            get { return Utf8.GetString(_language, 0, _language.Length); }
+        }
+
+        /// <summary>
+        /// Gets the size of the message in bytes.
+        /// </summary>
+        /// <value>
+        /// The size of the messages in bytes.
+        /// </value>
+        protected override int BufferCapacity
+        {
+            get
+            {
+                var capacity = base.BufferCapacity;
+                capacity += 4; // Message length
+                capacity += _message.Length; // Message
+                capacity += 4; // Language length
+                capacity += _language.Length; // Language
+                return capacity;
+            }
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be loaded.
+        /// </summary>
+        protected override void LoadData()
+        {
+            _message = ReadBinary();
+            _language = ReadBinary();
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be saved.
+        /// </summary>
+        protected override void SaveData()
+        {
+            WriteBinaryString(_message);
+            WriteBinaryString(_language);
+        }
+    }
+}

+ 53 - 53
src/Renci.SshNet/Messages/Authentication/FailureMessage.cs

@@ -1,53 +1,53 @@
-using System;
-
-namespace Renci.SshNet.Messages.Authentication
-{
-    /// <summary>
-    /// Represents SSH_MSG_USERAUTH_FAILURE message.
-    /// </summary>
-    [Message("SSH_MSG_USERAUTH_FAILURE", 51)]
-    public class FailureMessage : Message
-    {
-        /// <summary>
-        /// Gets or sets the allowed authentications if available.
-        /// </summary>
-        /// <value>
-        /// The allowed authentications.
-        /// </value>
-        public string[] AllowedAuthentications { get; set; }
-
-        /// <summary>
-        /// Gets failure message.
-        /// </summary>
-        public string Message { get; private set; }
-
-        /// <summary>
-        /// Gets a value indicating whether authentication is partially successful.
-        /// </summary>
-        /// <value>
-        ///   <c>true</c> if partially successful; otherwise, <c>false</c>.
-        /// </value>
-        public bool PartialSuccess { get; private set; }
-
-        /// <summary>
-        /// Called when type specific data need to be loaded.
-        /// </summary>
-        protected override void LoadData()
-        {
-            AllowedAuthentications = ReadNamesList();
-            PartialSuccess = ReadBoolean();
-            if (PartialSuccess)
-            {
-                Message = string.Join(",", AllowedAuthentications);
-            }
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be saved.
-        /// </summary>
-        protected override void SaveData()
-        {
-            throw new NotImplementedException();
-        }
-    }
-}
+using System;
+
+namespace Renci.SshNet.Messages.Authentication
+{
+    /// <summary>
+    /// Represents SSH_MSG_USERAUTH_FAILURE message.
+    /// </summary>
+    [Message("SSH_MSG_USERAUTH_FAILURE", 51)]
+    public class FailureMessage : Message
+    {
+        /// <summary>
+        /// Gets or sets the allowed authentications if available.
+        /// </summary>
+        /// <value>
+        /// The allowed authentications.
+        /// </value>
+        public string[] AllowedAuthentications { get; set; }
+
+        /// <summary>
+        /// Gets failure message.
+        /// </summary>
+        public string Message { get; private set; }
+
+        /// <summary>
+        /// Gets a value indicating whether authentication is partially successful.
+        /// </summary>
+        /// <value>
+        ///   <c>true</c> if partially successful; otherwise, <c>false</c>.
+        /// </value>
+        public bool PartialSuccess { get; private set; }
+
+        /// <summary>
+        /// Called when type specific data need to be loaded.
+        /// </summary>
+        protected override void LoadData()
+        {
+            AllowedAuthentications = ReadNamesList();
+            PartialSuccess = ReadBoolean();
+            if (PartialSuccess)
+            {
+                Message = string.Join(",", AllowedAuthentications);
+            }
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be saved.
+        /// </summary>
+        protected override void SaveData()
+        {
+            throw new NotImplementedException();
+        }
+    }
+}

+ 67 - 67
src/Renci.SshNet/Messages/Authentication/InformationRequestMessage.cs

@@ -1,67 +1,67 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using Renci.SshNet.Common;
-
-namespace Renci.SshNet.Messages.Authentication
-{
-    /// <summary>
-    /// Represents SSH_MSG_USERAUTH_INFO_REQUEST message.
-    /// </summary>
-    [Message("SSH_MSG_USERAUTH_INFO_REQUEST", 60)]
-    internal class InformationRequestMessage : Message
-    {
-        /// <summary>
-        /// Gets information request name.
-        /// </summary>
-        public string Name { get; private set; }
-
-        /// <summary>
-        /// Gets information request instruction.
-        /// </summary>
-        public string Instruction { get; private set; }
-
-        /// <summary>
-        /// Gets information request language.
-        /// </summary>
-        public string Language { get; private set; }
-
-        /// <summary>
-        /// Gets information request prompts.
-        /// </summary>
-        public IEnumerable<AuthenticationPrompt> Prompts { get; private set; }
-
-        /// <summary>
-        /// Called when type specific data need to be loaded.
-        /// </summary>
-        protected override void LoadData()
-        {
-            Name = ReadString(Encoding.UTF8);
-            Instruction = ReadString(Encoding.UTF8);
-
-            // language tag as defined in rfc3066:
-            // Language tags may always be presented using the characters A-Z, a-z, 0 - 9 and HYPHEN-MINUS
-            Language = ReadString(Ascii);
-
-            var numOfPrompts = ReadUInt32();
-            var prompts = new List<AuthenticationPrompt>();
-
-            for (var i = 0; i < numOfPrompts; i++)
-            {
-                var prompt = ReadString(Encoding.UTF8);
-                var echo = ReadBoolean();
-                prompts.Add(new AuthenticationPrompt(i, echo, prompt));
-            }
-
-            Prompts = prompts;
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be saved.
-        /// </summary>
-        protected override void SaveData()
-        {
-            throw new NotImplementedException();
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet.Messages.Authentication
+{
+    /// <summary>
+    /// Represents SSH_MSG_USERAUTH_INFO_REQUEST message.
+    /// </summary>
+    [Message("SSH_MSG_USERAUTH_INFO_REQUEST", 60)]
+    internal class InformationRequestMessage : Message
+    {
+        /// <summary>
+        /// Gets information request name.
+        /// </summary>
+        public string Name { get; private set; }
+
+        /// <summary>
+        /// Gets information request instruction.
+        /// </summary>
+        public string Instruction { get; private set; }
+
+        /// <summary>
+        /// Gets information request language.
+        /// </summary>
+        public string Language { get; private set; }
+
+        /// <summary>
+        /// Gets information request prompts.
+        /// </summary>
+        public IEnumerable<AuthenticationPrompt> Prompts { get; private set; }
+
+        /// <summary>
+        /// Called when type specific data need to be loaded.
+        /// </summary>
+        protected override void LoadData()
+        {
+            Name = ReadString(Encoding.UTF8);
+            Instruction = ReadString(Encoding.UTF8);
+
+            // language tag as defined in rfc3066:
+            // Language tags may always be presented using the characters A-Z, a-z, 0 - 9 and HYPHEN-MINUS
+            Language = ReadString(Ascii);
+
+            var numOfPrompts = ReadUInt32();
+            var prompts = new List<AuthenticationPrompt>();
+
+            for (var i = 0; i < numOfPrompts; i++)
+            {
+                var prompt = ReadString(Encoding.UTF8);
+                var echo = ReadBoolean();
+                prompts.Add(new AuthenticationPrompt(i, echo, prompt));
+            }
+
+            Prompts = prompts;
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be saved.
+        /// </summary>
+        protected override void SaveData()
+        {
+            throw new NotImplementedException();
+        }
+    }
+}

+ 57 - 57
src/Renci.SshNet/Messages/Authentication/InformationResponseMessage.cs

@@ -1,57 +1,57 @@
-using System;
-using System.Collections.Generic;
-
-namespace Renci.SshNet.Messages.Authentication
-{
-    /// <summary>
-    /// Represents SSH_MSG_USERAUTH_INFO_RESPONSE message.
-    /// </summary>
-    [Message("SSH_MSG_USERAUTH_INFO_RESPONSE", 61)]
-    internal class InformationResponseMessage : Message
-    {
-        /// <summary>
-        /// Gets authentication responses.
-        /// </summary>
-        public IList<string> Responses { get; private set; }
-
-        /// <summary>
-        /// Gets the size of the message in bytes.
-        /// </summary>
-        /// <value>
-        /// <c>-1</c> to indicate that the size of the message cannot be determined,
-        /// or is too costly to calculate.
-        /// </value>
-        protected override int BufferCapacity
-        {
-            get { return -1; }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="InformationResponseMessage"/> class.
-        /// </summary>
-        public InformationResponseMessage()
-        {
-            Responses = new List<string>();
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be loaded.
-        /// </summary>
-        protected override void LoadData()
-        {
-            throw new NotImplementedException();
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be saved.
-        /// </summary>
-        protected override void SaveData()
-        {
-            Write((UInt32)Responses.Count);
-            foreach (var response in Responses)
-            {
-                Write(response);
-            }
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+
+namespace Renci.SshNet.Messages.Authentication
+{
+    /// <summary>
+    /// Represents SSH_MSG_USERAUTH_INFO_RESPONSE message.
+    /// </summary>
+    [Message("SSH_MSG_USERAUTH_INFO_RESPONSE", 61)]
+    internal class InformationResponseMessage : Message
+    {
+        /// <summary>
+        /// Gets authentication responses.
+        /// </summary>
+        public IList<string> Responses { get; private set; }
+
+        /// <summary>
+        /// Gets the size of the message in bytes.
+        /// </summary>
+        /// <value>
+        /// <c>-1</c> to indicate that the size of the message cannot be determined,
+        /// or is too costly to calculate.
+        /// </value>
+        protected override int BufferCapacity
+        {
+            get { return -1; }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="InformationResponseMessage"/> class.
+        /// </summary>
+        public InformationResponseMessage()
+        {
+            Responses = new List<string>();
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be loaded.
+        /// </summary>
+        protected override void LoadData()
+        {
+            throw new NotImplementedException();
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be saved.
+        /// </summary>
+        protected override void SaveData()
+        {
+            Write((UInt32)Responses.Count);
+            foreach (var response in Responses)
+            {
+                Write(response);
+            }
+        }
+    }
+}

+ 56 - 56
src/Renci.SshNet/Messages/Authentication/PasswordChangeRequiredMessage.cs

@@ -1,56 +1,56 @@
-namespace Renci.SshNet.Messages.Authentication
-{
-    /// <summary>
-    /// Represents SSH_MSG_USERAUTH_PASSWD_CHANGEREQ message.
-    /// </summary>
-    [Message("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ", 60)]
-    internal class PasswordChangeRequiredMessage : Message
-    {
-        /// <summary>
-        /// Gets password change request message as UTF-8 encoded byte array.
-        /// </summary>
-        public byte[] Message { get; private set; }
-
-        /// <summary>
-        /// Gets message language as UTF-8 encoded byte array.
-        /// </summary>
-        public byte[] Language { get; private set; }
-
-        /// <summary>
-        /// Gets the size of the message in bytes.
-        /// </summary>
-        /// <value>
-        /// The size of the messages in bytes.
-        /// </value>
-        protected override int BufferCapacity
-        {
-            get
-            {
-                var capacity = base.BufferCapacity;
-                capacity += 4; // Message length
-                capacity += Message.Length; // Message
-                capacity += 4; // Language length
-                capacity += Language.Length; // Language
-                return capacity;
-            }
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be loaded.
-        /// </summary>
-        protected override void LoadData()
-        {
-            Message = ReadBinary();
-            Language = ReadBinary();
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be saved.
-        /// </summary>
-        protected override void SaveData()
-        {
-            WriteBinaryString(Message);
-            WriteBinaryString(Language);
-        }
-    }
-}
+namespace Renci.SshNet.Messages.Authentication
+{
+    /// <summary>
+    /// Represents SSH_MSG_USERAUTH_PASSWD_CHANGEREQ message.
+    /// </summary>
+    [Message("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ", 60)]
+    internal class PasswordChangeRequiredMessage : Message
+    {
+        /// <summary>
+        /// Gets password change request message as UTF-8 encoded byte array.
+        /// </summary>
+        public byte[] Message { get; private set; }
+
+        /// <summary>
+        /// Gets message language as UTF-8 encoded byte array.
+        /// </summary>
+        public byte[] Language { get; private set; }
+
+        /// <summary>
+        /// Gets the size of the message in bytes.
+        /// </summary>
+        /// <value>
+        /// The size of the messages in bytes.
+        /// </value>
+        protected override int BufferCapacity
+        {
+            get
+            {
+                var capacity = base.BufferCapacity;
+                capacity += 4; // Message length
+                capacity += Message.Length; // Message
+                capacity += 4; // Language length
+                capacity += Language.Length; // Language
+                return capacity;
+            }
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be loaded.
+        /// </summary>
+        protected override void LoadData()
+        {
+            Message = ReadBinary();
+            Language = ReadBinary();
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be saved.
+        /// </summary>
+        protected override void SaveData()
+        {
+            WriteBinaryString(Message);
+            WriteBinaryString(Language);
+        }
+    }
+}

+ 59 - 59
src/Renci.SshNet/Messages/Authentication/PublicKeyMessage.cs

@@ -1,59 +1,59 @@
-namespace Renci.SshNet.Messages.Authentication
-{
-    /// <summary>
-    /// Represents SSH_MSG_USERAUTH_PK_OK message.
-    /// </summary>
-    [Message("SSH_MSG_USERAUTH_PK_OK", 60)]
-    internal class PublicKeyMessage : Message
-    {
-        /// <summary>
-        /// Gets the name of the public key algorithm as ASCII encoded byte array.
-        /// </summary>
-        /// <value>
-        /// The name of the public key algorithm.
-        /// </value>
-        public byte[] PublicKeyAlgorithmName { get; private set; }
-
-        /// <summary>
-        /// Gets the public key data.
-        /// </summary>
-        public byte[] PublicKeyData { get; private set; }
-
-        /// <summary>
-        /// Gets the size of the message in bytes.
-        /// </summary>
-        /// <value>
-        /// The size of the messages in bytes.
-        /// </value>
-        protected override int BufferCapacity
-        {
-            get
-            {
-                var capacity = base.BufferCapacity;
-                capacity += 4; // PublicKeyAlgorithmName length
-                capacity += PublicKeyAlgorithmName.Length; // PublicKeyAlgorithmName
-                capacity += 4; // PublicKeyData length
-                capacity += PublicKeyData.Length; // PublicKeyData
-                return capacity;
-            }
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be loaded.
-        /// </summary>
-        protected override void LoadData()
-        {
-            PublicKeyAlgorithmName = ReadBinary();
-            PublicKeyData = ReadBinary();
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be saved.
-        /// </summary>
-        protected override void SaveData()
-        {
-            WriteBinaryString(PublicKeyAlgorithmName);
-            WriteBinaryString(PublicKeyData);
-        }
-    }
-}
+namespace Renci.SshNet.Messages.Authentication
+{
+    /// <summary>
+    /// Represents SSH_MSG_USERAUTH_PK_OK message.
+    /// </summary>
+    [Message("SSH_MSG_USERAUTH_PK_OK", 60)]
+    internal class PublicKeyMessage : Message
+    {
+        /// <summary>
+        /// Gets the name of the public key algorithm as ASCII encoded byte array.
+        /// </summary>
+        /// <value>
+        /// The name of the public key algorithm.
+        /// </value>
+        public byte[] PublicKeyAlgorithmName { get; private set; }
+
+        /// <summary>
+        /// Gets the public key data.
+        /// </summary>
+        public byte[] PublicKeyData { get; private set; }
+
+        /// <summary>
+        /// Gets the size of the message in bytes.
+        /// </summary>
+        /// <value>
+        /// The size of the messages in bytes.
+        /// </value>
+        protected override int BufferCapacity
+        {
+            get
+            {
+                var capacity = base.BufferCapacity;
+                capacity += 4; // PublicKeyAlgorithmName length
+                capacity += PublicKeyAlgorithmName.Length; // PublicKeyAlgorithmName
+                capacity += 4; // PublicKeyData length
+                capacity += PublicKeyData.Length; // PublicKeyData
+                return capacity;
+            }
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be loaded.
+        /// </summary>
+        protected override void LoadData()
+        {
+            PublicKeyAlgorithmName = ReadBinary();
+            PublicKeyData = ReadBinary();
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be saved.
+        /// </summary>
+        protected override void SaveData()
+        {
+            WriteBinaryString(PublicKeyAlgorithmName);
+            WriteBinaryString(PublicKeyData);
+        }
+    }
+}

+ 105 - 105
src/Renci.SshNet/Messages/Authentication/RequestMessage.cs

@@ -1,105 +1,105 @@
-using System;
-
-namespace Renci.SshNet.Messages.Authentication
-{
-    /// <summary>
-    /// Represents SSH_MSG_USERAUTH_REQUEST message. Server as a base message for other user authentication requests.
-    /// </summary>
-    [Message("SSH_MSG_USERAUTH_REQUEST", AuthenticationMessageCode)]
-    public abstract class RequestMessage : Message
-    {
-        /// <summary>
-        /// Returns the authentication message code for <c>SSH_MSG_USERAUTH_REQUEST</c>.
-        /// </summary>
-        internal const int AuthenticationMessageCode = 50;
-
-        private readonly byte[] _serviceName;
-        private readonly byte[] _userName;
-        private readonly byte[] _methodNameBytes;
-        private readonly string _methodName;
-
-        /// <summary>
-        /// Gets authentication username as UTF-8 encoded byte array.
-        /// </summary>
-        public byte[] Username
-        {
-            get { return _userName; }
-        }
-
-        /// <summary>
-        /// Gets the name of the service as ASCII encoded byte array.
-        /// </summary>
-        /// <value>
-        /// The name of the service.
-        /// </value>
-        public byte[] ServiceName
-        {
-            get { return _serviceName; }
-        }
-
-        /// <summary>
-        /// Gets the name of the authentication method.
-        /// </summary>
-        /// <value>
-        /// The name of the method.
-        /// </value>
-        public virtual string MethodName
-        {
-            get { return _methodName; }
-        }
-
-        /// <summary>
-        /// Gets the size of the message in bytes.
-        /// </summary>
-        /// <value>
-        /// The size of the messages in bytes.
-        /// </value>
-        protected override int BufferCapacity
-        {
-            get
-            {
-                var capacity = base.BufferCapacity;
-                capacity += 4; // Username length
-                capacity += Username.Length; // Username
-                capacity += 4; // ServiceName length
-                capacity += ServiceName.Length; // ServiceName
-                capacity += 4; // MethodName length
-                capacity += _methodNameBytes.Length; // MethodName
-                return capacity;
-            }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="RequestMessage"/> class.
-        /// </summary>
-        /// <param name="serviceName">Name of the service.</param>
-        /// <param name="username">Authentication username.</param>
-        /// <param name="methodName">The name of the authentication method.</param>
-        protected RequestMessage(ServiceName serviceName, string username, string methodName)
-        {
-            _serviceName = serviceName.ToArray();
-            _userName = Utf8.GetBytes(username);
-            _methodNameBytes = Ascii.GetBytes(methodName);
-            _methodName = methodName;
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be loaded.
-        /// </summary>
-        protected override void LoadData()
-        {
-            throw new InvalidOperationException("Load data is not supported.");
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be saved.
-        /// </summary>
-        protected override void SaveData()
-        {
-            WriteBinaryString(_userName);
-            WriteBinaryString(_serviceName);
-            WriteBinaryString(_methodNameBytes);
-        }
-    }
-}
-
+using System;
+
+namespace Renci.SshNet.Messages.Authentication
+{
+    /// <summary>
+    /// Represents SSH_MSG_USERAUTH_REQUEST message. Server as a base message for other user authentication requests.
+    /// </summary>
+    [Message("SSH_MSG_USERAUTH_REQUEST", AuthenticationMessageCode)]
+    public abstract class RequestMessage : Message
+    {
+        /// <summary>
+        /// Returns the authentication message code for <c>SSH_MSG_USERAUTH_REQUEST</c>.
+        /// </summary>
+        internal const int AuthenticationMessageCode = 50;
+
+        private readonly byte[] _serviceName;
+        private readonly byte[] _userName;
+        private readonly byte[] _methodNameBytes;
+        private readonly string _methodName;
+
+        /// <summary>
+        /// Gets authentication username as UTF-8 encoded byte array.
+        /// </summary>
+        public byte[] Username
+        {
+            get { return _userName; }
+        }
+
+        /// <summary>
+        /// Gets the name of the service as ASCII encoded byte array.
+        /// </summary>
+        /// <value>
+        /// The name of the service.
+        /// </value>
+        public byte[] ServiceName
+        {
+            get { return _serviceName; }
+        }
+
+        /// <summary>
+        /// Gets the name of the authentication method.
+        /// </summary>
+        /// <value>
+        /// The name of the method.
+        /// </value>
+        public virtual string MethodName
+        {
+            get { return _methodName; }
+        }
+
+        /// <summary>
+        /// Gets the size of the message in bytes.
+        /// </summary>
+        /// <value>
+        /// The size of the messages in bytes.
+        /// </value>
+        protected override int BufferCapacity
+        {
+            get
+            {
+                var capacity = base.BufferCapacity;
+                capacity += 4; // Username length
+                capacity += Username.Length; // Username
+                capacity += 4; // ServiceName length
+                capacity += ServiceName.Length; // ServiceName
+                capacity += 4; // MethodName length
+                capacity += _methodNameBytes.Length; // MethodName
+                return capacity;
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RequestMessage"/> class.
+        /// </summary>
+        /// <param name="serviceName">Name of the service.</param>
+        /// <param name="username">Authentication username.</param>
+        /// <param name="methodName">The name of the authentication method.</param>
+        protected RequestMessage(ServiceName serviceName, string username, string methodName)
+        {
+            _serviceName = serviceName.ToArray();
+            _userName = Utf8.GetBytes(username);
+            _methodNameBytes = Ascii.GetBytes(methodName);
+            _methodName = methodName;
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be loaded.
+        /// </summary>
+        protected override void LoadData()
+        {
+            throw new InvalidOperationException("Load data is not supported.");
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be saved.
+        /// </summary>
+        protected override void SaveData()
+        {
+            WriteBinaryString(_userName);
+            WriteBinaryString(_serviceName);
+            WriteBinaryString(_methodNameBytes);
+        }
+    }
+}
+

+ 104 - 104
src/Renci.SshNet/Messages/Authentication/RequestMessageHost.cs

@@ -1,104 +1,104 @@
-namespace Renci.SshNet.Messages.Authentication
-{
-    /// <summary>
-    /// Represents "hostbased" SSH_MSG_USERAUTH_REQUEST message.
-    /// </summary>
-    internal class RequestMessageHost : RequestMessage
-    {
-        /// <summary>
-        /// Gets the public key algorithm for host key as ASCII encoded byte array.
-        /// </summary>
-        public byte[] PublicKeyAlgorithm { get; private set; }
-
-        /// <summary>
-        /// Gets or sets the public host key and certificates for client host.
-        /// </summary>
-        /// <value>
-        /// The public host key.
-        /// </value>
-        public byte[] PublicHostKey { get; private set; }
-
-        /// <summary>
-        /// Gets or sets the name of the client host as ASCII encoded byte array.
-        /// </summary>
-        /// <value>
-        /// The name of the client host.
-        /// </value>
-        public byte[] ClientHostName { get; private set; }
-
-        /// <summary>
-        /// Gets or sets the client username on the client host as UTF-8 encoded byte array.
-        /// </summary>
-        /// <value>
-        /// The client username.
-        /// </value>
-        public byte[] ClientUsername { get; private set; }
-
-        /// <summary>
-        /// Gets or sets the signature.
-        /// </summary>
-        /// <value>
-        /// The signature.
-        /// </value>
-        public byte[] Signature { get; private set; }
-
-        /// <summary>
-        /// Gets the size of the message in bytes.
-        /// </summary>
-        /// <value>
-        /// The size of the messages in bytes.
-        /// </value>
-        protected override int BufferCapacity
-        {
-            get
-            {
-                var capacity = base.BufferCapacity;
-                capacity += 4; // PublicKeyAlgorithm length
-                capacity += PublicKeyAlgorithm.Length; // PublicKeyAlgorithm
-                capacity += 4; // PublicHostKey length
-                capacity += PublicHostKey.Length; // PublicHostKey
-                capacity += 4; // ClientHostName length
-                capacity += ClientHostName.Length; // ClientHostName
-                capacity += 4; // ClientUsername length
-                capacity += ClientUsername.Length; // ClientUsername
-                capacity += 4; // Signature length
-                capacity += Signature.Length; // Signature
-                return capacity;
-            }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="RequestMessageHost"/> class.
-        /// </summary>
-        /// <param name="serviceName">Name of the service.</param>
-        /// <param name="username">Authentication username.</param>
-        /// <param name="publicKeyAlgorithm">The public key algorithm.</param>
-        /// <param name="publicHostKey">The public host key.</param>
-        /// <param name="clientHostName">Name of the client host.</param>
-        /// <param name="clientUsername">The client username.</param>
-        /// <param name="signature">The signature.</param>
-        public RequestMessageHost(ServiceName serviceName, string username, string publicKeyAlgorithm, byte[] publicHostKey, string clientHostName, string clientUsername, byte[] signature)
-            : base(serviceName, username, "hostbased")
-        {
-            PublicKeyAlgorithm = Ascii.GetBytes(publicKeyAlgorithm);
-            PublicHostKey = publicHostKey;
-            ClientHostName = Ascii.GetBytes(clientHostName);
-            ClientUsername = Utf8.GetBytes(clientUsername);
-            Signature = signature;
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be saved.
-        /// </summary>
-        protected override void SaveData()
-        {
-            base.SaveData();
-
-            WriteBinaryString(PublicKeyAlgorithm);
-            WriteBinaryString(PublicHostKey);
-            WriteBinaryString(ClientHostName);
-            WriteBinaryString(ClientUsername);
-            WriteBinaryString(Signature);
-        }
-    }
-}
+namespace Renci.SshNet.Messages.Authentication
+{
+    /// <summary>
+    /// Represents "hostbased" SSH_MSG_USERAUTH_REQUEST message.
+    /// </summary>
+    internal class RequestMessageHost : RequestMessage
+    {
+        /// <summary>
+        /// Gets the public key algorithm for host key as ASCII encoded byte array.
+        /// </summary>
+        public byte[] PublicKeyAlgorithm { get; private set; }
+
+        /// <summary>
+        /// Gets or sets the public host key and certificates for client host.
+        /// </summary>
+        /// <value>
+        /// The public host key.
+        /// </value>
+        public byte[] PublicHostKey { get; private set; }
+
+        /// <summary>
+        /// Gets or sets the name of the client host as ASCII encoded byte array.
+        /// </summary>
+        /// <value>
+        /// The name of the client host.
+        /// </value>
+        public byte[] ClientHostName { get; private set; }
+
+        /// <summary>
+        /// Gets or sets the client username on the client host as UTF-8 encoded byte array.
+        /// </summary>
+        /// <value>
+        /// The client username.
+        /// </value>
+        public byte[] ClientUsername { get; private set; }
+
+        /// <summary>
+        /// Gets or sets the signature.
+        /// </summary>
+        /// <value>
+        /// The signature.
+        /// </value>
+        public byte[] Signature { get; private set; }
+
+        /// <summary>
+        /// Gets the size of the message in bytes.
+        /// </summary>
+        /// <value>
+        /// The size of the messages in bytes.
+        /// </value>
+        protected override int BufferCapacity
+        {
+            get
+            {
+                var capacity = base.BufferCapacity;
+                capacity += 4; // PublicKeyAlgorithm length
+                capacity += PublicKeyAlgorithm.Length; // PublicKeyAlgorithm
+                capacity += 4; // PublicHostKey length
+                capacity += PublicHostKey.Length; // PublicHostKey
+                capacity += 4; // ClientHostName length
+                capacity += ClientHostName.Length; // ClientHostName
+                capacity += 4; // ClientUsername length
+                capacity += ClientUsername.Length; // ClientUsername
+                capacity += 4; // Signature length
+                capacity += Signature.Length; // Signature
+                return capacity;
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RequestMessageHost"/> class.
+        /// </summary>
+        /// <param name="serviceName">Name of the service.</param>
+        /// <param name="username">Authentication username.</param>
+        /// <param name="publicKeyAlgorithm">The public key algorithm.</param>
+        /// <param name="publicHostKey">The public host key.</param>
+        /// <param name="clientHostName">Name of the client host.</param>
+        /// <param name="clientUsername">The client username.</param>
+        /// <param name="signature">The signature.</param>
+        public RequestMessageHost(ServiceName serviceName, string username, string publicKeyAlgorithm, byte[] publicHostKey, string clientHostName, string clientUsername, byte[] signature)
+            : base(serviceName, username, "hostbased")
+        {
+            PublicKeyAlgorithm = Ascii.GetBytes(publicKeyAlgorithm);
+            PublicHostKey = publicHostKey;
+            ClientHostName = Ascii.GetBytes(clientHostName);
+            ClientUsername = Utf8.GetBytes(clientUsername);
+            Signature = signature;
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be saved.
+        /// </summary>
+        protected override void SaveData()
+        {
+            base.SaveData();
+
+            WriteBinaryString(PublicKeyAlgorithm);
+            WriteBinaryString(PublicHostKey);
+            WriteBinaryString(ClientHostName);
+            WriteBinaryString(ClientUsername);
+            WriteBinaryString(Signature);
+        }
+    }
+}

+ 62 - 62
src/Renci.SshNet/Messages/Authentication/RequestMessageKeyboardInteractive.cs

@@ -1,62 +1,62 @@
-using Renci.SshNet.Common;
-
-namespace Renci.SshNet.Messages.Authentication
-{
-    /// <summary>
-    /// Represents "keyboard-interactive" SSH_MSG_USERAUTH_REQUEST message.
-    /// </summary>
-    internal class RequestMessageKeyboardInteractive : RequestMessage
-    {
-        /// <summary>
-        /// Gets message language.
-        /// </summary>
-        public byte[] Language { get; private set; }
-
-        /// <summary>
-        /// Gets authentication sub methods.
-        /// </summary>
-        public byte[] SubMethods { get; private set; }
-
-        /// <summary>
-        /// Gets the size of the message in bytes.
-        /// </summary>
-        /// <value>
-        /// The size of the messages in bytes.
-        /// </value>
-        protected override int BufferCapacity
-        {
-            get
-            {
-                var capacity = base.BufferCapacity;
-                capacity += 4; // Language length
-                capacity += Language.Length; // Language
-                capacity += 4; // SubMethods length
-                capacity += SubMethods.Length; // SubMethods
-                return capacity;
-            }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="RequestMessageKeyboardInteractive"/> class.
-        /// </summary>
-        /// <param name="serviceName">Name of the service.</param>
-        /// <param name="username">Authentication username.</param>
-        public RequestMessageKeyboardInteractive(ServiceName serviceName, string username)
-            : base(serviceName, username, "keyboard-interactive")
-        {
-            Language = Array<byte>.Empty;
-            SubMethods = Array<byte>.Empty;
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be saved.
-        /// </summary>
-        protected override void SaveData()
-        {
-            base.SaveData();
-
-            WriteBinaryString(Language);
-            WriteBinaryString(SubMethods);
-        }
-    }
-}
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet.Messages.Authentication
+{
+    /// <summary>
+    /// Represents "keyboard-interactive" SSH_MSG_USERAUTH_REQUEST message.
+    /// </summary>
+    internal class RequestMessageKeyboardInteractive : RequestMessage
+    {
+        /// <summary>
+        /// Gets message language.
+        /// </summary>
+        public byte[] Language { get; private set; }
+
+        /// <summary>
+        /// Gets authentication sub methods.
+        /// </summary>
+        public byte[] SubMethods { get; private set; }
+
+        /// <summary>
+        /// Gets the size of the message in bytes.
+        /// </summary>
+        /// <value>
+        /// The size of the messages in bytes.
+        /// </value>
+        protected override int BufferCapacity
+        {
+            get
+            {
+                var capacity = base.BufferCapacity;
+                capacity += 4; // Language length
+                capacity += Language.Length; // Language
+                capacity += 4; // SubMethods length
+                capacity += SubMethods.Length; // SubMethods
+                return capacity;
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RequestMessageKeyboardInteractive"/> class.
+        /// </summary>
+        /// <param name="serviceName">Name of the service.</param>
+        /// <param name="username">Authentication username.</param>
+        public RequestMessageKeyboardInteractive(ServiceName serviceName, string username)
+            : base(serviceName, username, "keyboard-interactive")
+        {
+            Language = Array<byte>.Empty;
+            SubMethods = Array<byte>.Empty;
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be saved.
+        /// </summary>
+        protected override void SaveData()
+        {
+            base.SaveData();
+
+            WriteBinaryString(Language);
+            WriteBinaryString(SubMethods);
+        }
+    }
+}

+ 18 - 18
src/Renci.SshNet/Messages/Authentication/RequestMessageNone.cs

@@ -1,18 +1,18 @@
-namespace Renci.SshNet.Messages.Authentication
-{
-    /// <summary>
-    /// Represents "none" SSH_MSG_USERAUTH_REQUEST message.
-    /// </summary>
-    internal class RequestMessageNone : RequestMessage
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="RequestMessagePassword"/> class.
-        /// </summary>
-        /// <param name="serviceName">Name of the service.</param>
-        /// <param name="username">Authentication username.</param>
-        public RequestMessageNone(ServiceName serviceName, string username)
-            : base(serviceName, username, "none")
-        {
-        }
-    }
-}
+namespace Renci.SshNet.Messages.Authentication
+{
+    /// <summary>
+    /// Represents "none" SSH_MSG_USERAUTH_REQUEST message.
+    /// </summary>
+    internal class RequestMessageNone : RequestMessage
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RequestMessagePassword"/> class.
+        /// </summary>
+        /// <param name="serviceName">Name of the service.</param>
+        /// <param name="username">Authentication username.</param>
+        public RequestMessageNone(ServiceName serviceName, string username)
+            : base(serviceName, username, "none")
+        {
+        }
+    }
+}

+ 83 - 83
src/Renci.SshNet/Messages/Authentication/RequestMessagePassword.cs

@@ -1,83 +1,83 @@
-namespace Renci.SshNet.Messages.Authentication
-{
-    /// <summary>
-    /// Represents "password" SSH_MSG_USERAUTH_REQUEST message.
-    /// </summary>
-    internal class RequestMessagePassword : RequestMessage
-    {
-        /// <summary>
-        /// Gets authentication password.
-        /// </summary>
-        public byte[] Password { get; private set; }
-
-        /// <summary>
-        /// Gets new authentication password.
-        /// </summary>
-        public byte[] NewPassword { get; private set; }
-
-        /// <summary>
-        /// Gets the size of the message in bytes.
-        /// </summary>
-        /// <value>
-        /// The size of the messages in bytes.
-        /// </value>
-        protected override int BufferCapacity
-        {
-            get
-            {
-                var capacity = base.BufferCapacity;
-                capacity += 1; // NewPassword flag
-                capacity += 4; // Password length
-                capacity += Password.Length; // Password
-
-                if (NewPassword != null)
-                {
-                    capacity += 4; // NewPassword length
-                    capacity += NewPassword.Length; // NewPassword
-                }
-
-                return capacity;
-            }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="RequestMessagePassword"/> class.
-        /// </summary>
-        /// <param name="serviceName">Name of the service.</param>
-        /// <param name="username">Authentication username.</param>
-        /// <param name="password">Authentication password.</param>
-        public RequestMessagePassword(ServiceName serviceName, string username, byte[] password)
-            : base(serviceName, username, "password")
-        {
-            Password = password;
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="RequestMessagePassword"/> class.
-        /// </summary>
-        /// <param name="serviceName">Name of the service.</param>
-        /// <param name="username">Authentication username.</param>
-        /// <param name="password">Authentication password.</param>
-        /// <param name="newPassword">New authentication password.</param>
-        public RequestMessagePassword(ServiceName serviceName, string username, byte[] password, byte[] newPassword)
-            : this(serviceName, username, password)
-        {
-            NewPassword = newPassword;
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be saved.
-        /// </summary>
-        protected override void SaveData()
-        {
-            base.SaveData();
-
-            Write(NewPassword != null);
-            WriteBinaryString(Password);
-            if (NewPassword != null)
-            {
-                WriteBinaryString(NewPassword);
-            }
-        }
-    }
-}
+namespace Renci.SshNet.Messages.Authentication
+{
+    /// <summary>
+    /// Represents "password" SSH_MSG_USERAUTH_REQUEST message.
+    /// </summary>
+    internal class RequestMessagePassword : RequestMessage
+    {
+        /// <summary>
+        /// Gets authentication password.
+        /// </summary>
+        public byte[] Password { get; private set; }
+
+        /// <summary>
+        /// Gets new authentication password.
+        /// </summary>
+        public byte[] NewPassword { get; private set; }
+
+        /// <summary>
+        /// Gets the size of the message in bytes.
+        /// </summary>
+        /// <value>
+        /// The size of the messages in bytes.
+        /// </value>
+        protected override int BufferCapacity
+        {
+            get
+            {
+                var capacity = base.BufferCapacity;
+                capacity += 1; // NewPassword flag
+                capacity += 4; // Password length
+                capacity += Password.Length; // Password
+
+                if (NewPassword != null)
+                {
+                    capacity += 4; // NewPassword length
+                    capacity += NewPassword.Length; // NewPassword
+                }
+
+                return capacity;
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RequestMessagePassword"/> class.
+        /// </summary>
+        /// <param name="serviceName">Name of the service.</param>
+        /// <param name="username">Authentication username.</param>
+        /// <param name="password">Authentication password.</param>
+        public RequestMessagePassword(ServiceName serviceName, string username, byte[] password)
+            : base(serviceName, username, "password")
+        {
+            Password = password;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RequestMessagePassword"/> class.
+        /// </summary>
+        /// <param name="serviceName">Name of the service.</param>
+        /// <param name="username">Authentication username.</param>
+        /// <param name="password">Authentication password.</param>
+        /// <param name="newPassword">New authentication password.</param>
+        public RequestMessagePassword(ServiceName serviceName, string username, byte[] password, byte[] newPassword)
+            : this(serviceName, username, password)
+        {
+            NewPassword = newPassword;
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be saved.
+        /// </summary>
+        protected override void SaveData()
+        {
+            base.SaveData();
+
+            Write(NewPassword != null);
+            WriteBinaryString(Password);
+            if (NewPassword != null)
+            {
+                WriteBinaryString(NewPassword);
+            }
+        }
+    }
+}

+ 98 - 98
src/Renci.SshNet/Messages/Authentication/RequestMessagePublicKey.cs

@@ -1,98 +1,98 @@
-namespace Renci.SshNet.Messages.Authentication
-{
-    /// <summary>
-    /// Represents "publickey" SSH_MSG_USERAUTH_REQUEST message.
-    /// </summary>
-    public class RequestMessagePublicKey : RequestMessage
-    {
-        /// <summary>
-        /// Gets the name of the public key algorithm as ASCII encoded byte array.
-        /// </summary>
-        /// <value>
-        /// The name of the public key algorithm.
-        /// </value>
-        public byte[] PublicKeyAlgorithmName { get; private set; }
-
-        /// <summary>
-        /// Gets the public key data.
-        /// </summary>
-        public byte[] PublicKeyData { get; private set; }
-
-        /// <summary>
-        /// Gets or sets public key signature.
-        /// </summary>
-        /// <value>
-        /// The signature.
-        /// </value>
-        public byte[] Signature { get; set; }
-
-        /// <summary>
-        /// Gets the size of the message in bytes.
-        /// </summary>
-        /// <value>
-        /// The size of the messages in bytes.
-        /// </value>
-        protected override int BufferCapacity
-        {
-            get
-            {
-                var capacity = base.BufferCapacity;
-                capacity += 1; // Signature flag
-                capacity += 4; // PublicKeyAlgorithmName length
-                capacity += PublicKeyAlgorithmName.Length; // PublicKeyAlgorithmName
-                capacity += 4; // PublicKeyData length
-                capacity += PublicKeyData.Length; // PublicKeyData
-
-                if (Signature != null)
-                {
-                    capacity += 4; // Signature length
-                    capacity += Signature.Length; // Signature
-                }
-
-                return capacity;
-            }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="RequestMessagePublicKey"/> class.
-        /// </summary>
-        /// <param name="serviceName">Name of the service.</param>
-        /// <param name="username">Authentication username.</param>
-        /// <param name="keyAlgorithmName">Name of private key algorithm.</param>
-        /// <param name="keyData">Private key data.</param>
-        public RequestMessagePublicKey(ServiceName serviceName, string username, string keyAlgorithmName, byte[] keyData)
-            : base(serviceName, username, "publickey")
-        {
-            PublicKeyAlgorithmName = Ascii.GetBytes(keyAlgorithmName);
-            PublicKeyData = keyData;
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="RequestMessagePublicKey"/> class.
-        /// </summary>
-        /// <param name="serviceName">Name of the service.</param>
-        /// <param name="username">Authentication username.</param>
-        /// <param name="keyAlgorithmName">Name of private key algorithm.</param>
-        /// <param name="keyData">Private key data.</param>
-        /// <param name="signature">Private key signature.</param>
-        public RequestMessagePublicKey(ServiceName serviceName, string username, string keyAlgorithmName, byte[] keyData, byte[] signature)
-            : this(serviceName, username, keyAlgorithmName, keyData)
-        {
-            Signature = signature;
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be saved.
-        /// </summary>
-        protected override void SaveData()
-        {
-            base.SaveData();
-
-            Write(Signature != null);
-            WriteBinaryString(PublicKeyAlgorithmName);
-            WriteBinaryString(PublicKeyData);
-            if (Signature != null)
-                WriteBinaryString(Signature);
-        }
-    }
-}
+namespace Renci.SshNet.Messages.Authentication
+{
+    /// <summary>
+    /// Represents "publickey" SSH_MSG_USERAUTH_REQUEST message.
+    /// </summary>
+    public class RequestMessagePublicKey : RequestMessage
+    {
+        /// <summary>
+        /// Gets the name of the public key algorithm as ASCII encoded byte array.
+        /// </summary>
+        /// <value>
+        /// The name of the public key algorithm.
+        /// </value>
+        public byte[] PublicKeyAlgorithmName { get; private set; }
+
+        /// <summary>
+        /// Gets the public key data.
+        /// </summary>
+        public byte[] PublicKeyData { get; private set; }
+
+        /// <summary>
+        /// Gets or sets public key signature.
+        /// </summary>
+        /// <value>
+        /// The signature.
+        /// </value>
+        public byte[] Signature { get; set; }
+
+        /// <summary>
+        /// Gets the size of the message in bytes.
+        /// </summary>
+        /// <value>
+        /// The size of the messages in bytes.
+        /// </value>
+        protected override int BufferCapacity
+        {
+            get
+            {
+                var capacity = base.BufferCapacity;
+                capacity += 1; // Signature flag
+                capacity += 4; // PublicKeyAlgorithmName length
+                capacity += PublicKeyAlgorithmName.Length; // PublicKeyAlgorithmName
+                capacity += 4; // PublicKeyData length
+                capacity += PublicKeyData.Length; // PublicKeyData
+
+                if (Signature != null)
+                {
+                    capacity += 4; // Signature length
+                    capacity += Signature.Length; // Signature
+                }
+
+                return capacity;
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RequestMessagePublicKey"/> class.
+        /// </summary>
+        /// <param name="serviceName">Name of the service.</param>
+        /// <param name="username">Authentication username.</param>
+        /// <param name="keyAlgorithmName">Name of private key algorithm.</param>
+        /// <param name="keyData">Private key data.</param>
+        public RequestMessagePublicKey(ServiceName serviceName, string username, string keyAlgorithmName, byte[] keyData)
+            : base(serviceName, username, "publickey")
+        {
+            PublicKeyAlgorithmName = Ascii.GetBytes(keyAlgorithmName);
+            PublicKeyData = keyData;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RequestMessagePublicKey"/> class.
+        /// </summary>
+        /// <param name="serviceName">Name of the service.</param>
+        /// <param name="username">Authentication username.</param>
+        /// <param name="keyAlgorithmName">Name of private key algorithm.</param>
+        /// <param name="keyData">Private key data.</param>
+        /// <param name="signature">Private key signature.</param>
+        public RequestMessagePublicKey(ServiceName serviceName, string username, string keyAlgorithmName, byte[] keyData, byte[] signature)
+            : this(serviceName, username, keyAlgorithmName, keyData)
+        {
+            Signature = signature;
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be saved.
+        /// </summary>
+        protected override void SaveData()
+        {
+            base.SaveData();
+
+            Write(Signature != null);
+            WriteBinaryString(PublicKeyAlgorithmName);
+            WriteBinaryString(PublicKeyData);
+            if (Signature != null)
+                WriteBinaryString(Signature);
+        }
+    }
+}

+ 23 - 23
src/Renci.SshNet/Messages/Authentication/SuccessMessage.cs

@@ -1,23 +1,23 @@
-namespace Renci.SshNet.Messages.Authentication
-{
-    /// <summary>
-    /// Represents SSH_MSG_USERAUTH_SUCCESS message.
-    /// </summary>
-    [Message("SSH_MSG_USERAUTH_SUCCESS", 52)]
-    public class SuccessMessage : Message
-    {
-        /// <summary>
-        /// Called when type specific data need to be loaded.
-        /// </summary>
-        protected override void LoadData()
-        {
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be saved.
-        /// </summary>
-        protected override void SaveData()
-        {
-        }
-    }
-}
+namespace Renci.SshNet.Messages.Authentication
+{
+    /// <summary>
+    /// Represents SSH_MSG_USERAUTH_SUCCESS message.
+    /// </summary>
+    [Message("SSH_MSG_USERAUTH_SUCCESS", 52)]
+    public class SuccessMessage : Message
+    {
+        /// <summary>
+        /// Called when type specific data need to be loaded.
+        /// </summary>
+        protected override void LoadData()
+        {
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be saved.
+        /// </summary>
+        protected override void SaveData()
+        {
+        }
+    }
+}

+ 26 - 26
src/Renci.SshNet/Messages/Connection/ChannelCloseMessage.cs

@@ -1,26 +1,26 @@
-namespace Renci.SshNet.Messages.Connection
-{
-    /// <summary>
-    /// Represents SSH_MSG_CHANNEL_CLOSE message.
-    /// </summary>
-    [Message("SSH_MSG_CHANNEL_CLOSE", 97)]
-    public class ChannelCloseMessage : ChannelMessage
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ChannelCloseMessage"/> class.
-        /// </summary>
-        public ChannelCloseMessage()
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ChannelCloseMessage"/> class.
-        /// </summary>
-        /// <param name="localChannelNumber">The local channel number.</param>
-        public ChannelCloseMessage(uint localChannelNumber)
-            : base(localChannelNumber)
-        {
-        }
-    }
-}
+namespace Renci.SshNet.Messages.Connection
+{
+    /// <summary>
+    /// Represents SSH_MSG_CHANNEL_CLOSE message.
+    /// </summary>
+    [Message("SSH_MSG_CHANNEL_CLOSE", 97)]
+    public class ChannelCloseMessage : ChannelMessage
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ChannelCloseMessage"/> class.
+        /// </summary>
+        public ChannelCloseMessage()
+        {
+
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ChannelCloseMessage"/> class.
+        /// </summary>
+        /// <param name="localChannelNumber">The local channel number.</param>
+        public ChannelCloseMessage(uint localChannelNumber)
+            : base(localChannelNumber)
+        {
+        }
+    }
+}

+ 118 - 118
src/Renci.SshNet/Messages/Connection/ChannelDataMessage.cs

@@ -1,118 +1,118 @@
-using System;
-
-namespace Renci.SshNet.Messages.Connection
-{
-    /// <summary>
-    /// Represents SSH_MSG_CHANNEL_DATA message.
-    /// </summary>
-    [Message("SSH_MSG_CHANNEL_DATA", MessageNumber)]
-    public class ChannelDataMessage : ChannelMessage
-    {
-        internal const byte MessageNumber = 94;
-
-        /// <summary>
-        /// Gets or sets message data.
-        /// </summary>
-        /// <value>
-        /// The data.
-        /// </value>
-        /// <remarks>
-        /// The actual data to read or write depends on the <see cref="Offset"/> and <see cref="Size"/>.
-        /// </remarks>
-        public byte[] Data { get; private set; }
-
-        /// <summary>
-        /// Gets the zero-based offset in <see cref="Data"/> at which the data begins.
-        /// </summary>
-        /// <value>
-        /// The zero-based offset in <see cref="Data"/> at which the data begins.
-        /// </value>
-        public int Offset { get; set; }
-
-        /// <summary>
-        /// Gets the number of bytes of <see cref="Data"/> to read or write.
-        /// </summary>
-        /// <value>
-        /// The number of bytes of <see cref="Data"/> to read or write.
-        /// </value>
-        public int Size { get; set; }
-
-        /// <summary>
-        /// Gets the size of the message in bytes.
-        /// </summary>
-        /// <value>
-        /// The size of the messages in bytes.
-        /// </value>
-        protected override int BufferCapacity
-        {
-            get
-            {
-                var capacity = base.BufferCapacity;
-                capacity += 4; // Data length
-                capacity += Size; // Data
-                return capacity;
-            }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ChannelDataMessage"/> class.
-        /// </summary>
-        public ChannelDataMessage()
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ChannelDataMessage"/> class.
-        /// </summary>
-        /// <param name="localChannelNumber">The local channel number.</param>
-        /// <param name="data">Message data.</param>
-        public ChannelDataMessage(uint localChannelNumber, byte[] data)
-            : base(localChannelNumber)
-        {
-            if (data == null)
-                throw new ArgumentNullException("data");
-
-            Data = data;
-            Offset = 0;
-            Size = data.Length;
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ChannelDataMessage"/> class.
-        /// </summary>
-        /// <param name="localChannelNumber">The local channel number.</param>
-        /// <param name="data">The message data.</param>
-        /// <param name="offset">The zero-based byte offset in <paramref name="data"/> at which to begin reading or writing data from.</param>
-        /// <param name="size">The number of bytes of <paramref name="data"/> to read or write.</param>
-        public ChannelDataMessage(uint localChannelNumber, byte[] data, int offset, int size)
-            : base(localChannelNumber)
-        {
-            if (data == null)
-                throw new ArgumentNullException("data");
-
-            Data = data;
-            Offset = offset;
-            Size = size;
-        }
-
-        /// <summary>
-        /// Loads the data.
-        /// </summary>
-        protected override void LoadData()
-        {
-            base.LoadData();
-            Data = ReadBinary();
-            Offset = 0;
-            Size = Data.Length;
-        }
-
-        /// <summary>
-        /// Saves the data.
-        /// </summary>
-        protected override void SaveData()
-        {
-            base.SaveData();
-            WriteBinary(Data, Offset, Size);
-        }
-    }
-}
+using System;
+
+namespace Renci.SshNet.Messages.Connection
+{
+    /// <summary>
+    /// Represents SSH_MSG_CHANNEL_DATA message.
+    /// </summary>
+    [Message("SSH_MSG_CHANNEL_DATA", MessageNumber)]
+    public class ChannelDataMessage : ChannelMessage
+    {
+        internal const byte MessageNumber = 94;
+
+        /// <summary>
+        /// Gets or sets message data.
+        /// </summary>
+        /// <value>
+        /// The data.
+        /// </value>
+        /// <remarks>
+        /// The actual data to read or write depends on the <see cref="Offset"/> and <see cref="Size"/>.
+        /// </remarks>
+        public byte[] Data { get; private set; }
+
+        /// <summary>
+        /// Gets the zero-based offset in <see cref="Data"/> at which the data begins.
+        /// </summary>
+        /// <value>
+        /// The zero-based offset in <see cref="Data"/> at which the data begins.
+        /// </value>
+        public int Offset { get; set; }
+
+        /// <summary>
+        /// Gets the number of bytes of <see cref="Data"/> to read or write.
+        /// </summary>
+        /// <value>
+        /// The number of bytes of <see cref="Data"/> to read or write.
+        /// </value>
+        public int Size { get; set; }
+
+        /// <summary>
+        /// Gets the size of the message in bytes.
+        /// </summary>
+        /// <value>
+        /// The size of the messages in bytes.
+        /// </value>
+        protected override int BufferCapacity
+        {
+            get
+            {
+                var capacity = base.BufferCapacity;
+                capacity += 4; // Data length
+                capacity += Size; // Data
+                return capacity;
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ChannelDataMessage"/> class.
+        /// </summary>
+        public ChannelDataMessage()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ChannelDataMessage"/> class.
+        /// </summary>
+        /// <param name="localChannelNumber">The local channel number.</param>
+        /// <param name="data">Message data.</param>
+        public ChannelDataMessage(uint localChannelNumber, byte[] data)
+            : base(localChannelNumber)
+        {
+            if (data == null)
+                throw new ArgumentNullException("data");
+
+            Data = data;
+            Offset = 0;
+            Size = data.Length;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ChannelDataMessage"/> class.
+        /// </summary>
+        /// <param name="localChannelNumber">The local channel number.</param>
+        /// <param name="data">The message data.</param>
+        /// <param name="offset">The zero-based byte offset in <paramref name="data"/> at which to begin reading or writing data from.</param>
+        /// <param name="size">The number of bytes of <paramref name="data"/> to read or write.</param>
+        public ChannelDataMessage(uint localChannelNumber, byte[] data, int offset, int size)
+            : base(localChannelNumber)
+        {
+            if (data == null)
+                throw new ArgumentNullException("data");
+
+            Data = data;
+            Offset = offset;
+            Size = size;
+        }
+
+        /// <summary>
+        /// Loads the data.
+        /// </summary>
+        protected override void LoadData()
+        {
+            base.LoadData();
+            Data = ReadBinary();
+            Offset = 0;
+            Size = Data.Length;
+        }
+
+        /// <summary>
+        /// Saves the data.
+        /// </summary>
+        protected override void SaveData()
+        {
+            base.SaveData();
+            WriteBinary(Data, Offset, Size);
+        }
+    }
+}

+ 26 - 26
src/Renci.SshNet/Messages/Connection/ChannelEofMessage.cs

@@ -1,26 +1,26 @@
-namespace Renci.SshNet.Messages.Connection
-{
-    /// <summary>
-    /// Represents SSH_MSG_CHANNEL_EOF message.
-    /// </summary>
-    [Message("SSH_MSG_CHANNEL_EOF", 96)]
-    public class ChannelEofMessage : ChannelMessage
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ChannelEofMessage"/> class.
-        /// </summary>
-        public ChannelEofMessage()
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ChannelEofMessage"/> class.
-        /// </summary>
-        /// <param name="localChannelNumber">The local channel number.</param>
-        public ChannelEofMessage(uint localChannelNumber)
-            : base(localChannelNumber)
-        {
-        }
-    }
-}
+namespace Renci.SshNet.Messages.Connection
+{
+    /// <summary>
+    /// Represents SSH_MSG_CHANNEL_EOF message.
+    /// </summary>
+    [Message("SSH_MSG_CHANNEL_EOF", 96)]
+    public class ChannelEofMessage : ChannelMessage
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ChannelEofMessage"/> class.
+        /// </summary>
+        public ChannelEofMessage()
+        {
+
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ChannelEofMessage"/> class.
+        /// </summary>
+        /// <param name="localChannelNumber">The local channel number.</param>
+        public ChannelEofMessage(uint localChannelNumber)
+            : base(localChannelNumber)
+        {
+        }
+    }
+}

+ 77 - 77
src/Renci.SshNet/Messages/Connection/ChannelExtendedDataMessage.cs

@@ -1,77 +1,77 @@
-namespace Renci.SshNet.Messages.Connection
-{
-    /// <summary>
-    /// Represents SSH_MSG_CHANNEL_EXTENDED_DATA message.
-    /// </summary>
-    [Message("SSH_MSG_CHANNEL_EXTENDED_DATA", 95)]
-    public class ChannelExtendedDataMessage : ChannelMessage
-    {
-        /// <summary>
-        /// Gets message data type code.
-        /// </summary>
-        public uint DataTypeCode { get; private set; }
-
-        /// <summary>
-        /// Gets message data.
-        /// </summary>
-        public byte[] Data { get; private set; }
-
-        /// <summary>
-        /// Gets the size of the message in bytes.
-        /// </summary>
-        /// <value>
-        /// The size of the messages in bytes.
-        /// </value>
-        protected override int BufferCapacity
-        {
-            get
-            {
-                var capacity = base.BufferCapacity;
-                capacity += 4; // DataTypeCode
-                capacity += 4; // Data length
-                capacity += Data.Length; // Data
-                return capacity;
-            }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ChannelExtendedDataMessage"/> class.
-        /// </summary>
-        public ChannelExtendedDataMessage()
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ChannelExtendedDataMessage"/> class.
-        /// </summary>
-        /// <param name="localChannelNumber">The local channel number.</param>
-        /// <param name="dataTypeCode">The message data type code.</param>
-        /// <param name="data">The message data.</param>
-        public ChannelExtendedDataMessage(uint localChannelNumber, uint dataTypeCode, byte[] data)
-            : base(localChannelNumber)
-        {
-            DataTypeCode = dataTypeCode;
-            Data = data;
-        }
-
-        /// <summary>
-        /// Loads the data.
-        /// </summary>
-        protected override void LoadData()
-        {
-            base.LoadData();
-            DataTypeCode = ReadUInt32();
-            Data = ReadBinary();
-        }
-
-        /// <summary>
-        /// Saves the data.
-        /// </summary>
-        protected override void SaveData()
-        {
-            base.SaveData();
-            Write(DataTypeCode);
-            WriteBinaryString(Data);
-        }
-    }
-}
+namespace Renci.SshNet.Messages.Connection
+{
+    /// <summary>
+    /// Represents SSH_MSG_CHANNEL_EXTENDED_DATA message.
+    /// </summary>
+    [Message("SSH_MSG_CHANNEL_EXTENDED_DATA", 95)]
+    public class ChannelExtendedDataMessage : ChannelMessage
+    {
+        /// <summary>
+        /// Gets message data type code.
+        /// </summary>
+        public uint DataTypeCode { get; private set; }
+
+        /// <summary>
+        /// Gets message data.
+        /// </summary>
+        public byte[] Data { get; private set; }
+
+        /// <summary>
+        /// Gets the size of the message in bytes.
+        /// </summary>
+        /// <value>
+        /// The size of the messages in bytes.
+        /// </value>
+        protected override int BufferCapacity
+        {
+            get
+            {
+                var capacity = base.BufferCapacity;
+                capacity += 4; // DataTypeCode
+                capacity += 4; // Data length
+                capacity += Data.Length; // Data
+                return capacity;
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ChannelExtendedDataMessage"/> class.
+        /// </summary>
+        public ChannelExtendedDataMessage()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ChannelExtendedDataMessage"/> class.
+        /// </summary>
+        /// <param name="localChannelNumber">The local channel number.</param>
+        /// <param name="dataTypeCode">The message data type code.</param>
+        /// <param name="data">The message data.</param>
+        public ChannelExtendedDataMessage(uint localChannelNumber, uint dataTypeCode, byte[] data)
+            : base(localChannelNumber)
+        {
+            DataTypeCode = dataTypeCode;
+            Data = data;
+        }
+
+        /// <summary>
+        /// Loads the data.
+        /// </summary>
+        protected override void LoadData()
+        {
+            base.LoadData();
+            DataTypeCode = ReadUInt32();
+            Data = ReadBinary();
+        }
+
+        /// <summary>
+        /// Saves the data.
+        /// </summary>
+        protected override void SaveData()
+        {
+            base.SaveData();
+            Write(DataTypeCode);
+            WriteBinaryString(Data);
+        }
+    }
+}

+ 26 - 26
src/Renci.SshNet/Messages/Connection/ChannelFailureMessage.cs

@@ -1,26 +1,26 @@
-namespace Renci.SshNet.Messages.Connection
-{
-    /// <summary>
-    /// Represents SSH_MSG_CHANNEL_FAILURE message.
-    /// </summary>
-    [Message("SSH_MSG_CHANNEL_FAILURE", 100)]
-    public class ChannelFailureMessage : ChannelMessage
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ChannelFailureMessage"/> class.
-        /// </summary>
-        public ChannelFailureMessage()
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ChannelFailureMessage"/> class.
-        /// </summary>
-        /// <param name="localChannelNumber">The local channel number.</param>
-        public ChannelFailureMessage(uint localChannelNumber)
-            : base(localChannelNumber)
-        {
-        }
-    }
-}
+namespace Renci.SshNet.Messages.Connection
+{
+    /// <summary>
+    /// Represents SSH_MSG_CHANNEL_FAILURE message.
+    /// </summary>
+    [Message("SSH_MSG_CHANNEL_FAILURE", 100)]
+    public class ChannelFailureMessage : ChannelMessage
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ChannelFailureMessage"/> class.
+        /// </summary>
+        public ChannelFailureMessage()
+        {
+
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ChannelFailureMessage"/> class.
+        /// </summary>
+        /// <param name="localChannelNumber">The local channel number.</param>
+        public ChannelFailureMessage(uint localChannelNumber)
+            : base(localChannelNumber)
+        {
+        }
+    }
+}

+ 77 - 77
src/Renci.SshNet/Messages/Connection/ChannelMessage.cs

@@ -1,77 +1,77 @@
-using System.Globalization;
-
-namespace Renci.SshNet.Messages.Connection
-{
-    /// <summary>
-    /// Base class for all channel specific SSH messages.
-    /// </summary>
-    public abstract class ChannelMessage : Message
-    {
-        /// <summary>
-        /// Gets or sets the local channel number.
-        /// </summary>
-        /// <value>
-        /// The local channel number.
-        /// </value>
-        public uint LocalChannelNumber { get; protected set; }
-
-        /// <summary>
-        /// Gets the size of the message in bytes.
-        /// </summary>
-        /// <value>
-        /// The size of the messages in bytes.
-        /// </value>
-        protected override int BufferCapacity
-        {
-            get
-            {
-                var capacity = base.BufferCapacity;
-                capacity += 4; // LocalChannelNumber
-                return capacity;
-            }
-        }
-
-        /// <summary>
-        /// Initializes a new <see cref="ChannelMessage"/>.
-        /// </summary>
-        protected ChannelMessage()
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new <see cref="ChannelMessage"/> with the specified local channel number.
-        /// </summary>
-        /// <param name="localChannelNumber">The local channel number.</param>
-        protected ChannelMessage(uint localChannelNumber)
-        {
-            LocalChannelNumber = localChannelNumber;
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be loaded.
-        /// </summary>
-        protected override void LoadData()
-        {
-            LocalChannelNumber = ReadUInt32();
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be saved.
-        /// </summary>
-        protected override void SaveData()
-        {
-            Write(LocalChannelNumber);
-        }
-
-        /// <summary>
-        /// Returns a <see cref="System.String"/> that represents this instance.
-        /// </summary>
-        /// <returns>
-        /// A <see cref="System.String"/> that represents this instance.
-        /// </returns>
-        public override string ToString()
-        {
-            return string.Format(CultureInfo.CurrentCulture, "{0} : #{1}", base.ToString(), LocalChannelNumber);
-        }
-    }
-}
+using System.Globalization;
+
+namespace Renci.SshNet.Messages.Connection
+{
+    /// <summary>
+    /// Base class for all channel specific SSH messages.
+    /// </summary>
+    public abstract class ChannelMessage : Message
+    {
+        /// <summary>
+        /// Gets or sets the local channel number.
+        /// </summary>
+        /// <value>
+        /// The local channel number.
+        /// </value>
+        public uint LocalChannelNumber { get; protected set; }
+
+        /// <summary>
+        /// Gets the size of the message in bytes.
+        /// </summary>
+        /// <value>
+        /// The size of the messages in bytes.
+        /// </value>
+        protected override int BufferCapacity
+        {
+            get
+            {
+                var capacity = base.BufferCapacity;
+                capacity += 4; // LocalChannelNumber
+                return capacity;
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new <see cref="ChannelMessage"/>.
+        /// </summary>
+        protected ChannelMessage()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new <see cref="ChannelMessage"/> with the specified local channel number.
+        /// </summary>
+        /// <param name="localChannelNumber">The local channel number.</param>
+        protected ChannelMessage(uint localChannelNumber)
+        {
+            LocalChannelNumber = localChannelNumber;
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be loaded.
+        /// </summary>
+        protected override void LoadData()
+        {
+            LocalChannelNumber = ReadUInt32();
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be saved.
+        /// </summary>
+        protected override void SaveData()
+        {
+            Write(LocalChannelNumber);
+        }
+
+        /// <summary>
+        /// Returns a <see cref="System.String"/> that represents this instance.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="System.String"/> that represents this instance.
+        /// </returns>
+        public override string ToString()
+        {
+            return string.Format(CultureInfo.CurrentCulture, "{0} : #{1}", base.ToString(), LocalChannelNumber);
+        }
+    }
+}

+ 32 - 32
src/Renci.SshNet/Messages/Connection/ChannelOpen/ChannelOpenInfo.cs

@@ -1,32 +1,32 @@
-using Renci.SshNet.Common;
-
-namespace Renci.SshNet.Messages.Connection
-{
-    /// <summary>
-    /// Base class for open channel messages
-    /// </summary>
-    public abstract class ChannelOpenInfo : SshData
-    {
-        /// <summary>
-        /// Gets the type of the channel to open.
-        /// </summary>
-        /// <value>
-        /// The type of the channel to open.
-        /// </value>
-        public abstract string ChannelType { get; }
-
-        /// <summary>
-        /// Called when type specific data need to be loaded.
-        /// </summary>
-        protected override void LoadData()
-        {
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be saved.
-        /// </summary>
-        protected override void SaveData()
-        {
-        }
-    }
-}
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet.Messages.Connection
+{
+    /// <summary>
+    /// Base class for open channel messages
+    /// </summary>
+    public abstract class ChannelOpenInfo : SshData
+    {
+        /// <summary>
+        /// Gets the type of the channel to open.
+        /// </summary>
+        /// <value>
+        /// The type of the channel to open.
+        /// </value>
+        public abstract string ChannelType { get; }
+
+        /// <summary>
+        /// Called when type specific data need to be loaded.
+        /// </summary>
+        protected override void LoadData()
+        {
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be saved.
+        /// </summary>
+        protected override void SaveData()
+        {
+        }
+    }
+}

+ 147 - 147
src/Renci.SshNet/Messages/Connection/ChannelOpen/ChannelOpenMessage.cs

@@ -1,147 +1,147 @@
-using System;
-using System.Globalization;
-
-namespace Renci.SshNet.Messages.Connection
-{
-    /// <summary>
-    /// Represents SSH_MSG_CHANNEL_OPEN message.
-    /// </summary>
-    [Message("SSH_MSG_CHANNEL_OPEN", MessageNumber)]
-    public class ChannelOpenMessage : Message
-    {
-        internal const byte MessageNumber = 90;
-
-        private byte[] _infoBytes;
-
-        /// <summary>
-        /// Gets the type of the channel as ASCII encoded byte array.
-        /// </summary>
-        /// <value>
-        /// The type of the channel.
-        /// </value>
-        public byte[] ChannelType { get; private set; }
-
-        /// <summary>
-        /// Gets or sets the local channel number.
-        /// </summary>
-        /// <value>
-        /// The local channel number.
-        /// </value>
-        public uint LocalChannelNumber { get; protected set; }
-
-        /// <summary>
-        /// Gets the initial size of the window.
-        /// </summary>
-        /// <value>
-        /// The initial size of the window.
-        /// </value>
-        public uint InitialWindowSize { get; private set; }
-
-        /// <summary>
-        /// Gets the maximum size of the packet.
-        /// </summary>
-        /// <value>
-        /// The maximum size of the packet.
-        /// </value>
-        public uint MaximumPacketSize { get; private set; }
-
-        /// <summary>
-        /// Gets channel specific open information.
-        /// </summary>
-        public ChannelOpenInfo Info { get; private set; }
-
-        /// <summary>
-        /// Gets the size of the message in bytes.
-        /// </summary>
-        /// <value>
-        /// The size of the messages in bytes.
-        /// </value>
-        protected override int BufferCapacity
-        {
-            get
-            {
-                var capacity = base.BufferCapacity;
-                capacity += 4; // ChannelType length
-                capacity += ChannelType.Length; // ChannelType
-                capacity += 4; // LocalChannelNumber
-                capacity += 4; // InitialWindowSize
-                capacity += 4; // MaximumPacketSize
-                capacity += _infoBytes.Length; // Info
-                return capacity;
-            }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ChannelOpenMessage"/> class.
-        /// </summary>
-        public ChannelOpenMessage()
-        {
-            //  Required for dynamicly loading request type when it comes from the server
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ChannelOpenMessage"/> class.
-        /// </summary>
-        /// <param name="channelNumber">The channel number.</param>
-        /// <param name="initialWindowSize">Initial size of the window.</param>
-        /// <param name="maximumPacketSize">Maximum size of the packet.</param>
-        /// <param name="info">Information specific to the type of the channel to open.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="info"/> is <c>null</c>.</exception>
-        public ChannelOpenMessage(uint channelNumber, uint initialWindowSize, uint maximumPacketSize, ChannelOpenInfo info)
-        {
-            if (info == null)
-                throw new ArgumentNullException("info");
-
-            ChannelType = Ascii.GetBytes(info.ChannelType);
-            LocalChannelNumber = channelNumber;
-            InitialWindowSize = initialWindowSize;
-            MaximumPacketSize = maximumPacketSize;
-            Info = info;
-            _infoBytes = info.GetBytes();
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be loaded.
-        /// </summary>
-        protected override void LoadData()
-        {
-            ChannelType = ReadBinary();
-            LocalChannelNumber = ReadUInt32();
-            InitialWindowSize = ReadUInt32();
-            MaximumPacketSize = ReadUInt32();
-            _infoBytes = ReadBytes();
-
-            var channelName = Ascii.GetString(ChannelType, 0, ChannelType.Length);
-
-            switch (channelName)
-            {
-                case SessionChannelOpenInfo.Name:
-                    Info = new SessionChannelOpenInfo(_infoBytes);
-                    break;
-                case X11ChannelOpenInfo.Name:
-                    Info = new X11ChannelOpenInfo(_infoBytes);
-                    break;
-                case DirectTcpipChannelInfo.NAME:
-                    Info = new DirectTcpipChannelInfo(_infoBytes);
-                    break;
-                case ForwardedTcpipChannelInfo.NAME:
-                    Info = new ForwardedTcpipChannelInfo(_infoBytes);
-                    break;
-                default:
-                    throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Channel type '{0}' is not supported.", channelName));
-            }
-        }
-
-        /// <summary>
-        /// Called when type specific data need to be saved.
-        /// </summary>
-        protected override void SaveData()
-        {
-            WriteBinaryString(ChannelType);
-            Write(LocalChannelNumber);
-            Write(InitialWindowSize);
-            Write(MaximumPacketSize);
-            Write(_infoBytes);
-        }
-    }
-}
+using System;
+using System.Globalization;
+
+namespace Renci.SshNet.Messages.Connection
+{
+    /// <summary>
+    /// Represents SSH_MSG_CHANNEL_OPEN message.
+    /// </summary>
+    [Message("SSH_MSG_CHANNEL_OPEN", MessageNumber)]
+    public class ChannelOpenMessage : Message
+    {
+        internal const byte MessageNumber = 90;
+
+        private byte[] _infoBytes;
+
+        /// <summary>
+        /// Gets the type of the channel as ASCII encoded byte array.
+        /// </summary>
+        /// <value>
+        /// The type of the channel.
+        /// </value>
+        public byte[] ChannelType { get; private set; }
+
+        /// <summary>
+        /// Gets or sets the local channel number.
+        /// </summary>
+        /// <value>
+        /// The local channel number.
+        /// </value>
+        public uint LocalChannelNumber { get; protected set; }
+
+        /// <summary>
+        /// Gets the initial size of the window.
+        /// </summary>
+        /// <value>
+        /// The initial size of the window.
+        /// </value>
+        public uint InitialWindowSize { get; private set; }
+
+        /// <summary>
+        /// Gets the maximum size of the packet.
+        /// </summary>
+        /// <value>
+        /// The maximum size of the packet.
+        /// </value>
+        public uint MaximumPacketSize { get; private set; }
+
+        /// <summary>
+        /// Gets channel specific open information.
+        /// </summary>
+        public ChannelOpenInfo Info { get; private set; }
+
+        /// <summary>
+        /// Gets the size of the message in bytes.
+        /// </summary>
+        /// <value>
+        /// The size of the messages in bytes.
+        /// </value>
+        protected override int BufferCapacity
+        {
+            get
+            {
+                var capacity = base.BufferCapacity;
+                capacity += 4; // ChannelType length
+                capacity += ChannelType.Length; // ChannelType
+                capacity += 4; // LocalChannelNumber
+                capacity += 4; // InitialWindowSize
+                capacity += 4; // MaximumPacketSize
+                capacity += _infoBytes.Length; // Info
+                return capacity;
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ChannelOpenMessage"/> class.
+        /// </summary>
+        public ChannelOpenMessage()
+        {
+            //  Required for dynamicly loading request type when it comes from the server
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ChannelOpenMessage"/> class.
+        /// </summary>
+        /// <param name="channelNumber">The channel number.</param>
+        /// <param name="initialWindowSize">Initial size of the window.</param>
+        /// <param name="maximumPacketSize">Maximum size of the packet.</param>
+        /// <param name="info">Information specific to the type of the channel to open.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="info"/> is <c>null</c>.</exception>
+        public ChannelOpenMessage(uint channelNumber, uint initialWindowSize, uint maximumPacketSize, ChannelOpenInfo info)
+        {
+            if (info == null)
+                throw new ArgumentNullException("info");
+
+            ChannelType = Ascii.GetBytes(info.ChannelType);
+            LocalChannelNumber = channelNumber;
+            InitialWindowSize = initialWindowSize;
+            MaximumPacketSize = maximumPacketSize;
+            Info = info;
+            _infoBytes = info.GetBytes();
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be loaded.
+        /// </summary>
+        protected override void LoadData()
+        {
+            ChannelType = ReadBinary();
+            LocalChannelNumber = ReadUInt32();
+            InitialWindowSize = ReadUInt32();
+            MaximumPacketSize = ReadUInt32();
+            _infoBytes = ReadBytes();
+
+            var channelName = Ascii.GetString(ChannelType, 0, ChannelType.Length);
+
+            switch (channelName)
+            {
+                case SessionChannelOpenInfo.Name:
+                    Info = new SessionChannelOpenInfo(_infoBytes);
+                    break;
+                case X11ChannelOpenInfo.Name:
+                    Info = new X11ChannelOpenInfo(_infoBytes);
+                    break;
+                case DirectTcpipChannelInfo.NAME:
+                    Info = new DirectTcpipChannelInfo(_infoBytes);
+                    break;
+                case ForwardedTcpipChannelInfo.NAME:
+                    Info = new ForwardedTcpipChannelInfo(_infoBytes);
+                    break;
+                default:
+                    throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Channel type '{0}' is not supported.", channelName));
+            }
+        }
+
+        /// <summary>
+        /// Called when type specific data need to be saved.
+        /// </summary>
+        protected override void SaveData()
+        {
+            WriteBinaryString(ChannelType);
+            Write(LocalChannelNumber);
+            Write(InitialWindowSize);
+            Write(MaximumPacketSize);
+            Write(_infoBytes);
+        }
+    }
+}

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác