Explorar o código

Fix analyzer errors in Renci.SshNet and Renci.SshNet.TestTools.OpenSSH (#1229)

* Fix analyzer errors in Renci.SshNet and Renci.SshNet.TestTools.OpenSSH.
Suppress all errors in unit tests and integration tests.

* Update unit tests now that we pass 'mode' as argument name when we throw ArgumentException.

* Remove stale comment and add unit tests for SshData.ReadBytes(int length).

* Remove unnessary suppression.

* Remove Visual Studio magic.

* Removed duplicate source file.

* Clarified that suppression hides a false positive.

* Remove suppressions for S2372.

* Update ReadExtensionPair() to return concrete dictionary.
Gert Driesen %!s(int64=2) %!d(string=hai) anos
pai
achega
508fc87d2a
Modificáronse 100 ficheiros con 1094 adicións e 523 borrados
  1. 50 0
      .editorconfig
  2. 3 5
      Directory.Build.props
  3. 121 2
      src/Renci.SshNet/.editorconfig
  4. 0 4
      src/Renci.SshNet/Abstractions/DiagnosticAbstraction.cs
  5. 3 3
      src/Renci.SshNet/Abstractions/DnsAbstraction.cs
  6. 1 1
      src/Renci.SshNet/Abstractions/ReflectionAbstraction.cs
  7. 6 6
      src/Renci.SshNet/Abstractions/SocketAbstraction.cs
  8. 22 9
      src/Renci.SshNet/Abstractions/SocketExtensions.cs
  9. 17 5
      src/Renci.SshNet/Abstractions/ThreadAbstraction.cs
  10. 2 0
      src/Renci.SshNet/AuthenticationMethod.cs
  11. 3 1
      src/Renci.SshNet/AuthenticationResult.cs
  12. 11 4
      src/Renci.SshNet/BaseClient.cs
  13. 7 7
      src/Renci.SshNet/Channels/Channel.cs
  14. 4 4
      src/Renci.SshNet/Channels/ChannelForwardedTcpip.cs
  15. 1 1
      src/Renci.SshNet/Channels/ChannelSession.cs
  16. 8 6
      src/Renci.SshNet/Channels/ChannelTypes.cs
  17. 1 1
      src/Renci.SshNet/Channels/ClientChannel.cs
  18. 6 2
      src/Renci.SshNet/Channels/IChannelSession.cs
  19. 1 1
      src/Renci.SshNet/CipherInfo.cs
  20. 20 6
      src/Renci.SshNet/ClientAuthentication.cs
  21. 0 46
      src/Renci.SshNet/Common/AsyncResult.cs
  22. 50 0
      src/Renci.SshNet/Common/AsyncResult{TResult}.cs
  23. 134 41
      src/Renci.SshNet/Common/BigInteger.cs
  24. 9 1
      src/Renci.SshNet/Common/ChannelDataEventArgs.cs
  25. 6 0
      src/Renci.SshNet/Common/ChannelRequestEventArgs.cs
  26. 1 1
      src/Renci.SshNet/Common/DerData.cs
  27. 2 1
      src/Renci.SshNet/Common/Extensions.cs
  28. 30 14
      src/Renci.SshNet/Common/HostKeyEventArgs.cs
  29. 1 1
      src/Renci.SshNet/Common/NetConfServerException.cs
  30. 2 0
      src/Renci.SshNet/Common/ObjectIdentifier.cs
  31. 30 15
      src/Renci.SshNet/Common/PipeStream.cs
  32. 2 2
      src/Renci.SshNet/Common/SemaphoreLight.cs
  33. 11 0
      src/Renci.SshNet/Common/SshConnectionException.cs
  34. 31 15
      src/Renci.SshNet/Common/SshData.cs
  35. 18 18
      src/Renci.SshNet/Common/SshDataStream.cs
  36. 5 1
      src/Renci.SshNet/Common/TerminalModes.cs
  37. 1 1
      src/Renci.SshNet/Compression/CompressionMode.cs
  38. 7 5
      src/Renci.SshNet/Compression/Compressor.cs
  39. 2 2
      src/Renci.SshNet/Compression/Zlib.cs
  40. 3 3
      src/Renci.SshNet/Compression/ZlibOpenSsh.cs
  41. 9 0
      src/Renci.SshNet/Compression/ZlibStream.cs
  42. 18 0
      src/Renci.SshNet/Connection/IConnector.cs
  43. 13 1
      src/Renci.SshNet/Connection/IProtocolVersionExchange.cs
  44. 14 0
      src/Renci.SshNet/Connection/ISocketFactory.cs
  45. 11 1
      src/Renci.SshNet/Connection/ProtocolVersionExchange.cs
  46. 33 2
      src/Renci.SshNet/Connection/ProxyConnector.cs
  47. 15 1
      src/Renci.SshNet/Connection/SocketFactory.cs
  48. 17 15
      src/Renci.SshNet/Connection/Socks4Connector.cs
  49. 34 28
      src/Renci.SshNet/Connection/Socks5Connector.cs
  50. 18 2
      src/Renci.SshNet/ConnectionInfo.cs
  51. 4 2
      src/Renci.SshNet/ForwardedPortDynamic.cs
  52. 2 0
      src/Renci.SshNet/ForwardedPortStatus.cs
  53. 2 2
      src/Renci.SshNet/HashInfo.cs
  54. 1 6
      src/Renci.SshNet/IBaseClient.cs
  55. 17 1
      src/Renci.SshNet/IClientAuthentication.cs
  56. 0 29
      src/Renci.SshNet/IConnectionInfo.cs
  57. 37 0
      src/Renci.SshNet/IConnectionInfoInternal.cs
  58. 0 30
      src/Renci.SshNet/IForwardedPort.cs
  59. 4 1
      src/Renci.SshNet/ISession.cs
  60. 20 18
      src/Renci.SshNet/ISftpClient.cs
  61. 5 5
      src/Renci.SshNet/ISubsystemSession.cs
  62. 2 1
      src/Renci.SshNet/KeyboardInteractiveConnectionInfo.cs
  63. 7 1
      src/Renci.SshNet/Messages/Authentication/FailureMessage.cs
  64. 2 1
      src/Renci.SshNet/Messages/Authentication/InformationResponseMessage.cs
  65. 0 1
      src/Renci.SshNet/Messages/Authentication/RequestMessage.cs
  66. 1 1
      src/Renci.SshNet/Messages/Authentication/RequestMessageNone.cs
  67. 0 1
      src/Renci.SshNet/Messages/Connection/ChannelCloseMessage.cs
  68. 0 1
      src/Renci.SshNet/Messages/Connection/ChannelEofMessage.cs
  69. 0 1
      src/Renci.SshNet/Messages/Connection/ChannelFailureMessage.cs
  70. 1 1
      src/Renci.SshNet/Messages/Connection/ChannelOpen/ChannelOpenInfo.cs
  71. 2 2
      src/Renci.SshNet/Messages/Connection/ChannelOpen/DirectTcpipChannelInfo.cs
  72. 20 8
      src/Renci.SshNet/Messages/Connection/ChannelOpen/ForwardedTcpipChannelInfo.cs
  73. 2 2
      src/Renci.SshNet/Messages/Connection/ChannelOpen/SessionChannelOpenInfo.cs
  74. 2 2
      src/Renci.SshNet/Messages/Connection/ChannelOpen/X11ChannelOpenInfo.cs
  75. 0 1
      src/Renci.SshNet/Messages/Connection/ChannelOpenFailureMessage.cs
  76. 7 4
      src/Renci.SshNet/Messages/Connection/ChannelOpenFailureReasons.cs
  77. 4 4
      src/Renci.SshNet/Messages/Connection/ChannelRequest/BreakRequestInfo.cs
  78. 5 2
      src/Renci.SshNet/Messages/Connection/ChannelRequest/ChannelRequestMessage.cs
  79. 2 2
      src/Renci.SshNet/Messages/Connection/ChannelRequest/EndOfWriteRequestInfo.cs
  80. 4 4
      src/Renci.SshNet/Messages/Connection/ChannelRequest/EnvironmentVariableRequestInfo.cs
  81. 3 3
      src/Renci.SshNet/Messages/Connection/ChannelRequest/ExitSignalRequestInfo.cs
  82. 2 2
      src/Renci.SshNet/Messages/Connection/ChannelRequest/ExitStatusRequestInfo.cs
  83. 3 3
      src/Renci.SshNet/Messages/Connection/ChannelRequest/KeepAliveRequestInfo.cs
  84. 1 1
      src/Renci.SshNet/Messages/Connection/ChannelRequest/PseudoTerminalRequestInfo.cs
  85. 1 1
      src/Renci.SshNet/Messages/Connection/ChannelRequest/RequestInfo.cs
  86. 2 2
      src/Renci.SshNet/Messages/Connection/ChannelRequest/ShellRequestInfo.cs
  87. 1 1
      src/Renci.SshNet/Messages/Connection/ChannelRequest/SignalRequestInfo.cs
  88. 2 2
      src/Renci.SshNet/Messages/Connection/ChannelRequest/SubsystemRequestInfo.cs
  89. 2 2
      src/Renci.SshNet/Messages/Connection/ChannelRequest/WindowChangeRequestInfo.cs
  90. 1 1
      src/Renci.SshNet/Messages/Connection/ChannelRequest/X11ForwardingRequestInfo.cs
  91. 2 2
      src/Renci.SshNet/Messages/Connection/ChannelRequest/XonXoffRequestInfo.cs
  92. 0 1
      src/Renci.SshNet/Messages/Connection/ChannelSuccessMessage.cs
  93. 1 1
      src/Renci.SshNet/Messages/Connection/GlobalRequestMessage.cs
  94. 3 2
      src/Renci.SshNet/Messages/Connection/GlobalRequestName.cs
  95. 59 54
      src/Renci.SshNet/Messages/Message.cs
  96. 4 5
      src/Renci.SshNet/Messages/MessageAttribute.cs
  97. 3 3
      src/Renci.SshNet/Messages/ServiceName.cs
  98. 1 1
      src/Renci.SshNet/Messages/Transport/DebugMessage.cs
  99. 33 16
      src/Renci.SshNet/Messages/Transport/DisconnectReason.cs
  100. 3 1
      src/Renci.SshNet/Messages/Transport/IKeyExchangedAllowed.cs

+ 50 - 0
.editorconfig

@@ -77,6 +77,12 @@ dotnet_diagnostic.S1172.severity = none
 # This is a duplicate of IDE0059.
 # This is a duplicate of IDE0059.
 dotnet_diagnostic.S1481.severity = none
 dotnet_diagnostic.S1481.severity = none
 
 
+# S1854: Unused assignments should be removed
+# https://rules.sonarsource.com/csharp/RSPEC-1854
+#
+# This is a duplicate of IDE0059.
+dotnet_diagnostic.S1854.severity = none
+
 # S2259: Null pointers should not be dereferenced
 # S2259: Null pointers should not be dereferenced
 # https://rules.sonarsource.com/csharp/RSPEC-2259
 # https://rules.sonarsource.com/csharp/RSPEC-2259
 #
 #
@@ -168,6 +174,12 @@ dotnet_diagnostic.S3928.severity = none
 # This is a duplicate of CA2002, and partial duplicate of MA0064.
 # This is a duplicate of CA2002, and partial duplicate of MA0064.
 dotnet_diagnostic.S3998.severity = none
 dotnet_diagnostic.S3998.severity = none
 
 
+# S4070: Non-flags enums should not be marked with "FlagsAttribute"
+# https://rules.sonarsource.com/csharp/RSPEC-4070
+#
+# This is a duplicate of MA0062.
+dotnet_diagnostic.S4070.severity = none
+
 # S4456: Parameter validation in yielding methods should be wrapped
 # S4456: Parameter validation in yielding methods should be wrapped
 # https://rules.sonarsource.com/csharp/RSPEC-4456
 # https://rules.sonarsource.com/csharp/RSPEC-4456
 #
 #
@@ -364,6 +376,14 @@ dotnet_diagnostic.MA0018.severity = none
 # No strong need for this, and may negatively affect performance.
 # No strong need for this, and may negatively affect performance.
 dotnet_diagnostic.MA0021.severity = none
 dotnet_diagnostic.MA0021.severity = none
 
 
+# MA0025: Implement the functionality instead of throwing NotImplementedException
+# https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0031.md
+dotnet_diagnostic.MA0025.severity = none
+
+# MA0026: Fix TODO comment
+# https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md
+dotnet_diagnostic.MA0026.severity = suggestion
+
 # MA0031: Optimize Enumerable.Count() usage
 # MA0031: Optimize Enumerable.Count() usage
 # https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0031.md
 # https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0031.md
 #
 #
@@ -436,6 +456,12 @@ dotnet_diagnostic.MA0112.severity = error
 # instead of a base class or interface.
 # instead of a base class or interface.
 dotnet_diagnostic.CA1002.severity = none
 dotnet_diagnostic.CA1002.severity = none
 
 
+# CA1003: Use generic event handler instances
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1003
+#
+# Similar to MA0046.
+dotnet_diagnostic.CA1003.severity = none
+
 # CA1008: Enums should have zero value
 # CA1008: Enums should have zero value
 #
 #
 # TODO: To be discussed. Having a zero value offers a performance advantage.
 # TODO: To be discussed. Having a zero value offers a performance advantage.
@@ -460,6 +486,10 @@ dotnet_diagnostic.CA1051.severity = none
 # By default, this diagnostic is only reported for public types.
 # By default, this diagnostic is only reported for public types.
 dotnet_code_quality.CA1052.api_surface = all
 dotnet_code_quality.CA1052.api_surface = all
 
 
+# CA1065: Do not raise exceptions in unexpected locations
+# https://learn.microsoft.com/en-US/dotnet/fundamentals/code-analysis/quality-rules/ca1065
+dotnet_diagnostic.CA1065.severity = none
+
 # CA1303: Do not pass literals as localized parameters
 # CA1303: Do not pass literals as localized parameters
 #
 #
 # We don't care about localization.
 # We don't care about localization.
@@ -473,6 +503,10 @@ dotnet_diagnostic.CA1303.severity = none
 # Submitted https://github.com/dotnet/roslyn-analyzers/issues/6096 to fix CA1305.
 # Submitted https://github.com/dotnet/roslyn-analyzers/issues/6096 to fix CA1305.
 dotnet_diagnostic.CA1305.severity = none
 dotnet_diagnostic.CA1305.severity = none
 
 
+# CA1309: Use ordinal StringComparison
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1309
+dotnet_diagnostic.CA1309.severity = none
+
 # CA1510: Use ArgumentNullException throw helper
 # CA1510: Use ArgumentNullException throw helper
 #
 #
 # This is only available in .NET 6.0 and higher. We'd need to use conditional compilation to only
 # This is only available in .NET 6.0 and higher. We'd need to use conditional compilation to only
@@ -577,6 +611,22 @@ dotnet_diagnostic.IDE0130.severity = none
 # var inputPath = originalDossierPathList.Find(x => x.id == updatedPath.id) ?? throw new PcsException($"Path id ({updatedPath.id}) unknown in PCS for dossier id {dossierFromTs.dossier.id}", updatedPath.id);
 # var inputPath = originalDossierPathList.Find(x => x.id == updatedPath.id) ?? throw new PcsException($"Path id ({updatedPath.id}) unknown in PCS for dossier id {dossierFromTs.dossier.id}", updatedPath.id);
 dotnet_diagnostic.IDE0270.severity = none
 dotnet_diagnostic.IDE0270.severity = none
 
 
+# IDE0290: Use primary constructor
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0290
+dotnet_diagnostic.IDE0290.severity = none
+
+# IDE0300: Collection initialization can be simplified
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0300
+#
+# TODO: Discuss whether we want to start using this
+dotnet_diagnostic.IDE0300.severity = none
+
+# IDE0301: Simplify collection initialization
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0301
+#
+# TODO: Discuss whether we want to start using this
+dotnet_diagnostic.IDE0301.severity = none
+
 #### .NET Compiler Platform code style rules ####
 #### .NET Compiler Platform code style rules ####
 
 
 ### Language rules ###
 ### Language rules ###

+ 3 - 5
Directory.Build.props

@@ -18,7 +18,7 @@
         Code analysis properties.
         Code analysis properties.
     -->
     -->
     <PropertyGroup>
     <PropertyGroup>
-        <EnableNETAnalyzers>false</EnableNETAnalyzers>
+        <EnableNETAnalyzers>true</EnableNETAnalyzers>
         <AnalysisLevel>preview-All</AnalysisLevel>
         <AnalysisLevel>preview-All</AnalysisLevel>
         <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
         <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
     </PropertyGroup>
     </PropertyGroup>
@@ -34,11 +34,9 @@
         Use fixed version of analyzers.
         Use fixed version of analyzers.
     -->
     -->
     <ItemGroup>
     <ItemGroup>
-        <!--
         <PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0-preview1.23165.1" PrivateAssets="all" />
         <PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0-preview1.23165.1" PrivateAssets="all" />
         <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="all" />
         <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="all" />
-        <PackageReference Include="Meziantou.Analyzer" Version="2.0.54" PrivateAssets="all" />
-        <PackageReference Include="SonarAnalyzer.CSharp" Version="8.55.0.65544" PrivateAssets="all" />
-        -->        
+        <PackageReference Include="Meziantou.Analyzer" Version="2.0.103" PrivateAssets="all" />
+        <PackageReference Include="SonarAnalyzer.CSharp" Version="9.12.0.78982" PrivateAssets="all" />
     </ItemGroup>
     </ItemGroup>
 </Project>
 </Project>

+ 121 - 2
src/Renci.SshNet/.editorconfig

@@ -1,5 +1,38 @@
 [*.cs]
 [*.cs]
 
 
+#### Sonar rules ####
+
+# S1264: A "while" loop should be used instead of a "for" loop
+# https://rules.sonarsource.com/csharp/RSPEC-1264
+dotnet_diagnostic.S1264.severity = none
+
+# S1450: Private fields only used as local variables in methods should become local variables
+# https://rules.sonarsource.com/csharp/RSPEC-1450
+#
+# TODO: Re-enable when the following issue is resolved:
+# https://github.com/SonarSource/sonar-dotnet/issues/8239
+dotnet_diagnostic.S1450.severity = none
+
+# S2372: Exceptions should not be thrown from property getters
+# https://rules.sonarsource.com/csharp/RSPEC-2372/
+dotnet_diagnostic.S2372.severity = none
+
+# S2583: Conditionally executed code should be reachable
+# https://rules.sonarsource.com/csharp/RSPEC-2583/
+#
+# TODO: Re-enable when the following issue is resolved:
+# https://github.com/SonarSource/sonar-dotnet/issues/8264
+dotnet_diagnostic.S2583.severity = none
+
+# S2589: Boolean expressions should not be gratuitous
+# https://rules.sonarsource.com/csharp/RSPEC-2589/
+#
+# TODO: Re-enable when the following issue is resolved:
+# https://github.com/SonarSource/sonar-dotnet/issues/8262
+dotnet_diagnostic.S2589.severity = none
+
+dotnet_diagnostic.S2372.severity = none
+
 #### SYSLIB diagnostics ####
 #### SYSLIB diagnostics ####
 
 
 # SYSLIB1045: Use 'GeneratedRegexAttribute' to generate the regular expression implementation at compile-time
 # SYSLIB1045: Use 'GeneratedRegexAttribute' to generate the regular expression implementation at compile-time
@@ -7,32 +40,114 @@
 # TODO: Remove this when https://github.com/sshnet/SSH.NET/issues/1131 is implemented.
 # TODO: Remove this when https://github.com/sshnet/SSH.NET/issues/1131 is implemented.
 dotnet_diagnostic.SYSLIB1045.severity = none
 dotnet_diagnostic.SYSLIB1045.severity = none
 
 
-### StyleCop Analyzers rules ###
+#### StyleCop Analyzers rules ####
+
+# SA1123: Do not place regions within elements
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1123.md
+dotnet_diagnostic.SA1123.severity = none
+
+# SA1124: Do not use regions
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1124.md
+dotnet_diagnostic.SA1124.severity = none
 
 
 # SA1202: Elements must be ordered by access
 # SA1202: Elements must be ordered by access
 # https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1202.md
 # https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1202.md
 dotnet_diagnostic.SA1202.severity = none
 dotnet_diagnostic.SA1202.severity = none
 
 
+# SA1204: Static elements must appear before instance elements
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1204.md
+dotnet_diagnostic.SA1204.severity = none
+
+# SA1310: Field names must not contain underscore
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1310.md
+#dotnet_diagnostic.SA1310.severity = none
+
+# SA1312: Variable names should begin with lower-case letter
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1312.md
+dotnet_diagnostic.SA1312.severity = none
+
+# SA1636: File header copyright text should match
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1636.md
+dotnet_diagnostic.SA1636.severity = none
+
+# SA1643: Destructor summary documentation must begin with standard text
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1643.md
+dotnet_diagnostic.SA1643.severity = none
+
 #### Meziantou.Analyzer rules ####
 #### Meziantou.Analyzer rules ####
 
 
+# MA0001: StringComparison is missing
+# https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0001.md
+dotnet_diagnostic.MA0001.severity = none
+
+# MA0011: IFormatProvider is missing
+# https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0011.md
+#
+# TODO: Remove exclusion when issues are fixed
+dotnet_diagnostic.MA0011.severity = none
+
+# MA0015: Specify the parameter name in ArgumentException
+# https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0015.md
+#
+# TODO: Remove exclusion when issues are fixed
+dotnet_diagnostic.MA0015.severity = none
+
+# MA0050: Validate arguments correctly in iterator methods
+# https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0050.md
+#
+# TODO: Re-enable when https://github.com/meziantou/Meziantou.Analyzer/issues/617 is fixed
+dotnet_diagnostic.MA0050.severity = none
+
 # MA0053: Make class sealed
 # MA0053: Make class sealed
 # https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0053.md
 # https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0053.md
 MA0053.public_class_should_be_sealed = false
 MA0053.public_class_should_be_sealed = false
 
 
+# MA0055: Do not use finalizer
+# https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0055.md
+#
+# TODO: Remove exclusion when issues are fixed
+dotnet_diagnostic.MA0055.severity = none
+
+# MA0110: Use the Regex source generator
+# https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0110.md
+dotnet_diagnostic.MA0110.severity = none
+
 #### .NET Compiler Platform analysers rules ####
 #### .NET Compiler Platform analysers rules ####
 
 
 # CA1030: Use events where appropriate
 # CA1030: Use events where appropriate
 # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1030
 # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1030
-dotnet_diagnostic.CA10310.severity = none
+dotnet_diagnostic.CA1030.severity = none
 
 
 # CA1031: Do not catch general exception types
 # CA1031: Do not catch general exception types
 # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1031
 # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1031
 dotnet_diagnostic.CA1031.severity = none
 dotnet_diagnostic.CA1031.severity = none
 
 
+# CA1062: Validate arguments of public methods
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1062
+#
+# TODO: Remove exclusion when issues are fixed
+dotnet_diagnostic.CA1062.severity = none
+
+# CA1307: Specify StringComparison for clarity
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1307
+dotnet_diagnostic.CA1307.severity = none
+
+# CA1716: Identifiers should not match keywords
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1716
+dotnet_diagnostic.CA1716.severity = none
+
+# CA1822: Mark members as static
+# https://learn.microsoft.com/en-US/dotnet/fundamentals/code-analysis/quality-rules/ca1822
+dotnet_code_quality.CA1822.api_surface = private,internal
+
 # CA2213: Disposable fields should be disposed
 # CA2213: Disposable fields should be disposed
 # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2213
 # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2213
 dotnet_diagnostic.CA2213.severity = none
 dotnet_diagnostic.CA2213.severity = none
 
 
+# CA3075: Insecure DTD Processing
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca3075
+dotnet_diagnostic.CA3075.severity = none
+
 # IDE0004: Types that own disposable fields should be disposable
 # IDE0004: Types that own disposable fields should be disposable
 # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0004
 # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0004
 dotnet_diagnostic.IDE0004.severity = none
 dotnet_diagnostic.IDE0004.severity = none
@@ -40,3 +155,7 @@ dotnet_diagnostic.IDE0004.severity = none
 # IDE0048: Add parentheses for clarity
 # IDE0048: Add parentheses for clarity
 # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0047
 # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0047
 dotnet_diagnostic.IDE0048.severity = none
 dotnet_diagnostic.IDE0048.severity = none
+
+# IDE0305: Collection initialization can be simplified
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0305
+dotnet_diagnostic.IDE0305.severity = none

+ 0 - 4
src/Renci.SshNet/Abstractions/DiagnosticAbstraction.cs

@@ -22,11 +22,7 @@ namespace Renci.SshNet.Abstractions
         public static void Log(string text)
         public static void Log(string text)
         {
         {
             Loggging.TraceEvent(TraceEventType.Verbose,
             Loggging.TraceEvent(TraceEventType.Verbose,
-#if NET6_0_OR_GREATER
                                 System.Environment.CurrentManagedThreadId,
                                 System.Environment.CurrentManagedThreadId,
-#else
-                                System.Threading.Thread.CurrentThread.ManagedThreadId,
-#endif // NET6_0_OR_GREATER
                                 text);
                                 text);
         }
         }
     }
     }

+ 3 - 3
src/Renci.SshNet/Abstractions/DnsAbstraction.cs

@@ -25,7 +25,7 @@ namespace Renci.SshNet.Abstractions
         /// <summary>
         /// <summary>
         /// Returns the Internet Protocol (IP) addresses for the specified host.
         /// Returns the Internet Protocol (IP) addresses for the specified host.
         /// </summary>
         /// </summary>
-        /// <param name="hostNameOrAddress">The host name or IP address to resolve</param>
+        /// <param name="hostNameOrAddress">The host name or IP address to resolve.</param>
         /// <returns>
         /// <returns>
         /// An array of type <see cref="IPAddress"/> that holds the IP addresses for the host that
         /// An array of type <see cref="IPAddress"/> that holds the IP addresses for the host that
         /// is specified by the <paramref name="hostNameOrAddress"/> parameter.
         /// is specified by the <paramref name="hostNameOrAddress"/> parameter.
@@ -34,7 +34,7 @@ namespace Renci.SshNet.Abstractions
         /// <exception cref="SocketException">An error is encountered when resolving <paramref name="hostNameOrAddress"/>.</exception>
         /// <exception cref="SocketException">An error is encountered when resolving <paramref name="hostNameOrAddress"/>.</exception>
         public static IPAddress[] GetHostAddresses(string hostNameOrAddress)
         public static IPAddress[] GetHostAddresses(string hostNameOrAddress)
         {
         {
-            // TODO Eliminate sync variant, and implement timeout
+            /* TODO Eliminate sync variant, and implement timeout */
 
 
 #if FEATURE_DNS_SYNC
 #if FEATURE_DNS_SYNC
             return Dns.GetHostAddresses(hostNameOrAddress);
             return Dns.GetHostAddresses(hostNameOrAddress);
@@ -92,7 +92,7 @@ namespace Renci.SshNet.Abstractions
         /// <summary>
         /// <summary>
         /// Returns the Internet Protocol (IP) addresses for the specified host.
         /// Returns the Internet Protocol (IP) addresses for the specified host.
         /// </summary>
         /// </summary>
-        /// <param name="hostNameOrAddress">The host name or IP address to resolve</param>
+        /// <param name="hostNameOrAddress">The host name or IP address to resolve.</param>
         /// <returns>
         /// <returns>
         /// A task with result of an array of type <see cref="IPAddress"/> that holds the IP addresses for the host that
         /// A task with result of an array of type <see cref="IPAddress"/> that holds the IP addresses for the host that
         /// is specified by the <paramref name="hostNameOrAddress"/> parameter.
         /// is specified by the <paramref name="hostNameOrAddress"/> parameter.

+ 1 - 1
src/Renci.SshNet/Abstractions/ReflectionAbstraction.cs

@@ -7,7 +7,7 @@ namespace Renci.SshNet.Abstractions
     internal static class ReflectionAbstraction
     internal static class ReflectionAbstraction
     {
     {
         public static IEnumerable<T> GetCustomAttributes<T>(this Type type, bool inherit)
         public static IEnumerable<T> GetCustomAttributes<T>(this Type type, bool inherit)
-            where T:Attribute
+            where T : Attribute
         {
         {
             var attributes = type.GetCustomAttributes(typeof(T), inherit);
             var attributes = type.GetCustomAttributes(typeof(T), inherit);
             return attributes.Cast<T>();
             return attributes.Cast<T>();

+ 6 - 6
src/Renci.SshNet/Abstractions/SocketAbstraction.cs

@@ -261,11 +261,6 @@ namespace Renci.SshNet.Abstractions
             return buffer;
             return buffer;
         }
         }
 
 
-        public static Task<int> ReadAsync(Socket socket, byte[] buffer, int offset, int length, CancellationToken cancellationToken)
-        {
-            return socket.ReceiveAsync(buffer, offset, length, cancellationToken);
-        }
-
         /// <summary>
         /// <summary>
         /// Receives data from a bound <see cref="Socket"/> into a receive buffer.
         /// Receives data from a bound <see cref="Socket"/> into a receive buffer.
         /// </summary>
         /// </summary>
@@ -293,7 +288,7 @@ namespace Renci.SshNet.Abstractions
             var totalBytesRead = 0;
             var totalBytesRead = 0;
             var totalBytesToRead = size;
             var totalBytesToRead = size;
 
 
-            socket.ReceiveTimeout = (int)readTimeout.TotalMilliseconds;
+            socket.ReceiveTimeout = (int) readTimeout.TotalMilliseconds;
 
 
             do
             do
             {
             {
@@ -330,6 +325,11 @@ namespace Renci.SshNet.Abstractions
             return totalBytesRead;
             return totalBytesRead;
         }
         }
 
 
+        public static Task<int> ReadAsync(Socket socket, byte[] buffer, int offset, int length, CancellationToken cancellationToken)
+        {
+            return socket.ReceiveAsync(buffer, offset, length, cancellationToken);
+        }
+
         public static void Send(Socket socket, byte[] data)
         public static void Send(Socket socket, byte[] data)
         {
         {
             Send(socket, data, 0, data.Length);
             Send(socket, data, 0, data.Length);

+ 22 - 9
src/Renci.SshNet/Abstractions/SocketExtensions.cs

@@ -10,24 +10,25 @@ namespace Renci.SshNet.Abstractions
     // Async helpers based on https://devblogs.microsoft.com/pfxteam/awaiting-socket-operations/
     // Async helpers based on https://devblogs.microsoft.com/pfxteam/awaiting-socket-operations/
     internal static class SocketExtensions
     internal static class SocketExtensions
     {
     {
-        private sealed class SocketAsyncEventArgsAwaitable : SocketAsyncEventArgs, INotifyCompletion
+        private sealed class AwaitableSocketAsyncEventArgs : SocketAsyncEventArgs, INotifyCompletion
         {
         {
             private static readonly Action SENTINEL = () => { };
             private static readonly Action SENTINEL = () => { };
 
 
             private bool _isCancelled;
             private bool _isCancelled;
             private Action _continuationAction;
             private Action _continuationAction;
 
 
-            public SocketAsyncEventArgsAwaitable()
+            public AwaitableSocketAsyncEventArgs()
             {
             {
-                Completed += delegate { SetCompleted(); };
+                Completed += (sender, e) => SetCompleted();
             }
             }
 
 
-            public SocketAsyncEventArgsAwaitable ExecuteAsync(Func<SocketAsyncEventArgs, bool> func)
+            public AwaitableSocketAsyncEventArgs ExecuteAsync(Func<SocketAsyncEventArgs, bool> func)
             {
             {
                 if (!func(this))
                 if (!func(this))
                 {
                 {
                     SetCompleted();
                     SetCompleted();
                 }
                 }
+
                 return this;
                 return this;
             }
             }
 
 
@@ -48,7 +49,9 @@ namespace Renci.SshNet.Abstractions
                 SetCompleted();
                 SetCompleted();
             }
             }
 
 
-            public SocketAsyncEventArgsAwaitable GetAwaiter()
+#pragma warning disable S1144 // Unused private types or members should be removed
+            public AwaitableSocketAsyncEventArgs GetAwaiter()
+#pragma warning restore S1144 // Unused private types or members should be removed
             {
             {
                 return this;
                 return this;
             }
             }
@@ -64,7 +67,9 @@ namespace Renci.SshNet.Abstractions
                 }
                 }
             }
             }
 
 
+#pragma warning disable S1144 // Unused private types or members should be removed
             public void GetResult()
             public void GetResult()
+#pragma warning restore S1144 // Unused private types or members should be removed
             {
             {
                 if (_isCancelled)
                 if (_isCancelled)
                 {
                 {
@@ -88,11 +93,15 @@ namespace Renci.SshNet.Abstractions
         {
         {
             cancellationToken.ThrowIfCancellationRequested();
             cancellationToken.ThrowIfCancellationRequested();
 
 
-            using (var args = new SocketAsyncEventArgsAwaitable())
+            using (var args = new AwaitableSocketAsyncEventArgs())
             {
             {
                 args.RemoteEndPoint = remoteEndpoint;
                 args.RemoteEndPoint = remoteEndpoint;
 
 
-                using (cancellationToken.Register(o => ((SocketAsyncEventArgsAwaitable)o).SetCancelled(), args, useSynchronizationContext: false))
+#if NET || NETSTANDARD2_1_OR_GREATER
+                await using (cancellationToken.Register(o => ((AwaitableSocketAsyncEventArgs)o).SetCancelled(), args, useSynchronizationContext: false).ConfigureAwait(continueOnCapturedContext: false))
+#else
+                using (cancellationToken.Register(o => ((AwaitableSocketAsyncEventArgs) o).SetCancelled(), args, useSynchronizationContext: false))
+#endif // NET || NETSTANDARD2_1_OR_GREATER
                 {
                 {
                     await args.ExecuteAsync(socket.ConnectAsync);
                     await args.ExecuteAsync(socket.ConnectAsync);
                 }
                 }
@@ -103,11 +112,15 @@ namespace Renci.SshNet.Abstractions
         {
         {
             cancellationToken.ThrowIfCancellationRequested();
             cancellationToken.ThrowIfCancellationRequested();
 
 
-            using (var args = new SocketAsyncEventArgsAwaitable())
+            using (var args = new AwaitableSocketAsyncEventArgs())
             {
             {
                 args.SetBuffer(buffer, offset, length);
                 args.SetBuffer(buffer, offset, length);
 
 
-                using (cancellationToken.Register(o => ((SocketAsyncEventArgsAwaitable)o).SetCancelled(), args, useSynchronizationContext: false))
+#if NET || NETSTANDARD2_1_OR_GREATER
+                await using (cancellationToken.Register(o => ((AwaitableSocketAsyncEventArgs) o).SetCancelled(), args, useSynchronizationContext: false).ConfigureAwait(continueOnCapturedContext: false))
+#else
+                using (cancellationToken.Register(o => ((AwaitableSocketAsyncEventArgs) o).SetCancelled(), args, useSynchronizationContext: false))
+#endif // NET || NETSTANDARD2_1_OR_GREATER
                 {
                 {
                     await args.ExecuteAsync(socket.ReceiveAsync);
                     await args.ExecuteAsync(socket.ReceiveAsync);
                 }
                 }

+ 17 - 5
src/Renci.SshNet/Abstractions/ThreadAbstraction.cs

@@ -1,4 +1,6 @@
 using System;
 using System;
+using System.Threading;
+using System.Threading.Tasks;
 
 
 namespace Renci.SshNet.Abstractions
 namespace Renci.SshNet.Abstractions
 {
 {
@@ -10,18 +12,28 @@ namespace Renci.SshNet.Abstractions
         /// <param name="millisecondsTimeout">The number of milliseconds for which the thread is suspended.</param>
         /// <param name="millisecondsTimeout">The number of milliseconds for which the thread is suspended.</param>
         public static void Sleep(int millisecondsTimeout)
         public static void Sleep(int millisecondsTimeout)
         {
         {
-            System.Threading.Thread.Sleep(millisecondsTimeout);
+            Thread.Sleep(millisecondsTimeout);
         }
         }
 
 
-        public static void ExecuteThreadLongRunning(Action action)
+        /// <summary>
+        /// Creates and starts a long-running <see cref="Task"/> for the specified <see cref="Action"/>.
+        /// </summary>
+        /// <param name="action">The <see cref="Action"/> to start.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="action"/> is <see langword="null"/>.</exception>
+        /// <returns>
+        /// A task that represents the execution of the specified <see cref="Action"/>.
+        /// </returns>
+        public static Task ExecuteThreadLongRunning(Action action)
         {
         {
             if (action is null)
             if (action is null)
             {
             {
                 throw new ArgumentNullException(nameof(action));
                 throw new ArgumentNullException(nameof(action));
             }
             }
 
 
-            var taskCreationOptions = System.Threading.Tasks.TaskCreationOptions.LongRunning;
-            _ = System.Threading.Tasks.Task.Factory.StartNew(action, taskCreationOptions);
+            return Task.Factory.StartNew(action,
+                                         CancellationToken.None,
+                                         TaskCreationOptions.LongRunning,
+                                         TaskScheduler.Current);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -35,7 +47,7 @@ namespace Renci.SshNet.Abstractions
                 throw new ArgumentNullException(nameof(action));
                 throw new ArgumentNullException(nameof(action));
             }
             }
 
 
-            _ = System.Threading.ThreadPool.QueueUserWorkItem(o => action());
+            _ = ThreadPool.QueueUserWorkItem(o => action());
         }
         }
     }
     }
 }
 }

+ 2 - 0
src/Renci.SshNet/AuthenticationMethod.cs

@@ -13,7 +13,9 @@ namespace Renci.SshNet
         /// <value>
         /// <value>
         /// The name of the authentication method.
         /// The name of the authentication method.
         /// </value>
         /// </value>
+#pragma warning disable CA2119 // Seal methods that satisfy private interfaces
         public abstract string Name { get; }
         public abstract string Name { get; }
+#pragma warning restore CA2119 // Seal methods that satisfy private interfaces
 
 
         /// <summary>
         /// <summary>
         /// Gets connection username.
         /// Gets connection username.

+ 3 - 1
src/Renci.SshNet/AuthenticationResult.cs

@@ -1,7 +1,7 @@
 namespace Renci.SshNet
 namespace Renci.SshNet
 {
 {
     /// <summary>
     /// <summary>
-    /// Represents possible authentication methods results
+    /// Represents possible authentication methods results.
     /// </summary>
     /// </summary>
     public enum AuthenticationResult
     public enum AuthenticationResult
     {
     {
@@ -9,10 +9,12 @@
         /// Authentication was successful.
         /// Authentication was successful.
         /// </summary>
         /// </summary>
         Success,
         Success,
+
         /// <summary>
         /// <summary>
         /// Authentication completed with partial success.
         /// Authentication completed with partial success.
         /// </summary>
         /// </summary>
         PartialSuccess,
         PartialSuccess,
+
         /// <summary>
         /// <summary>
         /// Authentication failed.
         /// Authentication failed.
         /// </summary>
         /// </summary>

+ 11 - 4
src/Renci.SshNet/BaseClient.cs

@@ -12,7 +12,7 @@ namespace Renci.SshNet
     /// <summary>
     /// <summary>
     /// Serves as base class for client implementations, provides common client functionality.
     /// Serves as base class for client implementations, provides common client functionality.
     /// </summary>
     /// </summary>
-    public abstract class BaseClient : IBaseClient, IDisposable
+    public abstract class BaseClient : IBaseClient
     {
     {
         /// <summary>
         /// <summary>
         /// Holds value indicating whether the connection info is owned by this client.
         /// Holds value indicating whether the connection info is owned by this client.
@@ -341,7 +341,9 @@ namespace Renci.SshNet
         /// intervals.
         /// intervals.
         /// </remarks>
         /// </remarks>
         /// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
         /// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
+#pragma warning disable S1133 // Deprecated code should be removed
         [Obsolete("Use KeepAliveInterval to send a keep-alive message at regular intervals.")]
         [Obsolete("Use KeepAliveInterval to send a keep-alive message at regular intervals.")]
+#pragma warning restore S1133 // Deprecated code should be removed
         public void SendKeepAlive()
         public void SendKeepAlive()
         {
         {
             CheckDisposed();
             CheckDisposed();
@@ -393,8 +395,6 @@ namespace Renci.SshNet
         /// </summary>
         /// </summary>
         public void Dispose()
         public void Dispose()
         {
         {
-            DiagnosticAbstraction.Log("Disposing client.");
-
             Dispose(disposing: true);
             Dispose(disposing: true);
             GC.SuppressFinalize(this);
             GC.SuppressFinalize(this);
         }
         }
@@ -412,14 +412,17 @@ namespace Renci.SshNet
 
 
             if (disposing)
             if (disposing)
             {
             {
+                DiagnosticAbstraction.Log("Disposing client.");
+
                 Disconnect();
                 Disconnect();
 
 
-                if (_ownsConnectionInfo && _connectionInfo != null)
+                if (_ownsConnectionInfo && _connectionInfo is not null)
                 {
                 {
                     if (_connectionInfo is IDisposable connectionInfoDisposable)
                     if (_connectionInfo is IDisposable connectionInfoDisposable)
                     {
                     {
                         connectionInfoDisposable.Dispose();
                         connectionInfoDisposable.Dispose();
                     }
                     }
+
                     _connectionInfo = null;
                     _connectionInfo = null;
                 }
                 }
 
 
@@ -433,10 +436,14 @@ namespace Renci.SshNet
         /// <exception cref="ObjectDisposedException">THe current instance is disposed.</exception>
         /// <exception cref="ObjectDisposedException">THe current instance is disposed.</exception>
         protected void CheckDisposed()
         protected void CheckDisposed()
         {
         {
+#if NET7_0_OR_GREATER
+            ObjectDisposedException.ThrowIf(_isDisposed, this);
+#else
             if (_isDisposed)
             if (_isDisposed)
             {
             {
                 throw new ObjectDisposedException(GetType().FullName);
                 throw new ObjectDisposedException(GetType().FullName);
             }
             }
+#endif // NET7_0_OR_GREATER
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 7 - 7
src/Renci.SshNet/Channels/Channel.cs

@@ -16,13 +16,14 @@ namespace Renci.SshNet.Channels
     internal abstract class Channel : IChannel
     internal abstract class Channel : IChannel
     {
     {
         private readonly object _serverWindowSizeLock = new object();
         private readonly object _serverWindowSizeLock = new object();
+        private readonly object _messagingLock = new object();
         private readonly uint _initialWindowSize;
         private readonly uint _initialWindowSize;
+        private readonly ISession _session;
         private EventWaitHandle _channelClosedWaitHandle = new ManualResetEvent(initialState: false);
         private EventWaitHandle _channelClosedWaitHandle = new ManualResetEvent(initialState: false);
         private EventWaitHandle _channelServerWindowAdjustWaitHandle = new ManualResetEvent(initialState: false);
         private EventWaitHandle _channelServerWindowAdjustWaitHandle = new ManualResetEvent(initialState: false);
         private uint? _remoteWindowSize;
         private uint? _remoteWindowSize;
         private uint? _remoteChannelNumber;
         private uint? _remoteChannelNumber;
         private uint? _remotePacketSize;
         private uint? _remotePacketSize;
-        private readonly ISession _session;
         private bool _isDisposed;
         private bool _isDisposed;
 
 
         /// <summary>
         /// <summary>
@@ -497,7 +498,7 @@ namespace Renci.SshNet.Channels
                 throw CreateChannelClosedException();
                 throw CreateChannelClosedException();
             }
             }
 
 
-            lock (this)
+            lock (_messagingLock)
             {
             {
                 _session.SendMessage(new ChannelEofMessage(RemoteChannelNumber));
                 _session.SendMessage(new ChannelEofMessage(RemoteChannelNumber));
                 _eofMessageSent = true;
                 _eofMessageSent = true;
@@ -525,7 +526,7 @@ namespace Renci.SshNet.Channels
              * message causing the server to disconnect the session.
              * message causing the server to disconnect the session.
              */
              */
 
 
-            lock (this)
+            lock (_messagingLock)
             {
             {
                 // Send EOF message first the following conditions are met:
                 // Send EOF message first the following conditions are met:
                 // * we have not sent a SSH_MSG_CHANNEL_EOF message
                 // * we have not sent a SSH_MSG_CHANNEL_EOF message
@@ -704,7 +705,6 @@ namespace Renci.SshNet.Channels
             {
             {
                 try
                 try
                 {
                 {
-
                     if (_session.ConnectionInfo.ChannelRequests.TryGetValue(e.Message.RequestName, out var requestInfo))
                     if (_session.ConnectionInfo.ChannelRequests.TryGetValue(e.Message.RequestName, out var requestInfo))
                     {
                     {
                         // Load request specific data
                         // Load request specific data
@@ -832,7 +832,7 @@ namespace Renci.SshNet.Channels
                 Close();
                 Close();
 
 
                 var session = _session;
                 var session = _session;
-                if (session != null)
+                if (session is not null)
                 {
                 {
                     session.ChannelWindowAdjustReceived -= OnChannelWindowAdjust;
                     session.ChannelWindowAdjustReceived -= OnChannelWindowAdjust;
                     session.ChannelDataReceived -= OnChannelData;
                     session.ChannelDataReceived -= OnChannelData;
@@ -847,14 +847,14 @@ namespace Renci.SshNet.Channels
                 }
                 }
 
 
                 var channelClosedWaitHandle = _channelClosedWaitHandle;
                 var channelClosedWaitHandle = _channelClosedWaitHandle;
-                if (channelClosedWaitHandle != null)
+                if (channelClosedWaitHandle is not null)
                 {
                 {
                     _channelClosedWaitHandle = null;
                     _channelClosedWaitHandle = null;
                     channelClosedWaitHandle.Dispose();
                     channelClosedWaitHandle.Dispose();
                 }
                 }
 
 
                 var channelServerWindowAdjustWaitHandle = _channelServerWindowAdjustWaitHandle;
                 var channelServerWindowAdjustWaitHandle = _channelServerWindowAdjustWaitHandle;
-                if (channelServerWindowAdjustWaitHandle != null)
+                if (channelServerWindowAdjustWaitHandle is not null)
                 {
                 {
                     _channelServerWindowAdjustWaitHandle = null;
                     _channelServerWindowAdjustWaitHandle = null;
                     channelServerWindowAdjustWaitHandle.Dispose();
                     channelServerWindowAdjustWaitHandle.Dispose();

+ 4 - 4
src/Renci.SshNet/Channels/ChannelForwardedTcpip.cs

@@ -17,7 +17,7 @@ namespace Renci.SshNet.Channels
         private IForwardedPort _forwardedPort;
         private IForwardedPort _forwardedPort;
 
 
         /// <summary>
         /// <summary>
-        /// Initializes a new <see cref="ChannelForwardedTcpip"/> instance.
+        /// Initializes a new instance of the <see cref="ChannelForwardedTcpip"/> class.
         /// </summary>
         /// </summary>
         /// <param name="session">The session.</param>
         /// <param name="session">The session.</param>
         /// <param name="localChannelNumber">The local channel number.</param>
         /// <param name="localChannelNumber">The local channel number.</param>
@@ -69,17 +69,17 @@ namespace Renci.SshNet.Channels
             _forwardedPort = forwardedPort;
             _forwardedPort = forwardedPort;
             _forwardedPort.Closing += ForwardedPort_Closing;
             _forwardedPort.Closing += ForwardedPort_Closing;
 
 
-            //  Try to connect to the socket 
+            // Try to connect to the socket
             try
             try
             {
             {
                 _socket = SocketAbstraction.Connect(remoteEndpoint, ConnectionInfo.Timeout);
                 _socket = SocketAbstraction.Connect(remoteEndpoint, ConnectionInfo.Timeout);
 
 
-                // send channel open confirmation message
+                // Send channel open confirmation message
                 SendMessage(new ChannelOpenConfirmationMessage(RemoteChannelNumber, LocalWindowSize, LocalPacketSize, LocalChannelNumber));
                 SendMessage(new ChannelOpenConfirmationMessage(RemoteChannelNumber, LocalWindowSize, LocalPacketSize, LocalChannelNumber));
             }
             }
             catch (Exception exp)
             catch (Exception exp)
             {
             {
-                // send channel open failure message
+                // Send channel open failure message
                 SendMessage(new ChannelOpenFailureMessage(RemoteChannelNumber, exp.ToString(), ChannelOpenFailureMessage.ConnectFailed, "en"));
                 SendMessage(new ChannelOpenFailureMessage(RemoteChannelNumber, exp.ToString(), ChannelOpenFailureMessage.ConnectFailed, "en"));
 
 
                 throw;
                 throw;

+ 1 - 1
src/Renci.SshNet/Channels/ChannelSession.cs

@@ -394,7 +394,7 @@ namespace Renci.SshNet.Channels
         /// </remarks>
         /// </remarks>
         private void SendChannelOpenMessage()
         private void SendChannelOpenMessage()
         {
         {
-            // do not allow open to be ChannelOpenMessage to be sent again until we've
+            // do not allow the ChannelOpenMessage to be sent again until we've
             // had a response on the previous attempt for the current channel
             // had a response on the previous attempt for the current channel
             if (Interlocked.CompareExchange(ref _sessionSemaphoreObtained, 1, 0) == 0)
             if (Interlocked.CompareExchange(ref _sessionSemaphoreObtained, 1, 0) == 0)
             {
             {

+ 8 - 6
src/Renci.SshNet/Channels/ChannelTypes.cs

@@ -1,5 +1,4 @@
-
-namespace Renci.SshNet.Channels
+namespace Renci.SshNet.Channels
 {
 {
     /// <summary>
     /// <summary>
     /// Lists channel types as defined by the protocol.
     /// Lists channel types as defined by the protocol.
@@ -7,19 +6,22 @@ namespace Renci.SshNet.Channels
     internal enum ChannelTypes
     internal enum ChannelTypes
     {
     {
         /// <summary>
         /// <summary>
-        /// session
+        /// Session.
         /// </summary>
         /// </summary>
         Session,
         Session,
+
         /// <summary>
         /// <summary>
-        /// x11
+        /// X11.
         /// </summary>
         /// </summary>
         X11,
         X11,
+
         /// <summary>
         /// <summary>
-        /// forwarded-tcpip
+        /// Forwarded-tcpip.
         /// </summary>
         /// </summary>
         ForwardedTcpip,
         ForwardedTcpip,
+
         /// <summary>
         /// <summary>
-        /// direct-tcpip
+        /// Direct-tcpip.
         /// </summary>
         /// </summary>
         DirectTcpip
         DirectTcpip
     }
     }

+ 1 - 1
src/Renci.SshNet/Channels/ClientChannel.cs

@@ -49,7 +49,7 @@ namespace Renci.SshNet.Channels
         /// <summary>
         /// <summary>
         /// Send message to open a channel.
         /// Send message to open a channel.
         /// </summary>
         /// </summary>
-        /// <param name="message">Message to send</param>
+        /// <param name="message">Message to send.</param>
         /// <exception cref="SshConnectionException">The client is not connected.</exception>
         /// <exception cref="SshConnectionException">The client is not connected.</exception>
         /// <exception cref="SshOperationTimeoutException">The operation timed out.</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>
         /// <exception cref="InvalidOperationException">The size of the packet exceeds the maximum size defined by the protocol.</exception>

+ 6 - 2
src/Renci.SshNet/Channels/IChannelSession.cs

@@ -25,8 +25,12 @@ namespace Renci.SshNet.Channels
         /// <returns>
         /// <returns>
         /// <see langword="true"/> if request was successful; otherwise <see langword="false"/>.
         /// <see langword="true"/> if request was successful; otherwise <see langword="false"/>.
         /// </returns>
         /// </returns>
-        bool SendPseudoTerminalRequest(string environmentVariable, uint columns, uint rows, uint width, uint height,
-            IDictionary<TerminalModes, uint> terminalModeValues);
+        bool SendPseudoTerminalRequest(string environmentVariable,
+                                       uint columns,
+                                       uint rows,
+                                       uint width,
+                                       uint height,
+                                       IDictionary<TerminalModes, uint> terminalModeValues);
 
 
         /// <summary>
         /// <summary>
         /// Sends the X11 forwarding request.
         /// Sends the X11 forwarding request.

+ 1 - 1
src/Renci.SshNet/CipherInfo.cs

@@ -5,7 +5,7 @@ using Renci.SshNet.Security.Cryptography;
 namespace Renci.SshNet
 namespace Renci.SshNet
 {
 {
     /// <summary>
     /// <summary>
-    /// Holds information about key size and cipher to use
+    /// Holds information about key size and cipher to use.
     /// </summary>
     /// </summary>
     public class CipherInfo
     public class CipherInfo
     {
     {

+ 20 - 6
src/Renci.SshNet/ClientAuthentication.cs

@@ -1,9 +1,14 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.Globalization;
+
 using Renci.SshNet.Common;
 using Renci.SshNet.Common;
 
 
 namespace Renci.SshNet
 namespace Renci.SshNet
 {
 {
+    /// <summary>
+    /// Represents a mechanism to authenticate a given client.
+    /// </summary>
     internal sealed class ClientAuthentication : IClientAuthentication
     internal sealed class ClientAuthentication : IClientAuthentication
     {
     {
         private readonly int _partialSuccessLimit;
         private readonly int _partialSuccessLimit;
@@ -37,11 +42,14 @@ namespace Renci.SshNet
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Attempts to authentication for a given <see cref="ISession"/> using the <see cref="IConnectionInfoInternal.AuthenticationMethods"/>
-        /// of the specified <see cref="IConnectionInfoInternal"/>.
+        /// Attempts to perform authentication for a given <see cref="ISession"/> using the
+        /// <see cref="IConnectionInfoInternal.AuthenticationMethods"/> of the specified
+        /// <see cref="IConnectionInfoInternal"/>.
         /// </summary>
         /// </summary>
         /// <param name="connectionInfo">A <see cref="IConnectionInfoInternal"/> to use for authenticating.</param>
         /// <param name="connectionInfo">A <see cref="IConnectionInfoInternal"/> to use for authenticating.</param>
         /// <param name="session">The <see cref="ISession"/> for which to perform authentication.</param>
         /// <param name="session">The <see cref="ISession"/> for which to perform authentication.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="connectionInfo"/> or <paramref name="session"/> is <see langword="null"/>.</exception>
+        /// <exception cref="SshAuthenticationException">Failed to authenticate the client.</exception>
         public void Authenticate(IConnectionInfoInternal connectionInfo, ISession session)
         public void Authenticate(IConnectionInfoInternal connectionInfo, ISession session)
         {
         {
             if (connectionInfo is null)
             if (connectionInfo is null)
@@ -102,8 +110,14 @@ namespace Renci.SshNet
             var matchingAuthenticationMethods = authenticationState.GetSupportedAuthenticationMethods(allowedAuthenticationMethods);
             var matchingAuthenticationMethods = authenticationState.GetSupportedAuthenticationMethods(allowedAuthenticationMethods);
             if (matchingAuthenticationMethods.Count == 0)
             if (matchingAuthenticationMethods.Count == 0)
             {
             {
-                authenticationException = new SshAuthenticationException(string.Format("No suitable authentication method found to complete authentication ({0}).",
-                                                                                       string.Join(",", allowedAuthenticationMethods)));
+                authenticationException = new SshAuthenticationException(string.Format(CultureInfo.InvariantCulture,
+                                                                                       "No suitable authentication method found to complete authentication ({0}).",
+#if NET || NETSTANDARD2_1_OR_GREATER
+                                                                                       string.Join(',', allowedAuthenticationMethods)))
+#else
+                                                                                       string.Join(",", allowedAuthenticationMethods)))
+#endif // NET || NETSTANDARD2_1_OR_GREATER
+                ;
                 return false;
                 return false;
             }
             }
 
 
@@ -113,7 +127,7 @@ namespace Renci.SshNet
                 // methods after a partial success
                 // methods after a partial success
                 if (authenticationState.GetPartialSuccessCount(authenticationMethod) >= _partialSuccessLimit)
                 if (authenticationState.GetPartialSuccessCount(authenticationMethod) >= _partialSuccessLimit)
                 {
                 {
-                    // TODO Get list of all authentication methods that have reached the partial success limit?
+                    /* TODO Get list of all authentication methods that have reached the partial success limit? */
 
 
                     authenticationException = new SshAuthenticationException(string.Format("Reached authentication attempt limit for method ({0}).",
                     authenticationException = new SshAuthenticationException(string.Format("Reached authentication attempt limit for method ({0}).",
                                                                                            authenticationMethod.Name));
                                                                                            authenticationMethod.Name));
@@ -195,7 +209,7 @@ namespace Renci.SshNet
             {
             {
                 if (_authenticationMethodPartialSuccessRegister.TryGetValue(authenticationMethod, out var partialSuccessCount))
                 if (_authenticationMethodPartialSuccessRegister.TryGetValue(authenticationMethod, out var partialSuccessCount))
                 {
                 {
-                    _authenticationMethodPartialSuccessRegister[authenticationMethod] = ++partialSuccessCount;
+                    _authenticationMethodPartialSuccessRegister[authenticationMethod] = partialSuccessCount + 1;
                 }
                 }
                 else
                 else
                 {
                 {

+ 0 - 46
src/Renci.SshNet/Common/AsyncResult.cs

@@ -155,50 +155,4 @@ namespace Renci.SshNet.Common
             get { return _completedState != StatePending; }
             get { return _completedState != StatePending; }
         }
         }
     }
     }
-
-    /// <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{TResult}"/> 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 <see langword="true"/> [completed synchronously].</param>
-        public void SetAsCompleted(TResult result, bool completedSynchronously)
-        {
-            // Save the asynchronous operation's result
-            _result = result;
-
-            // Tell the base class that the operation completed successfully (no exception)
-            SetAsCompleted(exception: null, completedSynchronously);
-        }
-
-        /// <summary>
-        /// Waits until the asynchronous operation completes, and then returns the value generated by the asynchronous operation. 
-        /// </summary>
-        /// <returns>
-        /// The invocation result.
-        /// </returns>
-        public new TResult EndInvoke()
-        {
-            base.EndInvoke(); // Wait until operation has completed
-            return _result;  // Return the result (if above didn't throw)
-        }
-    }
 }
 }

+ 50 - 0
src/Renci.SshNet/Common/AsyncResult{TResult}.cs

@@ -0,0 +1,50 @@
+using System;
+
+namespace Renci.SshNet.Common
+{
+    /// <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{TResult}"/> 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 <see langword="true"/> [completed synchronously].</param>
+        public void SetAsCompleted(TResult result, bool completedSynchronously)
+        {
+            // Save the asynchronous operation's result
+            _result = result;
+
+            // Tell the base class that the operation completed successfully (no exception)
+            SetAsCompleted(exception: null, completedSynchronously);
+        }
+
+        /// <summary>
+        /// Waits until the asynchronous operation completes, and then returns the value generated by the asynchronous operation.
+        /// </summary>
+        /// <returns>
+        /// The invocation result.
+        /// </returns>
+        public new TResult EndInvoke()
+        {
+            base.EndInvoke(); // Wait until operation has completed
+            return _result;  // Return the result (if above didn't throw)
+        }
+    }
+}

+ 134 - 41
src/Renci.SshNet/Common/BigInteger.cs

@@ -1,4 +1,6 @@
-//
+#pragma warning disable SA1028 // Code should not contain trailing whitespace
+#pragma warning disable SA1515 // Single-line comment should be preceded by blank line
+//
 // System.Numerics.BigInteger
 // System.Numerics.BigInteger
 //
 //
 // Authors:
 // Authors:
@@ -44,6 +46,8 @@
 *
 *
 *
 *
 * ***************************************************************************/
 * ***************************************************************************/
+#pragma warning restore SA1515 // Single-line comment should be preceded by blank line
+#pragma warning restore SA1028 // Code should not contain trailing whitespace
 
 
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
@@ -106,7 +110,7 @@ namespace Renci.SshNet.Common
 
 
                 var msbBitCount = BitScanBackward(_data[msbIndex]) + 1;
                 var msbBitCount = BitScanBackward(_data[msbIndex]) + 1;
 
 
-                return msbIndex * 4 * 8 + msbBitCount + ((_sign > 0) ? 0 : 1);
+                return (msbIndex * 4 * 8) + msbBitCount + ((_sign > 0) ? 0 : 1);
             }
             }
         }
         }
 
 
@@ -145,8 +149,8 @@ namespace Renci.SshNet.Common
 
 
                 p1 += (b / a) * p0;
                 p1 += (b / a) * p0;
                 b %= a;
                 b %= a;
-
             }
             }
+
             return 0;
             return 0;
         }
         }
 
 
@@ -210,7 +214,9 @@ namespace Renci.SshNet.Common
             else
             else
             {
             {
                 _sign = -1;
                 _sign = -1;
+#pragma warning disable SA1021 // Negative signs should be spaced correctly
                 _data = new[] { (uint) -value };
                 _data = new[] { (uint) -value };
+#pragma warning restore SA1021 // Negative signs should be spaced correctly
             }
             }
         }
         }
 
 
@@ -419,7 +425,9 @@ namespace Renci.SshNet.Common
                 _sign = 1;
                 _sign = 1;
             }
             }
 
 
+#pragma warning disable CA1508 // Avoid dead conditional code | this is the following bug in the analyzer rule: https://github.com/dotnet/roslyn-analyzers/issues/6991
             if (_sign == 1)
             if (_sign == 1)
+#pragma warning restore CA1508 // Avoid dead conditional code
             {
             {
                 while (value[len - 1] == 0)
                 while (value[len - 1] == 0)
                 {
                 {
@@ -514,8 +522,9 @@ namespace Renci.SshNet.Common
 
 
                 if (borrow != 0)
                 if (borrow != 0)
                 {
                 {
-                    // FIXME I believe this can't happen, can someone write a test for it?
+#pragma warning disable CA2201 // Do not raise reserved exception types
                     throw new Exception("non zero final carry");
                     throw new Exception("non zero final carry");
+#pragma warning restore CA2201 // Do not raise reserved exception types
                 }
                 }
             }
             }
         }
         }
@@ -535,14 +544,14 @@ namespace Renci.SshNet.Common
             var i1 = (uint)v[0] | ((uint)v[1] << 8) | ((uint)v[2] << 16) | ((uint)v[3] << 24);
             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);
             var i2 = (uint)v[4] | ((uint)v[5] << 8) | ((uint)(v[6] & 0xF) << 16);
 
 
-            return ((ulong) i1 | ((ulong) i2 << 32));
+            return (ulong) i1 | ((ulong) i2 << 32);
         }
         }
 
 
         /// <summary>
         /// <summary>
         /// Gets a value indicating whether the value of the current <see cref="BigInteger"/> object is an even number.
         /// Gets a value indicating whether the value of the current <see cref="BigInteger"/> object is an even number.
         /// </summary>
         /// </summary>
         /// <value>
         /// <value>
-        /// <see langword="true"/> if the value of the BigInteger object is an even number; otherwise, <see langword="false"/>.
+        /// <see langword="true"/> if the value of the <see cref="BigInteger"/> object is an even number; otherwise, <see langword="false"/>.
         /// </value>
         /// </value>
         public readonly bool IsEven
         public readonly bool IsEven
         {
         {
@@ -768,7 +777,9 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static explicit operator int(BigInteger value)
         public static explicit operator int(BigInteger value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             if (value._data is null)
             if (value._data is null)
             {
             {
@@ -813,7 +824,9 @@ namespace Renci.SshNet.Common
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
         [CLSCompliant(false)]
         [CLSCompliant(false)]
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static explicit operator uint(BigInteger value)
         public static explicit operator uint(BigInteger value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             if (value._data is null)
             if (value._data is null)
             {
             {
@@ -835,7 +848,9 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static explicit operator short(BigInteger value)
         public static explicit operator short(BigInteger value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             var val = (int) value;
             var val = (int) value;
             if (val is < short.MinValue or > short.MaxValue)
             if (val is < short.MinValue or > short.MaxValue)
@@ -854,7 +869,9 @@ namespace Renci.SshNet.Common
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
         [CLSCompliant(false)]
         [CLSCompliant(false)]
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static explicit operator ushort(BigInteger value)
         public static explicit operator ushort(BigInteger value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             var val = (uint) value;
             var val = (uint) value;
             if (val > ushort.MaxValue)
             if (val > ushort.MaxValue)
@@ -872,7 +889,9 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static explicit operator byte(BigInteger value)
         public static explicit operator byte(BigInteger value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             var val = (uint) value;
             var val = (uint) value;
             if (val > byte.MaxValue)
             if (val > byte.MaxValue)
@@ -891,7 +910,9 @@ namespace Renci.SshNet.Common
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
         [CLSCompliant(false)]
         [CLSCompliant(false)]
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static explicit operator sbyte(BigInteger value)
         public static explicit operator sbyte(BigInteger value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             var val = (int) value;
             var val = (int) value;
             if (val is < sbyte.MinValue or > sbyte.MaxValue)
             if (val is < sbyte.MinValue or > sbyte.MaxValue)
@@ -909,7 +930,9 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static explicit operator long(BigInteger value)
         public static explicit operator long(BigInteger value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             if (value._data is null)
             if (value._data is null)
             {
             {
@@ -973,7 +996,9 @@ namespace Renci.SshNet.Common
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
         [CLSCompliant(false)]
         [CLSCompliant(false)]
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static explicit operator ulong(BigInteger value)
         public static explicit operator ulong(BigInteger value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             if (value._data is null)
             if (value._data is null)
             {
             {
@@ -1002,7 +1027,9 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static explicit operator double(BigInteger value)
         public static explicit operator double(BigInteger value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             if (value._data is null)
             if (value._data is null)
             {
             {
@@ -1041,7 +1068,9 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static explicit operator float(BigInteger value)
         public static explicit operator float(BigInteger value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             return (float) (double) value;
             return (float) (double) value;
         }
         }
@@ -1053,7 +1082,9 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static explicit operator decimal(BigInteger value)
         public static explicit operator decimal(BigInteger value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             if (value._data is null)
             if (value._data is null)
             {
             {
@@ -1092,7 +1123,9 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static implicit operator BigInteger(int value)
         public static implicit operator BigInteger(int value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             return new BigInteger(value);
             return new BigInteger(value);
         }
         }
@@ -1105,7 +1138,9 @@ namespace Renci.SshNet.Common
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
         [CLSCompliant(false)]
         [CLSCompliant(false)]
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static implicit operator BigInteger(uint value)
         public static implicit operator BigInteger(uint value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             return new BigInteger(value);
             return new BigInteger(value);
         }
         }
@@ -1117,7 +1152,9 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static implicit operator BigInteger(short value)
         public static implicit operator BigInteger(short value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             return new BigInteger(value);
             return new BigInteger(value);
         }
         }
@@ -1130,7 +1167,9 @@ namespace Renci.SshNet.Common
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
         [CLSCompliant(false)]
         [CLSCompliant(false)]
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static implicit operator BigInteger(ushort value)
         public static implicit operator BigInteger(ushort value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             return new BigInteger(value);
             return new BigInteger(value);
         }
         }
@@ -1142,20 +1181,24 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static implicit operator BigInteger(byte value)
         public static implicit operator BigInteger(byte value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             return new BigInteger(value);
             return new BigInteger(value);
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// 
+        /// Defines an implicit conversion of a signed byte to a <see cref="BigInteger"/> value.
         /// </summary>
         /// </summary>
         /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
         /// <param name="value">The value to convert to a <see cref="BigInteger"/>.</param>
         /// <returns>
         /// <returns>
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
         [CLSCompliant(false)]
         [CLSCompliant(false)]
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static implicit operator BigInteger(sbyte value)
         public static implicit operator BigInteger(sbyte value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             return new BigInteger(value);
             return new BigInteger(value);
         }
         }
@@ -1167,7 +1210,9 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static implicit operator BigInteger(long value)
         public static implicit operator BigInteger(long value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             return new BigInteger(value);
             return new BigInteger(value);
         }
         }
@@ -1180,7 +1225,9 @@ namespace Renci.SshNet.Common
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
         [CLSCompliant(false)]
         [CLSCompliant(false)]
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static implicit operator BigInteger(ulong value)
         public static implicit operator BigInteger(ulong value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             return new BigInteger(value);
             return new BigInteger(value);
         }
         }
@@ -1192,7 +1239,9 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static explicit operator BigInteger(double value)
         public static explicit operator BigInteger(double value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             return new BigInteger(value);
             return new BigInteger(value);
         }
         }
@@ -1204,7 +1253,9 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static explicit operator BigInteger(float value)
         public static explicit operator BigInteger(float value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             return new BigInteger(value);
             return new BigInteger(value);
         }
         }
@@ -1216,7 +1267,9 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// An object that contains the value of the <paramref name="value"/> parameter.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static explicit operator BigInteger(decimal value)
         public static explicit operator BigInteger(decimal value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             return new BigInteger(value);
             return new BigInteger(value);
         }
         }
@@ -1255,7 +1308,7 @@ namespace Renci.SshNet.Common
 
 
             if (r > 0)
             if (r > 0)
             {
             {
-                //left > right
+                // left > right
                 return new BigInteger(left._sign, CoreSub(left._data, right._data));
                 return new BigInteger(left._sign, CoreSub(left._data, right._data));
             }
             }
 
 
@@ -1279,7 +1332,9 @@ namespace Renci.SshNet.Common
 
 
             if (left._sign == 0)
             if (left._sign == 0)
             {
             {
+#pragma warning disable SA1021 // Negative signs should be spaced correctly
                 return new BigInteger((short) -right._sign, right._data);
                 return new BigInteger((short) -right._sign, right._data);
+#pragma warning restore SA1021 // Negative signs should be spaced correctly
             }
             }
 
 
             if (left._sign == right._sign)
             if (left._sign == right._sign)
@@ -1351,7 +1406,7 @@ namespace Renci.SshNet.Common
                 ulong carry = 0;
                 ulong carry = 0;
                 for (var j = 0; j < b.Length; ++j)
                 for (var j = 0; j < b.Length; ++j)
                 {
                 {
-                    carry = carry + ((ulong) ai) * b[j] + res[k];
+                    carry = carry + (((ulong) ai) * b[j]) + res[k];
                     res[k++] = (uint)carry;
                     res[k++] = (uint)carry;
                     carry >>= 32;
                     carry >>= 32;
                 }
                 }
@@ -1475,7 +1530,9 @@ namespace Renci.SshNet.Common
                 return value;
                 return value;
             }
             }
 
 
+#pragma warning disable SA1021 // Negative signs should be spaced correctly
             return new BigInteger((short) -value._sign, value._data);
             return new BigInteger((short) -value._sign, value._data);
+#pragma warning restore SA1021 // Negative signs should be spaced correctly
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1488,7 +1545,9 @@ namespace Renci.SshNet.Common
         /// <remarks>
         /// <remarks>
         /// The sign of the operand is unchanged.
         /// The sign of the operand is unchanged.
         /// </remarks>
         /// </remarks>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static BigInteger operator +(BigInteger value)
         public static BigInteger operator +(BigInteger value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             return value;
             return value;
         }
         }
@@ -1500,7 +1559,9 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// The value of the <paramref name="value"/> parameter incremented by 1.
         /// The value of the <paramref name="value"/> parameter incremented by 1.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static BigInteger operator ++(BigInteger value)
         public static BigInteger operator ++(BigInteger value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             if (value._data is null)
             if (value._data is null)
             {
             {
@@ -1534,7 +1595,9 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// The value of the <paramref name="value"/> parameter decremented by 1.
         /// The value of the <paramref name="value"/> parameter decremented by 1.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static BigInteger operator --(BigInteger value)
         public static BigInteger operator --(BigInteger value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             if (value._data is null)
             if (value._data is null)
             {
             {
@@ -1569,7 +1632,9 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// The result of the bitwise <c>And</c> operation.
         /// The result of the bitwise <c>And</c> operation.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static BigInteger operator &(BigInteger left, BigInteger right)
         public static BigInteger operator &(BigInteger left, BigInteger right)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             if (left._sign == 0)
             if (left._sign == 0)
             {
             {
@@ -1659,7 +1724,9 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// The result of the bitwise <c>Or</c> operation.
         /// The result of the bitwise <c>Or</c> operation.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static BigInteger operator |(BigInteger left, BigInteger right)
         public static BigInteger operator |(BigInteger left, BigInteger right)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             if (left._sign == 0)
             if (left._sign == 0)
             {
             {
@@ -1749,7 +1816,9 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// The result of the bitwise <c>Or</c> operation.
         /// The result of the bitwise <c>Or</c> operation.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static BigInteger operator ^(BigInteger left, BigInteger right)
         public static BigInteger operator ^(BigInteger left, BigInteger right)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             if (left._sign == 0)
             if (left._sign == 0)
             {
             {
@@ -1838,7 +1907,9 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// The bitwise one's complement of <paramref name="value"/>.
         /// The bitwise one's complement of <paramref name="value"/>.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static BigInteger operator ~(BigInteger value)
         public static BigInteger operator ~(BigInteger value)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             if (value._data is null)
             if (value._data is null)
             {
             {
@@ -1895,9 +1966,14 @@ namespace Renci.SshNet.Common
             return new BigInteger(negRes ? (short)-1 : (short)1, result);
             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)
+        /// <summary>
+        /// Returns the zero-based index of the most significant set bit.
+        /// </summary>
+        /// <param name="word">The value to scan.</param>
+        /// <returns>
+        /// The zero-based index of the most significant set bit, or zero if no bit is set.
+        /// </returns>
+        private static int BitScanBackward(uint word)
         {
         {
             for (var i = 31; i >= 0; --i)
             for (var i = 31; i >= 0; --i)
             {
             {
@@ -1919,7 +1995,9 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// A value that has been shifted to the left by the specified number of bits.
         /// A value that has been shifted to the left by the specified number of bits.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static BigInteger operator <<(BigInteger value, int shift)
         public static BigInteger operator <<(BigInteger value, int shift)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             if (shift == 0 || value._data is null)
             if (shift == 0 || value._data is null)
             {
             {
@@ -1976,7 +2054,9 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// A value that has been shifted to the right by the specified number of bits.
         /// A value that has been shifted to the right by the specified number of bits.
         /// </returns>
         /// </returns>
+#pragma warning disable CA2225 // Operator overloads have named alternates
         public static BigInteger operator >>(BigInteger value, int shift)
         public static BigInteger operator >>(BigInteger value, int shift)
+#pragma warning restore CA2225 // Operator overloads have named alternates
         {
         {
             if (shift == 0 || value._sign == 0)
             if (shift == 0 || value._sign == 0)
             {
             {
@@ -2092,7 +2172,6 @@ namespace Renci.SshNet.Common
             return left.CompareTo(right) < 0;
             return left.CompareTo(right) < 0;
         }
         }
 
 
-
         /// <summary>
         /// <summary>
         /// Returns a value that indicates whether a 64-bit signed integer is less than a <see cref="BigInteger"/> value.
         /// Returns a value that indicates whether a 64-bit signed integer is less than a <see cref="BigInteger"/> value.
         /// </summary>
         /// </summary>
@@ -2672,7 +2751,11 @@ namespace Renci.SshNet.Common
                         return additional + baseStr;
                         return additional + baseStr;
                     }
                     }
 
 
+#if NET
+                    return string.Concat("-", additional, baseStr.AsSpan(1));
+#else
                     return "-" + additional + baseStr.Substring(1);
                     return "-" + additional + baseStr.Substring(1);
+#endif // NET
                 }
                 }
 
 
                 return baseStr;
                 return baseStr;
@@ -2689,9 +2772,9 @@ namespace Renci.SshNet.Common
             for (var i = 0; i < v.Length; ++i)
             for (var i = 0; i < v.Length; ++i)
             {
             {
                 var word = v[i];
                 var word = v[i];
-                carry = (ulong)~word + carry;
-                word = (uint)carry;
-                carry = (uint)(carry >> 32);
+                carry = (ulong) ~word + carry;
+                word = (uint) carry;
+                carry = (uint) (carry >> 32);
                 res[i] = word;
                 res[i] = word;
             }
             }
 
 
@@ -2713,7 +2796,7 @@ namespace Renci.SshNet.Common
 
 
             if (characterSet.Length < radix)
             if (characterSet.Length < radix)
             {
             {
-                throw new ArgumentException("charSet length less than radix", "characterSet");
+                throw new ArgumentException("charSet length less than radix", nameof(radix));
             }
             }
 
 
             if (radix == 1)
             if (radix == 1)
@@ -2731,7 +2814,7 @@ namespace Renci.SshNet.Common
                 return _sign == 1 ? "1" : "-1";
                 return _sign == 1 ? "1" : "-1";
             }
             }
 
 
-            var digits = new List<char>(1 + _data.Length * 3 / 10);
+            var digits = new List<char>(1 + ((_data.Length * 3) / 10));
 
 
             BigInteger a;
             BigInteger a;
             if (_sign == 1)
             if (_sign == 1)
@@ -2910,7 +2993,9 @@ namespace Renci.SshNet.Common
             return true;
             return true;
         }
         }
 
 
+#pragma warning disable S4136 // Method overloads should be grouped together
         private static bool Parse(string value, NumberStyles style, IFormatProvider fp, bool tryParse, out BigInteger result, out Exception exc)
         private static bool Parse(string value, NumberStyles style, IFormatProvider fp, bool tryParse, out BigInteger result, out Exception exc)
+#pragma warning restore S4136 // Method overloads should be grouped together
         {
         {
             result = Zero;
             result = Zero;
             exc = null;
             exc = null;
@@ -2949,16 +3034,16 @@ namespace Renci.SshNet.Common
                 return false;
                 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 allowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) == NumberStyles.AllowCurrencySymbol;
+            var allowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) == NumberStyles.AllowHexSpecifier;
+            var allowThousands = (style & NumberStyles.AllowThousands) == NumberStyles.AllowThousands;
+            var allowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) == NumberStyles.AllowDecimalPoint;
+            var allowParentheses = (style & NumberStyles.AllowParentheses) == NumberStyles.AllowParentheses;
+            var allowTrailingSign = (style & NumberStyles.AllowTrailingSign) == NumberStyles.AllowTrailingSign;
+            var allowLeadingSign = (style & NumberStyles.AllowLeadingSign) == NumberStyles.AllowLeadingSign;
+            var allowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) == NumberStyles.AllowTrailingWhite;
+            var allowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) == NumberStyles.AllowLeadingWhite;
+            var allowExponent = (style & NumberStyles.AllowExponent) == NumberStyles.AllowExponent;
 
 
             var pos = 0;
             var pos = 0;
 
 
@@ -3223,7 +3308,11 @@ namespace Renci.SshNet.Common
                 {
                 {
                     if (!tryParse)
                     if (!tryParse)
                     {
                     {
-                        exc = new OverflowException("Value too large or too small. exp=" + exponent + " rem = " + remainder + " pow = " + Pow(10, -exponent));
+                        exc = new OverflowException(string.Format(CultureInfo.InvariantCulture,
+                                                                  "Value too large or too small. exp= {0} rem = {1} pow = {2}",
+                                                                  exponent,
+                                                                  remainder,
+                                                                  Pow(10, -exponent)));
                     }
                     }
 
 
                     return false;
                     return false;
@@ -3252,20 +3341,20 @@ namespace Renci.SshNet.Common
 
 
         private static bool CheckStyle(NumberStyles style, bool tryParse, ref Exception exc)
         private static bool CheckStyle(NumberStyles style, bool tryParse, ref Exception exc)
         {
         {
-            if ((style & NumberStyles.AllowHexSpecifier) != 0)
+            if ((style & NumberStyles.AllowHexSpecifier) == NumberStyles.AllowHexSpecifier)
             {
             {
                 var ne = style ^ NumberStyles.AllowHexSpecifier;
                 var ne = style ^ NumberStyles.AllowHexSpecifier;
-                if ((ne & NumberStyles.AllowLeadingWhite) != 0)
+                if ((ne & NumberStyles.AllowLeadingWhite) == NumberStyles.AllowLeadingWhite)
                 {
                 {
                     ne ^= NumberStyles.AllowLeadingWhite;
                     ne ^= NumberStyles.AllowLeadingWhite;
                 }
                 }
 
 
-                if ((ne & NumberStyles.AllowTrailingWhite) != 0)
+                if ((ne & NumberStyles.AllowTrailingWhite) == NumberStyles.AllowTrailingWhite)
                 {
                 {
                     ne ^= NumberStyles.AllowTrailingWhite;
                     ne ^= NumberStyles.AllowTrailingWhite;
                 }
                 }
 
 
-                if (ne != 0)
+                if (ne != NumberStyles.None)
                 {
                 {
                     if (!tryParse)
                     if (!tryParse)
                     {
                     {
@@ -3424,7 +3513,7 @@ namespace Renci.SshNet.Common
             return char.IsDigit(e);
             return char.IsDigit(e);
         }
         }
 
 
-        private static Exception GetFormatException()
+        private static FormatException GetFormatException()
         {
         {
             return new FormatException("Input string was not in the correct format");
             return new FormatException("Input string was not in the correct format");
         }
         }
@@ -3545,7 +3634,9 @@ namespace Renci.SshNet.Common
             {
             {
                 result = val;
                 result = val;
             }
             }
+#pragma warning disable CA1508 // Avoid dead conditional code | this is the following bug in the analyzer rule: https://github.com/dotnet/roslyn-analyzers/issues/6991
             else if (sign == -1)
             else if (sign == -1)
+#pragma warning restore CA1508 // Avoid dead conditional code
             {
             {
                 result = new BigInteger(-1, val._data);
                 result = new BigInteger(-1, val._data);
             }
             }
@@ -3836,7 +3927,6 @@ namespace Renci.SshNet.Common
                 g = x;
                 g = x;
                 x = y % x;
                 x = y % x;
                 y = g;
                 y = g;
-
             }
             }
 
 
             if (x.IsZero)
             if (x.IsZero)
@@ -3926,7 +4016,7 @@ namespace Renci.SshNet.Common
             {
             {
                 if ((value._data[length] & (1 << curBit)) != 0)
                 if ((value._data[length] & (1 << curBit)) != 0)
                 {
                 {
-                    bitCount = curBit + length * 32;
+                    bitCount = curBit + (length * 32);
                     break;
                     break;
                 }
                 }
             }
             }
@@ -4472,7 +4562,7 @@ namespace Renci.SshNet.Common
                 if (carry == 0)
                 if (carry == 0)
                 {
                 {
                     var ex = FirstNonFfByte(word);
                     var ex = FirstNonFfByte(word);
-                    var needExtra = (word & (1 << (ex * 8 - 1))) == 0;
+                    var needExtra = (word & (1 << ((ex * 8) - 1))) == 0;
                     var to = ex + (needExtra ? 1 : 0);
                     var to = ex + (needExtra ? 1 : 0);
 
 
                     if (to != extra)
                     if (to != extra)
@@ -4488,7 +4578,9 @@ namespace Renci.SshNet.Common
 
 
                     if (needExtra)
                     if (needExtra)
                     {
                     {
+#pragma warning disable S1854 // Unused assignments should be removed
                         res[j++] = 0xFF;
                         res[j++] = 0xFF;
+#pragma warning restore S1854 // Unused assignments should be removed
                     }
                     }
                 }
                 }
                 else
                 else
@@ -4498,7 +4590,9 @@ namespace Renci.SshNet.Common
                     res[j++] = (byte)(word >> 8);
                     res[j++] = (byte)(word >> 8);
                     res[j++] = (byte)(word >> 16);
                     res[j++] = (byte)(word >> 16);
                     res[j++] = (byte)(word >> 24);
                     res[j++] = (byte)(word >> 24);
+#pragma warning disable S1854 // Unused assignments should be removed
                     res[j++] = 0xFF;
                     res[j++] = 0xFF;
+#pragma warning restore S1854 // Unused assignments should be removed
                 }
                 }
             }
             }
 
 
@@ -4807,14 +4901,14 @@ namespace Renci.SshNet.Common
                 {
                 {
                     int i;
                     int i;
 
 
-                    var rr = Base * un[j + n] + un[j + n - 1];
+                    var rr = (Base * un[j + n]) + un[j + n - 1];
                     var qq = rr / vn[n - 1];
                     var qq = rr / vn[n - 1];
                     rr -= qq * vn[n - 1];
                     rr -= qq * vn[n - 1];
 
 
-                    for (;;)
+                    for (; ; )
                     {
                     {
                         // Estimate too big ?
                         // Estimate too big ?
-                        if ((qq >= Base) || (qq * vn[n - 2] > (rr * Base + un[j + n - 2])))
+                        if ((qq >= Base) || (qq * vn[n - 2] > ((rr * Base) + un[j + n - 2])))
                         {
                         {
                             qq--;
                             qq--;
                             rr += (ulong)vn[n - 1];
                             rr += (ulong)vn[n - 1];
@@ -4827,7 +4921,6 @@ namespace Renci.SshNet.Common
                         break;
                         break;
                     }
                     }
 
 
-
                     // Multiply and subtract
                     // Multiply and subtract
                     long b = 0;
                     long b = 0;
                     long t;
                     long t;

+ 9 - 1
src/Renci.SshNet/Common/ChannelDataEventArgs.cs

@@ -1,4 +1,6 @@
-namespace Renci.SshNet.Common
+using System;
+
+namespace Renci.SshNet.Common
 {
 {
     /// <summary>
     /// <summary>
     /// Provides data for <see cref="Channels.Channel.DataReceived"/> event.
     /// Provides data for <see cref="Channels.Channel.DataReceived"/> event.
@@ -10,9 +12,15 @@
         /// </summary>
         /// </summary>
         /// <param name="channelNumber">Channel number.</param>
         /// <param name="channelNumber">Channel number.</param>
         /// <param name="data">Channel data.</param>
         /// <param name="data">Channel data.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="data"/> is <see langword="null"/>.</exception>
         public ChannelDataEventArgs(uint channelNumber, byte[] data)
         public ChannelDataEventArgs(uint channelNumber, byte[] data)
             : base(channelNumber)
             : base(channelNumber)
         {
         {
+            if (data is null)
+            {
+                throw new ArgumentNullException(nameof(data));
+            }
+
             Data = data;
             Data = data;
         }
         }
 
 

+ 6 - 0
src/Renci.SshNet/Common/ChannelRequestEventArgs.cs

@@ -13,8 +13,14 @@ namespace Renci.SshNet.Common
         /// Initializes a new instance of the <see cref="ChannelRequestEventArgs"/> class.
         /// Initializes a new instance of the <see cref="ChannelRequestEventArgs"/> class.
         /// </summary>
         /// </summary>
         /// <param name="info">Request information.</param>
         /// <param name="info">Request information.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="info"/> is <see langword="null"/>.</exception>
         public ChannelRequestEventArgs(RequestInfo info)
         public ChannelRequestEventArgs(RequestInfo info)
         {
         {
+            if (info is null)
+            {
+                throw new ArgumentNullException(nameof(info));
+            }
+
             Info = info;
             Info = info;
         }
         }
 
 

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

@@ -48,7 +48,7 @@ namespace Renci.SshNet.Common
         /// Initializes a new instance of the <see cref="DerData"/> class.
         /// Initializes a new instance of the <see cref="DerData"/> class.
         /// </summary>
         /// </summary>
         /// <param name="data">DER encoded data.</param>
         /// <param name="data">DER encoded data.</param>
-        /// <param name="construct">its a construct</param>
+        /// <param name="construct">its a construct.</param>
         public DerData(byte[] data, bool construct = false)
         public DerData(byte[] data, bool construct = false)
         {
         {
             _data = new List<byte>(data);
             _data = new List<byte>(data);

+ 2 - 1
src/Renci.SshNet/Common/Extensions.cs

@@ -50,7 +50,7 @@ namespace Renci.SshNet.Common
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Initializes a new instance of the <see cref="BigInteger"/> structure using the SSH BigNum2 Format
+        /// Initializes a new instance of the <see cref="BigInteger"/> structure using the SSH BigNum2 Format.
         /// </summary>
         /// </summary>
         public static BigInteger ToBigInteger2(this byte[] data)
         public static BigInteger ToBigInteger2(this byte[] data)
         {
         {
@@ -60,6 +60,7 @@ namespace Renci.SshNet.Common
                 Buffer.BlockCopy(data, 0, buf, 1, data.Length);
                 Buffer.BlockCopy(data, 0, buf, 1, data.Length);
                 data = buf;
                 data = buf;
             }
             }
+
             return data.ToBigInteger();
             return data.ToBigInteger();
         }
         }
 
 

+ 30 - 14
src/Renci.SshNet/Common/HostKeyEventArgs.cs

@@ -30,7 +30,7 @@ namespace Renci.SshNet.Common
         /// <summary>
         /// <summary>
         /// Gets the host key name.
         /// Gets the host key name.
         /// </summary>
         /// </summary>
-        public string HostKeyName{ get; private set; }
+        public string HostKeyName { get; private set; }
 
 
         /// <summary>
         /// <summary>
         /// Gets the MD5 fingerprint.
         /// Gets the MD5 fingerprint.
@@ -50,7 +50,7 @@ namespace Renci.SshNet.Common
         /// Gets the SHA256 fingerprint of the host key in the same format as the ssh command,
         /// Gets the SHA256 fingerprint of the host key in the same format as the ssh command,
         /// i.e. non-padded base64, but without the <c>SHA256:</c> prefix.
         /// i.e. non-padded base64, but without the <c>SHA256:</c> prefix.
         /// </summary>
         /// </summary>
-        /// <example><c>ohD8VZEXGWo6Ez8GSEJQ9WpafgLFsOfLOtGGQCQo6Og</c></example>
+        /// <example><c>ohD8VZEXGWo6Ez8GSEJQ9WpafgLFsOfLOtGGQCQo6Og</c>.</example>
         /// <value>
         /// <value>
         /// Base64 encoded SHA256 fingerprint with padding (equals sign) removed.
         /// Base64 encoded SHA256 fingerprint with padding (equals sign) removed.
         /// </value>
         /// </value>
@@ -66,7 +66,7 @@ namespace Renci.SshNet.Common
         /// Gets the MD5 fingerprint of the host key in the same format as the ssh command,
         /// Gets the MD5 fingerprint of the host key in the same format as the ssh command,
         /// i.e. hexadecimal bytes separated by colons, but without the <c>MD5:</c> prefix.
         /// i.e. hexadecimal bytes separated by colons, but without the <c>MD5:</c> prefix.
         /// </summary>
         /// </summary>
-        /// <example><c>97:70:33:82:fd:29:3a:73:39:af:6a:07:ad:f8:80:49</c></example>
+        /// <example><c>97:70:33:82:fd:29:3a:73:39:af:6a:07:ad:f8:80:49</c>.</example>
         public string FingerPrintMD5
         public string FingerPrintMD5
         {
         {
             get
             get
@@ -87,27 +87,43 @@ namespace Renci.SshNet.Common
         /// Initializes a new instance of the <see cref="HostKeyEventArgs"/> class.
         /// Initializes a new instance of the <see cref="HostKeyEventArgs"/> class.
         /// </summary>
         /// </summary>
         /// <param name="host">The host.</param>
         /// <param name="host">The host.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="host"/> is <see langword="null"/>.</exception>
         public HostKeyEventArgs(KeyHostAlgorithm host)
         public HostKeyEventArgs(KeyHostAlgorithm host)
         {
         {
+            if (host is null)
+            {
+                throw new ArgumentNullException(nameof(host));
+            }
+
             CanTrust = true;
             CanTrust = true;
             HostKey = host.Data;
             HostKey = host.Data;
             HostKeyName = host.Name;
             HostKeyName = host.Name;
             KeyLength = host.Key.KeyLength;
             KeyLength = host.Key.KeyLength;
-            
+
             _lazyFingerPrint = new Lazy<byte[]>(() =>
             _lazyFingerPrint = new Lazy<byte[]>(() =>
-            {
-                using var md5 = CryptoAbstraction.CreateMD5();
-                return md5.ComputeHash(HostKey);
-            });
+                {
+                    using var md5 = CryptoAbstraction.CreateMD5();
+                    return md5.ComputeHash(HostKey);
+                });
 
 
             _lazyFingerPrintSHA256 = new Lazy<string>(() =>
             _lazyFingerPrintSHA256 = new Lazy<string>(() =>
-            {
-                using var sha256 = CryptoAbstraction.CreateSHA256();
-                return Convert.ToBase64String(sha256.ComputeHash(HostKey)).Replace("=", "");
-            });
+                {
+                    using var sha256 = CryptoAbstraction.CreateSHA256();
+
+                    return Convert.ToBase64String(sha256.ComputeHash(HostKey))
+#if NET || NETSTANDARD2_1_OR_GREATER
+                                  .Replace("=", string.Empty, StringComparison.Ordinal);
+#else
+                                  .Replace("=", string.Empty);
+#endif // NET || NETSTANDARD2_1_OR_GREATER
+                });
 
 
-            _lazyFingerPrintMD5 = new Lazy<string>(() => 
-                BitConverter.ToString(FingerPrint).Replace("-", ":").ToLowerInvariant());
+            _lazyFingerPrintMD5 = new Lazy<string>(() =>
+                {
+#pragma warning disable CA1308 // Normalize strings to uppercase
+                    return BitConverter.ToString(FingerPrint).Replace('-', ':').ToLowerInvariant();
+#pragma warning restore CA1308 // Normalize strings to uppercase
+                });
         }
         }
     }
     }
 }
 }

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

@@ -41,7 +41,7 @@ namespace Renci.SshNet.Common
 
 
 #if FEATURE_BINARY_SERIALIZATION
 #if FEATURE_BINARY_SERIALIZATION
         /// <summary>
         /// <summary>
-        /// Initializes a new instance of the <see cref="SshAuthenticationException"/> class.
+        /// Initializes a new instance of the <see cref="NetConfServerException"/> class.
         /// </summary>
         /// </summary>
         /// <param name="info">The <see cref="SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
         /// <param name="info">The <see cref="SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
         /// <param name="context">The <see cref="StreamingContext"/> that contains contextual information about the source or destination.</param>
         /// <param name="context">The <see cref="StreamingContext"/> that contains contextual information about the source or destination.</param>

+ 2 - 0
src/Renci.SshNet/Common/ObjectIdentifier.cs

@@ -7,7 +7,9 @@ namespace Renci.SshNet.Common
     /// <summary>
     /// <summary>
     /// Describes object identifier for DER encoding.
     /// Describes object identifier for DER encoding.
     /// </summary>
     /// </summary>
+#pragma warning disable CA1815 // Override equals and operator equals on value types
     public struct ObjectIdentifier
     public struct ObjectIdentifier
+#pragma warning restore CA1815 // Override equals and operator equals on value types
     {
     {
         /// <summary>
         /// <summary>
         /// Gets the object identifier.
         /// Gets the object identifier.

+ 30 - 15
src/Renci.SshNet/Common/PipeStream.cs

@@ -10,8 +10,6 @@ namespace Renci.SshNet.Common
     /// PipeStream is a thread-safe read/write data stream for use between two threads in a
     /// PipeStream is a thread-safe read/write data stream for use between two threads in a
     /// single-producer/single-consumer type problem.
     /// single-producer/single-consumer type problem.
     /// </summary>
     /// </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>
     /// <license>
     /// Copyright (c) 2006 James Kolpack (james dot kolpack at google mail)
     /// Copyright (c) 2006 James Kolpack (james dot kolpack at google mail)
     ///
     ///
@@ -46,11 +44,6 @@ namespace Renci.SshNet.Common
         /// </summary>
         /// </summary>
         private bool _isFlushed;
         private bool _isFlushed;
 
 
-        /// <summary>
-        /// Maximum number of bytes to store in the buffer.
-        /// </summary>
-        private long _maxBufferLength = 200 * 1024 * 1024;
-
         /// <summary>
         /// <summary>
         /// Setting this to true will cause Read() to block if it appears
         /// Setting this to true will cause Read() to block if it appears
         /// that it will run out of data.
         /// that it will run out of data.
@@ -66,11 +59,7 @@ namespace Renci.SshNet.Common
         /// Gets or sets the maximum number of bytes to store in the buffer.
         /// Gets or sets the maximum number of bytes to store in the buffer.
         /// </summary>
         /// </summary>
         /// <value>The length of the max buffer.</value>
         /// <value>The length of the max buffer.</value>
-        public long MaxBufferLength
-        {
-            get { return _maxBufferLength; }
-            set { _maxBufferLength = value; }
-        }
+        public long MaxBufferLength { get; set; } = 200 * 1024 * 1024;
 
 
         /// <summary>
         /// <summary>
         /// Gets or sets a value indicating whether to block last read method before the buffer is empty.
         /// Gets or sets a value indicating whether to block last read method before the buffer is empty.
@@ -88,19 +77,27 @@ namespace Renci.SshNet.Common
         {
         {
             get
             get
             {
             {
+#if NET7_0_OR_GREATER
+                ObjectDisposedException.ThrowIf(_isDisposed, this);
+#else
                 if (_isDisposed)
                 if (_isDisposed)
                 {
                 {
                     throw CreateObjectDisposedException();
                     throw CreateObjectDisposedException();
                 }
                 }
+#endif // NET7_0_OR_GREATER
 
 
                 return _canBlockLastRead;
                 return _canBlockLastRead;
             }
             }
             set
             set
             {
             {
+#if NET7_0_OR_GREATER
+                ObjectDisposedException.ThrowIf(_isDisposed, this);
+#else
                 if (_isDisposed)
                 if (_isDisposed)
                 {
                 {
                     throw CreateObjectDisposedException();
                     throw CreateObjectDisposedException();
                 }
                 }
+#endif // NET7_0_OR_GREATER
 
 
                 _canBlockLastRead = value;
                 _canBlockLastRead = value;
 
 
@@ -126,10 +123,14 @@ namespace Renci.SshNet.Common
         /// </remarks>
         /// </remarks>
         public override void Flush()
         public override void Flush()
         {
         {
+#if NET7_0_OR_GREATER
+            ObjectDisposedException.ThrowIf(_isDisposed, this);
+#else
             if (_isDisposed)
             if (_isDisposed)
             {
             {
                 throw CreateObjectDisposedException();
                 throw CreateObjectDisposedException();
             }
             }
+#endif // NET7_0_OR_GREATER
 
 
             _isFlushed = true;
             _isFlushed = true;
             lock (_buffer)
             lock (_buffer)
@@ -200,15 +201,19 @@ namespace Renci.SshNet.Common
                 throw new ArgumentOutOfRangeException(nameof(offset), "offset or count is negative.");
                 throw new ArgumentOutOfRangeException(nameof(offset), "offset or count is negative.");
             }
             }
 
 
-            if (BlockLastReadBuffer && count >= _maxBufferLength)
+            if (BlockLastReadBuffer && count >= MaxBufferLength)
             {
             {
-                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "count({0}) > mMaxBufferLength({1})", count, _maxBufferLength));
+                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "count({0}) > mMaxBufferLength({1})", count, MaxBufferLength));
             }
             }
 
 
+#if NET7_0_OR_GREATER
+            ObjectDisposedException.ThrowIf(_isDisposed, this);
+#else
             if (_isDisposed)
             if (_isDisposed)
             {
             {
                 throw CreateObjectDisposedException();
                 throw CreateObjectDisposedException();
             }
             }
+#endif // NET7_0_OR_GREATER
 
 
             if (count == 0)
             if (count == 0)
             {
             {
@@ -284,10 +289,14 @@ namespace Renci.SshNet.Common
                 throw new ArgumentOutOfRangeException(nameof(offset), "offset or count is negative.");
                 throw new ArgumentOutOfRangeException(nameof(offset), "offset or count is negative.");
             }
             }
 
 
+#if NET7_0_OR_GREATER
+            ObjectDisposedException.ThrowIf(_isDisposed, this);
+#else
             if (_isDisposed)
             if (_isDisposed)
             {
             {
                 throw CreateObjectDisposedException();
                 throw CreateObjectDisposedException();
             }
             }
+#endif // NET7_0_OR_GREATER
 
 
             if (count == 0)
             if (count == 0)
             {
             {
@@ -297,7 +306,7 @@ namespace Renci.SshNet.Common
             lock (_buffer)
             lock (_buffer)
             {
             {
                 // wait until the buffer isn't full
                 // wait until the buffer isn't full
-                while (Length >= _maxBufferLength)
+                while (Length >= MaxBufferLength)
                 {
                 {
                     _ = Monitor.Wait(_buffer);
                     _ = Monitor.Wait(_buffer);
                 }
                 }
@@ -380,10 +389,14 @@ namespace Renci.SshNet.Common
         {
         {
             get
             get
             {
             {
+#if NET7_0_OR_GREATER
+                ObjectDisposedException.ThrowIf(_isDisposed, this);
+#else
                 if (_isDisposed)
                 if (_isDisposed)
                 {
                 {
                     throw CreateObjectDisposedException();
                     throw CreateObjectDisposedException();
                 }
                 }
+#endif // NET7_0_OR_GREATER
 
 
                 return _buffer.Count;
                 return _buffer.Count;
             }
             }
@@ -402,9 +415,11 @@ namespace Renci.SshNet.Common
             set { throw new NotSupportedException(); }
             set { throw new NotSupportedException(); }
         }
         }
 
 
+#if !NET7_0_OR_GREATER
         private ObjectDisposedException CreateObjectDisposedException()
         private ObjectDisposedException CreateObjectDisposedException()
         {
         {
             return new ObjectDisposedException(GetType().FullName);
             return new ObjectDisposedException(GetType().FullName);
         }
         }
+#endif // !NET7_0_OR_GREATER
     }
     }
 }
 }

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

@@ -6,7 +6,7 @@ namespace Renci.SshNet.Common
     /// <summary>
     /// <summary>
     /// Light implementation of SemaphoreSlim.
     /// Light implementation of SemaphoreSlim.
     /// </summary>
     /// </summary>
-    public class SemaphoreLight : IDisposable
+    public sealed class SemaphoreLight : IDisposable
     {
     {
         private readonly object _lock = new object();
         private readonly object _lock = new object();
         private ManualResetEvent _waitHandle;
         private ManualResetEvent _waitHandle;
@@ -228,7 +228,7 @@ namespace Renci.SshNet.Common
         /// Releases unmanaged and - optionally - managed resources.
         /// Releases unmanaged and - optionally - managed resources.
         /// </summary>
         /// </summary>
         /// <param name="disposing"><see langword="true"/> to release both managed and unmanaged resources; <see langword="false"/> to release only unmanaged resources.</param>
         /// <param name="disposing"><see langword="true"/> to release both managed and unmanaged resources; <see langword="false"/> to release only unmanaged resources.</param>
-        protected void Dispose(bool disposing)
+        private void Dispose(bool disposing)
         {
         {
             if (disposing)
             if (disposing)
             {
             {

+ 11 - 0
src/Renci.SshNet/Common/SshConnectionException.cs

@@ -47,6 +47,17 @@ namespace Renci.SshNet.Common
             DisconnectReason = disconnectReasonCode;
             DisconnectReason = disconnectReasonCode;
         }
         }
 
 
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SshConnectionException"/> class.
+        /// </summary>
+        /// <param name="message">The message.</param>
+        /// <param name="inner">The inner.</param>
+        public SshConnectionException(string message, Exception inner)
+            : base(message, inner)
+        {
+            DisconnectReason = DisconnectReason.None;
+        }
+
         /// <summary>
         /// <summary>
         /// Initializes a new instance of the <see cref="SshConnectionException"/> class.
         /// Initializes a new instance of the <see cref="SshConnectionException"/> class.
         /// </summary>
         /// </summary>

+ 31 - 15
src/Renci.SshNet/Common/SshData.cs

@@ -7,7 +7,9 @@ namespace Renci.SshNet.Common
     /// <summary>
     /// <summary>
     /// Base ssh data serialization type.
     /// Base ssh data serialization type.
     /// </summary>
     /// </summary>
+#pragma warning disable CA1001 // Types that own disposable fields should be disposable
     public abstract class SshData
     public abstract class SshData
+#pragma warning restore CA1001 // Types that own disposable fields should be disposable
     {
     {
         internal const int DefaultCapacity = 64;
         internal const int DefaultCapacity = 64;
 
 
@@ -63,9 +65,12 @@ namespace Renci.SshNet.Common
         {
         {
             var messageLength = BufferCapacity;
             var messageLength = BufferCapacity;
             var capacity = messageLength != -1 ? messageLength : DefaultCapacity;
             var capacity = messageLength != -1 ? messageLength : DefaultCapacity;
-            var dataStream = new SshDataStream(capacity);
-            WriteBytes(dataStream);
-            return dataStream.ToArray();
+
+            using (var dataStream = new SshDataStream(capacity))
+            {
+                WriteBytes(dataStream);
+                return dataStream.ToArray();
+            }
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -129,7 +134,9 @@ namespace Renci.SshNet.Common
         /// <summary>
         /// <summary>
         /// Reads all data left in internal buffer at current position.
         /// Reads all data left in internal buffer at current position.
         /// </summary>
         /// </summary>
-        /// <returns>An array of bytes containing the remaining data in the internal buffer.</returns>
+        /// <returns>
+        /// An array of bytes containing the remaining data in the internal buffer.
+        /// </returns>
         protected byte[] ReadBytes()
         protected byte[] ReadBytes()
         {
         {
             var bytesLength = (int) (_stream.Length - _stream.Position);
             var bytesLength = (int) (_stream.Length - _stream.Position);
@@ -142,16 +149,12 @@ namespace Renci.SshNet.Common
         /// Reads next specified number of bytes data type from internal buffer.
         /// Reads next specified number of bytes data type from internal buffer.
         /// </summary>
         /// </summary>
         /// <param name="length">Number of bytes to read.</param>
         /// <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>
+        /// <returns>
+        /// An array of bytes that was read from the internal buffer.
+        /// </returns>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="length"/> is greater than the number of bytes available to be read.</exception>
         protected byte[] ReadBytes(int length)
         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 data = new byte[length];
             var bytesRead = _stream.Read(data, 0, length);
             var bytesRead = _stream.Read(data, 0, length);
 
 
@@ -166,7 +169,10 @@ namespace Renci.SshNet.Common
         /// <summary>
         /// <summary>
         /// Reads next byte data type from internal buffer.
         /// Reads next byte data type from internal buffer.
         /// </summary>
         /// </summary>
-        /// <returns>Byte read.</returns>
+        /// <returns>
+        /// The <see cref="byte"/> read.
+        /// </returns>
+        /// <exception cref="InvalidOperationException">Attempt to read past the end of the stream.</exception>
         protected byte ReadByte()
         protected byte ReadByte()
         {
         {
             var byteRead = _stream.ReadByte();
             var byteRead = _stream.ReadByte();
@@ -184,6 +190,7 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// The <see cref="bool"/> that was read.
         /// The <see cref="bool"/> that was read.
         /// </returns>
         /// </returns>
+        /// <exception cref="InvalidOperationException">Attempt to read past the end of the stream.</exception>
         protected bool ReadBoolean()
         protected bool ReadBoolean()
         {
         {
             return ReadByte() != 0;
             return ReadByte() != 0;
@@ -195,6 +202,7 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// The <see cref="ushort"/> that was read.
         /// The <see cref="ushort"/> that was read.
         /// </returns>
         /// </returns>
+        /// <exception cref="InvalidOperationException">Attempt to read past the end of the stream.</exception>
         protected ushort ReadUInt16()
         protected ushort ReadUInt16()
         {
         {
             return Pack.BigEndianToUInt16(ReadBytes(2));
             return Pack.BigEndianToUInt16(ReadBytes(2));
@@ -206,6 +214,7 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// The <see cref="uint"/> that was read.
         /// The <see cref="uint"/> that was read.
         /// </returns>
         /// </returns>
+        /// <exception cref="InvalidOperationException">Attempt to read past the end of the stream.</exception>
         protected uint ReadUInt32()
         protected uint ReadUInt32()
         {
         {
             return Pack.BigEndianToUInt32(ReadBytes(4));
             return Pack.BigEndianToUInt32(ReadBytes(4));
@@ -217,6 +226,7 @@ namespace Renci.SshNet.Common
         /// <returns>
         /// <returns>
         /// The <see cref="ulong"/> that was read.
         /// The <see cref="ulong"/> that was read.
         /// </returns>
         /// </returns>
+        /// <exception cref="InvalidOperationException">Attempt to read past the end of the stream.</exception>
         protected ulong ReadUInt64()
         protected ulong ReadUInt64()
         {
         {
             return Pack.BigEndianToUInt64(ReadBytes(8));
             return Pack.BigEndianToUInt64(ReadBytes(8));
@@ -260,8 +270,10 @@ namespace Renci.SshNet.Common
         /// <summary>
         /// <summary>
         /// Reads next extension-pair data type from internal buffer.
         /// Reads next extension-pair data type from internal buffer.
         /// </summary>
         /// </summary>
-        /// <returns>Extensions pair dictionary.</returns>
-        protected IDictionary<string, string> ReadExtensionPair()
+        /// <returns>
+        /// Extensions pair dictionary.
+        /// </returns>
+        protected Dictionary<string, string> ReadExtensionPair()
         {
         {
             var result = new Dictionary<string, string>();
             var result = new Dictionary<string, string>();
 
 
@@ -373,7 +385,11 @@ namespace Renci.SshNet.Common
         /// <param name="data">name-list data to write.</param>
         /// <param name="data">name-list data to write.</param>
         protected void Write(string[] data)
         protected void Write(string[] data)
         {
         {
+#if NET || NETSTANDARD2_1_OR_GREATER
+            Write(string.Join(',', data), Ascii);
+#else
             Write(string.Join(",", data), Ascii);
             Write(string.Join(",", data), Ascii);
+#endif // NET || NETSTANDARD2_1_OR_GREATER
         }
         }
 
 
         /// <summary>
         /// <summary>

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

@@ -101,6 +101,24 @@ namespace Renci.SshNet.Common
             Write(data, 0, data.Length);
             Write(data, 0, data.Length);
         }
         }
 
 
+        /// <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 <see langword="null"/>.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="encoding"/> is <see langword="null"/>.</exception>
+        public void Write(string s, Encoding encoding)
+        {
+            if (encoding is null)
+            {
+                throw new ArgumentNullException(nameof(encoding));
+            }
+
+            var bytes = encoding.GetBytes(s);
+            WriteBinary(bytes, 0, bytes.Length);
+        }
+
         /// <summary>
         /// <summary>
         /// Reads a byte array from the SSH data stream.
         /// Reads a byte array from the SSH data stream.
         /// </summary>
         /// </summary>
@@ -149,24 +167,6 @@ namespace Renci.SshNet.Common
             Write(buffer, offset, 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 <see langword="null"/>.</exception>
-        /// <exception cref="ArgumentNullException"><paramref name="encoding"/> is <see langword="null"/>.</exception>
-        public void Write(string s, Encoding encoding)
-        {
-            if (encoding is null)
-            {
-                throw new ArgumentNullException(nameof(encoding));
-            }
-
-            var bytes = encoding.GetBytes(s);
-            WriteBinary(bytes, 0, bytes.Length);
-        }
-
         /// <summary>
         /// <summary>
         /// Reads a <see cref="BigInteger"/> from the SSH datastream.
         /// Reads a <see cref="BigInteger"/> from the SSH datastream.
         /// </summary>
         /// </summary>

+ 5 - 1
src/Renci.SshNet/Common/TerminalModes.cs

@@ -1,10 +1,13 @@
 namespace Renci.SshNet.Common
 namespace Renci.SshNet.Common
 {
 {
     /// <summary>
     /// <summary>
-    /// Specifies the initial assignments of the opcode values that are used in the 'encoded terminal modes' valu
+    /// Specifies the initial assignments of the opcode values that are used in the 'encoded terminal modes' value.
     /// </summary>
     /// </summary>
+#pragma warning disable CA1028 // Enum Storage should be Int32
     public enum TerminalModes : byte
     public enum TerminalModes : byte
+#pragma warning restore CA1028 // Enum Storage should be Int32
     {
     {
+#pragma warning disable CA1707 // Identifiers should not contain underscores
         /// <summary>
         /// <summary>
         /// Indicates end of options.
         /// Indicates end of options.
         /// </summary>
         /// </summary>
@@ -289,5 +292,6 @@
         /// Specifies the output baud rate in bits per second.
         /// Specifies the output baud rate in bits per second.
         /// </summary>
         /// </summary>
         TTY_OP_OSPEED = 129,
         TTY_OP_OSPEED = 129,
+#pragma warning restore CA1707 // Identifiers should not contain underscores
     }
     }
 }
 }

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

@@ -1,7 +1,7 @@
 namespace Renci.SshNet.Compression
 namespace Renci.SshNet.Compression
 {
 {
     /// <summary>
     /// <summary>
-    /// Specifies compression modes
+    /// Specifies compression modes.
     /// </summary>
     /// </summary>
     public enum CompressionMode
     public enum CompressionMode
     {
     {

+ 7 - 5
src/Renci.SshNet/Compression/Compressor.cs

@@ -6,7 +6,7 @@ using Renci.SshNet.Security;
 namespace Renci.SshNet.Compression
 namespace Renci.SshNet.Compression
 {
 {
     /// <summary>
     /// <summary>
-    /// Represents base class for compression algorithm implementation
+    /// Represents base class for compression algorithm implementation.
     /// </summary>
     /// </summary>
     public abstract class Compressor : Algorithm, IDisposable
     public abstract class Compressor : Algorithm, IDisposable
     {
     {
@@ -20,7 +20,7 @@ namespace Renci.SshNet.Compression
         /// Gets or sets a value indicating whether compression is active.
         /// Gets or sets a value indicating whether compression is active.
         /// </summary>
         /// </summary>
         /// <value>
         /// <value>
-        ///   <see langword="true"/> if compression is active; otherwise, <see langword="false"/>.
+        /// <see langword="true"/> if compression is active; otherwise, <see langword="false"/>.
         /// </value>
         /// </value>
         protected bool IsActive { get; set; }
         protected bool IsActive { get; set; }
 
 
@@ -42,7 +42,7 @@ namespace Renci.SshNet.Compression
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Initializes the algorithm
+        /// Initializes the algorithm.
         /// </summary>
         /// </summary>
         /// <param name="session">The session.</param>
         /// <param name="session">The session.</param>
         public virtual void Init(Session session)
         public virtual void Init(Session session)
@@ -54,7 +54,9 @@ namespace Renci.SshNet.Compression
         /// Compresses the specified data.
         /// Compresses the specified data.
         /// </summary>
         /// </summary>
         /// <param name="data">Data to compress.</param>
         /// <param name="data">Data to compress.</param>
-        /// <returns>Compressed data</returns>
+        /// <returns>
+        /// The compressed data.
+        /// </returns>
         public virtual byte[] Compress(byte[] data)
         public virtual byte[] Compress(byte[] data)
         {
         {
             return Compress(data, 0, data.Length);
             return Compress(data, 0, data.Length);
@@ -142,7 +144,7 @@ namespace Renci.SshNet.Compression
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Releases unmanaged and - optionally - managed resources
+        /// Releases unmanaged and - optionally - managed resources.
         /// </summary>
         /// </summary>
         /// <param name="disposing"><see langword="true"/> to release both managed and unmanaged resources; <see langword="false"/> to release only unmanaged resources.</param>
         /// <param name="disposing"><see langword="true"/> to release both managed and unmanaged resources; <see langword="false"/> to release only unmanaged resources.</param>
         protected virtual void Dispose(bool disposing)
         protected virtual void Dispose(bool disposing)

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

@@ -1,7 +1,7 @@
 namespace Renci.SshNet.Compression
 namespace Renci.SshNet.Compression
 {
 {
     /// <summary>
     /// <summary>
-    /// Represents "zlib" compression implementation
+    /// Represents "zlib" compression implementation.
     /// </summary>
     /// </summary>
     internal sealed class Zlib : Compressor
     internal sealed class Zlib : Compressor
     {
     {
@@ -14,7 +14,7 @@
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Initializes the algorithm
+        /// Initializes the algorithm.
         /// </summary>
         /// </summary>
         /// <param name="session">The session.</param>
         /// <param name="session">The session.</param>
         public override void Init(Session session)
         public override void Init(Session session)

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

@@ -3,7 +3,7 @@
 namespace Renci.SshNet.Compression
 namespace Renci.SshNet.Compression
 {
 {
     /// <summary>
     /// <summary>
-    /// Represents "zlib@openssh.org" compression implementation
+    /// Represents "zlib@openssh.org" compression implementation.
     /// </summary>
     /// </summary>
     public class ZlibOpenSsh : Compressor
     public class ZlibOpenSsh : Compressor
     {
     {
@@ -16,7 +16,7 @@ namespace Renci.SshNet.Compression
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Initializes the algorithm
+        /// Initializes the algorithm.
         /// </summary>
         /// </summary>
         /// <param name="session">The session.</param>
         /// <param name="session">The session.</param>
         public override void Init(Session session)
         public override void Init(Session session)
@@ -32,4 +32,4 @@ namespace Renci.SshNet.Compression
             Session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
             Session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
         }
         }
     }
     }
-}
+}

+ 9 - 0
src/Renci.SshNet/Compression/ZlibStream.cs

@@ -1,11 +1,16 @@
 using System.IO;
 using System.IO;
 
 
+#pragma warning disable S125 // Sections of code should not be commented out
+#pragma warning disable SA1005 // Single line comments should begin with single space
+
 namespace Renci.SshNet.Compression
 namespace Renci.SshNet.Compression
 {
 {
     /// <summary>
     /// <summary>
     /// Implements Zlib compression algorithm.
     /// Implements Zlib compression algorithm.
     /// </summary>
     /// </summary>
+#pragma warning disable CA1711 // Identifiers should not have incorrect suffix
     public class ZlibStream
     public class ZlibStream
+#pragma warning restore CA1711 // Identifiers should not have incorrect suffix
     {
     {
         //private readonly Ionic.Zlib.ZlibStream _baseStream;
         //private readonly Ionic.Zlib.ZlibStream _baseStream;
 
 
@@ -45,5 +50,9 @@ namespace Renci.SshNet.Compression
         {
         {
             //this._baseStream.Write(buffer, offset, count);
             //this._baseStream.Write(buffer, offset, count);
         }
         }
+#pragma warning restore SA1005 // Single line comments should begin with single space
     }
     }
 }
 }
+
+#pragma warning restore SA1005 // Single line comments should begin with single space
+#pragma warning restore S125 // Sections of code should not be commented out

+ 18 - 0
src/Renci.SshNet/Connection/IConnector.cs

@@ -3,10 +3,28 @@ using System.Threading;
 
 
 namespace Renci.SshNet.Connection
 namespace Renci.SshNet.Connection
 {
 {
+    /// <summary>
+    /// Represents a means to connect to a SSH endpoint.
+    /// </summary>
     internal interface IConnector
     internal interface IConnector
     {
     {
+        /// <summary>
+        /// Connects to a SSH endpoint using the specified <see cref="IConnectionInfo"/>.
+        /// </summary>
+        /// <param name="connectionInfo">The <see cref="IConnectionInfo"/> to use to establish a connection to a SSH endpoint.</param>
+        /// <returns>
+        /// A <see cref="Socket"/> connected to the SSH endpoint represented by the specified <see cref="IConnectionInfo"/>.
+        /// </returns>
         Socket Connect(IConnectionInfo connectionInfo);
         Socket Connect(IConnectionInfo connectionInfo);
 
 
+        /// <summary>
+        /// Asynchronously connects to a SSH endpoint using the specified <see cref="IConnectionInfo"/>.
+        /// </summary>
+        /// <param name="connectionInfo">The <see cref="IConnectionInfo"/> to use to establish a connection to a SSH endpoint.</param>
+        /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
+        /// <returns>
+        /// A <see cref="Socket"/> connected to the SSH endpoint represented by the specified <see cref="IConnectionInfo"/>.
+        /// </returns>
         System.Threading.Tasks.Task<Socket> ConnectAsync(IConnectionInfo connectionInfo, CancellationToken cancellationToken);
         System.Threading.Tasks.Task<Socket> ConnectAsync(IConnectionInfo connectionInfo, CancellationToken cancellationToken);
     }
     }
 }
 }

+ 13 - 1
src/Renci.SshNet/Connection/IProtocolVersionExchange.cs

@@ -1,5 +1,7 @@
 using System;
 using System;
 using System.Net.Sockets;
 using System.Net.Sockets;
+using System.Threading;
+using System.Threading.Tasks;
 
 
 namespace Renci.SshNet.Connection
 namespace Renci.SshNet.Connection
 {
 {
@@ -19,6 +21,16 @@ namespace Renci.SshNet.Connection
         /// </returns>
         /// </returns>
         SshIdentification Start(string clientVersion, Socket socket, TimeSpan timeout);
         SshIdentification Start(string clientVersion, Socket socket, TimeSpan timeout);
 
 
-        System.Threading.Tasks.Task<SshIdentification> StartAsync(string clientVersion, Socket socket, System.Threading.CancellationToken cancellationToken);
+        /// <summary>
+        /// Asynchronously performs the SSH protocol version exchange.
+        /// </summary>
+        /// <param name="clientVersion">The identification string of the SSH client.</param>
+        /// <param name="socket">A <see cref="Socket"/> connected to the server.</param>
+        /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
+        /// <returns>
+        /// A task that represents the SSH protocol version exchange. The value of its
+        /// <see cref="Task{Task}.Result"/> contains the SSH identification of the server.
+        /// </returns>
+        Task<SshIdentification> StartAsync(string clientVersion, Socket socket, CancellationToken cancellationToken);
     }
     }
 }
 }

+ 14 - 0
src/Renci.SshNet/Connection/ISocketFactory.cs

@@ -2,8 +2,22 @@
 
 
 namespace Renci.SshNet.Connection
 namespace Renci.SshNet.Connection
 {
 {
+    /// <summary>
+    /// Represents a factory to create <see cref="Socket"/> instances.
+    /// </summary>
     internal interface ISocketFactory
     internal interface ISocketFactory
     {
     {
+        /// <summary>
+        /// Creates a <see cref="Socket"/> with the specified <see cref="AddressFamily"/>,
+        /// <see cref="SocketType"/> and <see cref="ProtocolType"/> that does not use the
+        /// <c>Nagle</c> algorithm.
+        /// </summary>
+        /// <param name="addressFamily">The <see cref="AddressFamily"/>.</param>
+        /// <param name="socketType">The <see cref="SocketType"/>.</param>
+        /// <param name="protocolType">The <see cref="ProtocolType"/>.</param>
+        /// <returns>
+        /// The <see cref="Socket"/>.
+        /// </returns>
         Socket Create(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType);
         Socket Create(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType);
     }
     }
 }
 }

+ 11 - 1
src/Renci.SshNet/Connection/ProtocolVersionExchange.cs

@@ -23,7 +23,7 @@ namespace Renci.SshNet.Connection
     {
     {
         private const byte Null = 0x00;
         private const byte Null = 0x00;
 
 
-        private static readonly Regex ServerVersionRe = new Regex("^SSH-(?<protoversion>[^-]+)-(?<softwareversion>.+?)([ ](?<comments>.+))?$", RegexOptions.Compiled);
+        private static readonly Regex ServerVersionRe = new Regex("^SSH-(?<protoversion>[^-]+)-(?<softwareversion>.+?)([ ](?<comments>.+))?$", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
 
 
         /// <summary>
         /// <summary>
         /// Performs the SSH protocol version exchange.
         /// Performs the SSH protocol version exchange.
@@ -67,6 +67,16 @@ namespace Renci.SshNet.Connection
             }
             }
         }
         }
 
 
+        /// <summary>
+        /// Asynchronously performs the SSH protocol version exchange.
+        /// </summary>
+        /// <param name="clientVersion">The identification string of the SSH client.</param>
+        /// <param name="socket">A <see cref="Socket"/> connected to the server.</param>
+        /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
+        /// <returns>
+        /// A task that represents the SSH protocol version exchange. The value of its
+        /// <see cref="Task{Task}.Result"/> contains the SSH identification of the server.
+        /// </returns>
         public async Task<SshIdentification> StartAsync(string clientVersion, Socket socket, CancellationToken cancellationToken)
         public async Task<SshIdentification> StartAsync(string clientVersion, Socket socket, CancellationToken cancellationToken)
         {
         {
             // Immediately send the identification string since the spec states both sides MUST send an identification string
             // Immediately send the identification string since the spec states both sides MUST send an identification string

+ 33 - 2
src/Renci.SshNet/Connection/ProxyConnector.cs

@@ -5,6 +5,10 @@ using System.Threading.Tasks;
 
 
 namespace Renci.SshNet.Connection
 namespace Renci.SshNet.Connection
 {
 {
+    /// <summary>
+    /// Represents a connector that uses a proxy server to establish a connection to a given SSH
+    /// endpoint.
+    /// </summary>
     internal abstract class ProxyConnector : ConnectorBase
     internal abstract class ProxyConnector : ConnectorBase
     {
     {
         protected ProxyConnector(ISocketFactory socketFactory)
         protected ProxyConnector(ISocketFactory socketFactory)
@@ -15,18 +19,37 @@ namespace Renci.SshNet.Connection
         protected abstract void HandleProxyConnect(IConnectionInfo connectionInfo, Socket socket);
         protected abstract void HandleProxyConnect(IConnectionInfo connectionInfo, Socket socket);
 
 
         // ToDo: Performs async/sync fallback, true async version should be implemented in derived classes
         // ToDo: Performs async/sync fallback, true async version should be implemented in derived classes
-        protected virtual Task HandleProxyConnectAsync(IConnectionInfo connectionInfo, Socket socket, CancellationToken cancellationToken)
+        protected virtual
+#if NET || NETSTANDARD2_1_OR_GREATER
+        async
+#endif // NET || NETSTANDARD2_1_OR_GREATER
+        Task HandleProxyConnectAsync(IConnectionInfo connectionInfo, Socket socket, CancellationToken cancellationToken)
         {
         {
             cancellationToken.ThrowIfCancellationRequested();
             cancellationToken.ThrowIfCancellationRequested();
 
 
-            using (cancellationToken.Register(o => ((Socket)o).Dispose(), socket, useSynchronizationContext: false))
+#if NET || NETSTANDARD2_1_OR_GREATER
+            await using (cancellationToken.Register(o => ((Socket)o).Dispose(), socket, useSynchronizationContext: false).ConfigureAwait(continueOnCapturedContext: false))
+#else
+            using (cancellationToken.Register(o => ((Socket) o).Dispose(), socket, useSynchronizationContext: false))
+#endif // NET || NETSTANDARD2_1_OR_GREATER
             {
             {
+#pragma warning disable MA0042 // Do not use blocking calls in an async method; false positive caused by https://github.com/meziantou/Meziantou.Analyzer/issues/613
                 HandleProxyConnect(connectionInfo, socket);
                 HandleProxyConnect(connectionInfo, socket);
+#pragma warning restore MA0042 // Do not use blocking calls in an async method
             }
             }
 
 
+#if !NET && !NETSTANDARD2_1_OR_GREATER
             return Task.CompletedTask;
             return Task.CompletedTask;
+#endif // !NET && !NETSTANDARD2_1_OR_GREATER
         }
         }
 
 
+        /// <summary>
+        /// Connects to a SSH endpoint using the specified <see cref="IConnectionInfo"/>.
+        /// </summary>
+        /// <param name="connectionInfo">The <see cref="IConnectionInfo"/> to use to establish a connection to a SSH endpoint.</param>
+        /// <returns>
+        /// A <see cref="Socket"/> connected to the SSH endpoint represented by the specified <see cref="IConnectionInfo"/>.
+        /// </returns>
         public override Socket Connect(IConnectionInfo connectionInfo)
         public override Socket Connect(IConnectionInfo connectionInfo)
         {
         {
             var socket = SocketConnect(connectionInfo.ProxyHost, connectionInfo.ProxyPort, connectionInfo.Timeout);
             var socket = SocketConnect(connectionInfo.ProxyHost, connectionInfo.ProxyPort, connectionInfo.Timeout);
@@ -45,6 +68,14 @@ namespace Renci.SshNet.Connection
             }
             }
         }
         }
 
 
+        /// <summary>
+        /// Asynchronously connects to a SSH endpoint using the specified <see cref="IConnectionInfo"/>.
+        /// </summary>
+        /// <param name="connectionInfo">The <see cref="IConnectionInfo"/> to use to establish a connection to a SSH endpoint.</param>
+        /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
+        /// <returns>
+        /// A <see cref="Socket"/> connected to the SSH endpoint represented by the specified <see cref="IConnectionInfo"/>.
+        /// </returns>
         public override async Task<Socket> ConnectAsync(IConnectionInfo connectionInfo, CancellationToken cancellationToken)
         public override async Task<Socket> ConnectAsync(IConnectionInfo connectionInfo, CancellationToken cancellationToken)
         {
         {
             var socket = await SocketConnectAsync(connectionInfo.ProxyHost, connectionInfo.ProxyPort, cancellationToken).ConfigureAwait(false);
             var socket = await SocketConnectAsync(connectionInfo.ProxyHost, connectionInfo.ProxyPort, cancellationToken).ConfigureAwait(false);

+ 15 - 1
src/Renci.SshNet/Connection/SocketFactory.cs

@@ -2,11 +2,25 @@
 
 
 namespace Renci.SshNet.Connection
 namespace Renci.SshNet.Connection
 {
 {
+    /// <summary>
+    /// Represents a factory to create <see cref="Socket"/> instances.
+    /// </summary>
     internal sealed class SocketFactory : ISocketFactory
     internal sealed class SocketFactory : ISocketFactory
     {
     {
+        /// <summary>
+        /// Creates a <see cref="Socket"/> with the specified <see cref="AddressFamily"/>,
+        /// <see cref="SocketType"/> and <see cref="ProtocolType"/> that does not use the
+        /// <c>Nagle</c> algorithm.
+        /// </summary>
+        /// <param name="addressFamily">The <see cref="AddressFamily"/>.</param>
+        /// <param name="socketType">The <see cref="SocketType"/>.</param>
+        /// <param name="protocolType">The <see cref="ProtocolType"/>.</param>
+        /// <returns>
+        /// The <see cref="Socket"/>.
+        /// </returns>
         public Socket Create(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
         public Socket Create(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
         {
         {
-            return new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp) { NoDelay = true };
+            return new Socket(addressFamily, socketType, protocolType) { NoDelay = true };
         }
         }
     }
     }
 }
 }

+ 17 - 15
src/Renci.SshNet/Connection/Socks4Connector.cs

@@ -62,21 +62,23 @@ namespace Renci.SshNet.Connection
             var addressBytes = GetSocks4DestinationAddress(hostname);
             var addressBytes = GetSocks4DestinationAddress(hostname);
             var proxyUserBytes = GetProxyUserBytes(username);
             var proxyUserBytes = GetProxyUserBytes(username);
 
 
-            var connectionRequest = new byte
-                [
-                    // SOCKS version number
-                    1 +
-                    // Command code
-                    1 +
-                    // Port number
-                    2 +
-                    // IP address
-                    addressBytes.Length +
-                    // Username
-                    proxyUserBytes.Length +
-                    // Null terminator
-                    1
-                ];
+            var connectionRequest = new byte[// SOCKS version number
+                                             1 +
+
+                                             // Command code
+                                             1 +
+
+                                             // Port number
+                                             2 +
+
+                                             // IP address
+                                             addressBytes.Length +
+
+                                             // Username
+                                             proxyUserBytes.Length +
+
+                                             // Null terminator
+                                             1];
 
 
             var index = 0;
             var index = 0;
 
 

+ 34 - 28
src/Renci.SshNet/Connection/Socks5Connector.cs

@@ -30,10 +30,13 @@ namespace Renci.SshNet.Connection
                 {
                 {
                     // SOCKS version number
                     // SOCKS version number
                     0x05,
                     0x05,
+
                     // Number of supported authentication methods
                     // Number of supported authentication methods
                     0x02,
                     0x02,
+
                     // No authentication
                     // No authentication
                     0x00,
                     0x00,
+
                     // Username/Password authentication
                     // Username/Password authentication
                     0x02
                     0x02
                 };
                 };
@@ -156,19 +159,20 @@ namespace Renci.SshNet.Connection
                 throw new ProxyException("Proxy password is too long.");
                 throw new ProxyException("Proxy password is too long.");
             }
             }
 
 
-            var authenticationRequest = new byte
-                [
-                    // Version of the negotiation
-                    1 +
-                    // Length of the username
-                    1 +
-                    // Username
-                    username.Length +
-                    // Length of the password
-                    1 +
-                    // Password
-                    password.Length
-                ];
+            var authenticationRequest = new byte[// Version of the negotiation
+                                                 1 +
+
+                                                 // Length of the username
+                                                 1 +
+
+                                                 // Username
+                                                 username.Length +
+
+                                                 // Length of the password
+                                                 1 +
+
+                                                 // Password
+                                                 password.Length];
 
 
             var index = 0;
             var index = 0;
 
 
@@ -195,21 +199,23 @@ namespace Renci.SshNet.Connection
         {
         {
             var addressBytes = GetSocks5DestinationAddress(hostname, out var addressType);
             var addressBytes = GetSocks5DestinationAddress(hostname, out var addressType);
 
 
-            var connectionRequest = new byte
-                [
-                    // SOCKS version number
-                    1 +
-                    // Command code
-                    1 +
-                    // Reserved
-                    1 +
-                    // Address type
-                    1 +
-                    // Address
-                    addressBytes.Length +
-                    // Port number
-                    2
-                ];
+            var connectionRequest = new byte[// SOCKS version number
+                                             1 +
+
+                                             // Command code
+                                             1 +
+
+                                             // Reserved
+                                             1 +
+
+                                             // Address type
+                                             1 +
+
+                                             // Address
+                                             addressBytes.Length +
+
+                                             // Port number
+                                             2];
 
 
             var index = 0;
             var index = 0;
 
 

+ 18 - 2
src/Renci.SshNet/ConnectionInfo.cs

@@ -398,8 +398,10 @@ namespace Renci.SshNet
                     { "ecdsa-sha2-nistp256", data => new KeyHostAlgorithm("ecdsa-sha2-nistp256", new EcdsaKey(), data) },
                     { "ecdsa-sha2-nistp256", data => new KeyHostAlgorithm("ecdsa-sha2-nistp256", new EcdsaKey(), data) },
                     { "ecdsa-sha2-nistp384", data => new KeyHostAlgorithm("ecdsa-sha2-nistp384", new EcdsaKey(), data) },
                     { "ecdsa-sha2-nistp384", data => new KeyHostAlgorithm("ecdsa-sha2-nistp384", new EcdsaKey(), data) },
                     { "ecdsa-sha2-nistp521", data => new KeyHostAlgorithm("ecdsa-sha2-nistp521", new EcdsaKey(), data) },
                     { "ecdsa-sha2-nistp521", data => new KeyHostAlgorithm("ecdsa-sha2-nistp521", new EcdsaKey(), data) },
-                    { "rsa-sha2-512", data => { var key = new RsaKey(); return new KeyHostAlgorithm("rsa-sha2-512", key, data, new RsaDigitalSignature(key, HashAlgorithmName.SHA512)); }},
-                    { "rsa-sha2-256", data => { var key = new RsaKey(); return new KeyHostAlgorithm("rsa-sha2-256", key, data, new RsaDigitalSignature(key, HashAlgorithmName.SHA256)); }},
+#pragma warning disable SA1107 // Code should not contain multiple statements on one line
+                    { "rsa-sha2-512", data => { var key = new RsaKey(); return new KeyHostAlgorithm("rsa-sha2-512", key, data, new RsaDigitalSignature(key, HashAlgorithmName.SHA512)); } },
+                    { "rsa-sha2-256", data => { var key = new RsaKey(); return new KeyHostAlgorithm("rsa-sha2-256", key, data, new RsaDigitalSignature(key, HashAlgorithmName.SHA256)); } },
+#pragma warning restore SA1107 // Code should not contain multiple statements on one line
                     { "ssh-rsa", data => new KeyHostAlgorithm("ssh-rsa", new RsaKey(), data) },
                     { "ssh-rsa", data => new KeyHostAlgorithm("ssh-rsa", new RsaKey(), data) },
                     { "ssh-dss", data => new KeyHostAlgorithm("ssh-dss", new DsaKey(), data) },
                     { "ssh-dss", data => new KeyHostAlgorithm("ssh-dss", new DsaKey(), data) },
                 };
                 };
@@ -470,14 +472,28 @@ namespace Renci.SshNet
             AuthenticationBanner?.Invoke(this, new AuthenticationBannerEventArgs(Username, e.Message.Message, e.Message.Language));
             AuthenticationBanner?.Invoke(this, new AuthenticationBannerEventArgs(Username, e.Message.Message, e.Message.Language));
         }
         }
 
 
+        /// <summary>
+        /// Creates a <c>none</c> authentication method.
+        /// </summary>
+        /// <returns>
+        /// A <c>none</c> authentication method.
+        /// </returns>
         IAuthenticationMethod IConnectionInfoInternal.CreateNoneAuthenticationMethod()
         IAuthenticationMethod IConnectionInfoInternal.CreateNoneAuthenticationMethod()
         {
         {
             return new NoneAuthenticationMethod(Username);
             return new NoneAuthenticationMethod(Username);
         }
         }
 
 
+        /// <summary>
+        /// Gets the supported authentication methods for this connection.
+        /// </summary>
+        /// <value>
+        /// The supported authentication methods for this connection.
+        /// </value>
         IList<IAuthenticationMethod> IConnectionInfoInternal.AuthenticationMethods
         IList<IAuthenticationMethod> IConnectionInfoInternal.AuthenticationMethods
         {
         {
+#pragma warning disable S2365 // Properties should not make collection or array copies
             get { return AuthenticationMethods.Cast<IAuthenticationMethod>().ToList(); }
             get { return AuthenticationMethods.Cast<IAuthenticationMethod>().ToList(); }
+#pragma warning restore S2365 // Properties should not make collection or array copies
         }
         }
     }
     }
 }
 }

+ 4 - 2
src/Renci.SshNet/ForwardedPortDynamic.cs

@@ -361,10 +361,12 @@ namespace Renci.SshNet
                 Closing -= closeClientSocket;
                 Closing -= closeClientSocket;
             }
             }
 
 
-            void closeClientSocket(object _, EventArgs args)
+#pragma warning disable SA1300 // Element should begin with upper-case letter
+            void closeClientSocket(object sender, EventArgs args)
             {
             {
                 CloseClientSocket(clientSocket);
                 CloseClientSocket(clientSocket);
-            };
+            }
+#pragma warning restore SA1300 // Element should begin with upper-case letter
         }
         }
 
 
         private static void CloseClientSocket(Socket clientSocket)
         private static void CloseClientSocket(Socket clientSocket)

+ 2 - 0
src/Renci.SshNet/ForwardedPortStatus.cs

@@ -34,7 +34,9 @@ namespace Renci.SshNet
             return forwardedPortStatus._value == _value;
             return forwardedPortStatus._value == _value;
         }
         }
 
 
+#pragma warning disable S3875 // "operator==" should not be overloaded on reference types
         public static bool operator ==(ForwardedPortStatus left, ForwardedPortStatus right)
         public static bool operator ==(ForwardedPortStatus left, ForwardedPortStatus right)
+#pragma warning restore S3875 // "operator==" should not be overloaded on reference types
         {
         {
             // check if lhs is null
             // check if lhs is null
             if (left is null)
             if (left is null)

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

@@ -5,7 +5,7 @@ using Renci.SshNet.Common;
 namespace Renci.SshNet
 namespace Renci.SshNet
 {
 {
     /// <summary>
     /// <summary>
-    /// Holds information about key size and cipher to use
+    /// Holds information about key size and cipher to use.
     /// </summary>
     /// </summary>
     public class HashInfo
     public class HashInfo
     {
     {
@@ -23,7 +23,7 @@ namespace Renci.SshNet
         public Func<byte[], HashAlgorithm> HashAlgorithm { get; private set; }
         public Func<byte[], HashAlgorithm> HashAlgorithm { get; private set; }
 
 
         /// <summary>
         /// <summary>
-        /// Initializes a new instance of the <see cref="CipherInfo"/> class.
+        /// Initializes a new instance of the <see cref="HashInfo"/> class.
         /// </summary>
         /// </summary>
         /// <param name="keySize">Size of the key.</param>
         /// <param name="keySize">Size of the key.</param>
         /// <param name="hash">The hash algorithm to use for a given key.</param>
         /// <param name="hash">The hash algorithm to use for a given key.</param>

+ 1 - 6
src/Renci.SshNet/IBaseClient.cs

@@ -10,7 +10,7 @@ namespace Renci.SshNet
     /// <summary>
     /// <summary>
     /// Serves as base class for client implementations, provides common client functionality.
     /// Serves as base class for client implementations, provides common client functionality.
     /// </summary>
     /// </summary>
-    public interface IBaseClient
+    public interface IBaseClient : IDisposable
     {
     {
         /// <summary>
         /// <summary>
         /// Gets the connection info.
         /// Gets the connection info.
@@ -87,11 +87,6 @@ namespace Renci.SshNet
         /// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
         /// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
         void Disconnect();
         void Disconnect();
 
 
-        /// <summary>
-        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
-        /// </summary>
-        void Dispose();
-
         /// <summary>
         /// <summary>
         /// Sends a keep-alive message to the server.
         /// Sends a keep-alive message to the server.
         /// </summary>
         /// </summary>

+ 17 - 1
src/Renci.SshNet/IClientAuthentication.cs

@@ -1,7 +1,23 @@
-namespace Renci.SshNet
+using System;
+
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet
 {
 {
+    /// <summary>
+    /// Represents a mechanism to authenticate a given client.
+    /// </summary>
     internal interface IClientAuthentication
     internal interface IClientAuthentication
     {
     {
+        /// <summary>
+        /// Attempts to perform authentication for a given <see cref="ISession"/> using the
+        /// <see cref="IConnectionInfoInternal.AuthenticationMethods"/> of the specified
+        /// <see cref="IConnectionInfoInternal"/>.
+        /// </summary>
+        /// <param name="connectionInfo">A <see cref="IConnectionInfoInternal"/> to use for authenticating.</param>
+        /// <param name="session">The <see cref="ISession"/> for which to perform authentication.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="connectionInfo"/> or <paramref name="session"/> is <see langword="null"/>.</exception>
+        /// <exception cref="SshAuthenticationException">Failed to Authenticate the client.</exception>
         void Authenticate(IConnectionInfoInternal connectionInfo, ISession session);
         void Authenticate(IConnectionInfoInternal connectionInfo, ISession session);
     }
     }
 }
 }

+ 0 - 29
src/Renci.SshNet/IConnectionInfo.cs

@@ -3,39 +3,10 @@ using System.Collections.Generic;
 using System.Text;
 using System.Text;
 
 
 using Renci.SshNet.Common;
 using Renci.SshNet.Common;
-using Renci.SshNet.Messages.Authentication;
 using Renci.SshNet.Messages.Connection;
 using Renci.SshNet.Messages.Connection;
 
 
 namespace Renci.SshNet
 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>
     /// <summary>
     /// Represents remote connection information.
     /// Represents remote connection information.
     /// </summary>
     /// </summary>

+ 37 - 0
src/Renci.SshNet/IConnectionInfoInternal.cs

@@ -0,0 +1,37 @@
+using System.Collections.Generic;
+
+using Renci.SshNet.Messages.Authentication;
+
+namespace Renci.SshNet
+{
+    /// <summary>
+    /// Represents remote connection information.
+    /// </summary>
+    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();
+    }
+}

+ 0 - 30
src/Renci.SshNet/IForwardedPort.cs

@@ -1,7 +1,5 @@
 using System;
 using System;
 
 
-using Renci.SshNet.Common;
-
 namespace Renci.SshNet
 namespace Renci.SshNet
 {
 {
     /// <summary>
     /// <summary>
@@ -13,33 +11,5 @@ namespace Renci.SshNet
         /// The <see cref="Closing"/> event occurs as the forwarded port is being stopped.
         /// The <see cref="Closing"/> event occurs as the forwarded port is being stopped.
         /// </summary>
         /// </summary>
         event EventHandler Closing;
         event EventHandler Closing;
-
-        /// <summary>
-        /// Occurs when an exception is thrown.
-        /// </summary>
-        event EventHandler<ExceptionEventArgs> Exception;
-
-        /// <summary>
-        /// Occurs when a port forwarding request is received.
-        /// </summary>
-        event EventHandler<PortForwardEventArgs> RequestReceived;
-
-        /// <summary>
-        /// Gets a value indicating whether port forwarding is started.
-        /// </summary>
-        /// <value>
-        /// <see langword="true"/> if port forwarding is started; otherwise, <see langword="false"/>.
-        /// </value>
-        bool IsStarted { get; }
-
-        /// <summary>
-        /// Starts port forwarding.
-        /// </summary>
-        void Start();
-
-        /// <summary>
-        /// Stops port forwarding.
-        /// </summary>
-        void Stop();
     }
     }
 }
 }

+ 4 - 1
src/Renci.SshNet/ISession.cs

@@ -17,7 +17,7 @@ namespace Renci.SshNet
     internal interface ISession : IDisposable
     internal interface ISession : IDisposable
     {
     {
         /// <summary>
         /// <summary>
-        /// Gets or sets the connection info.
+        /// Gets the connection info.
         /// </summary>
         /// </summary>
         /// <value>The connection info.</value>
         /// <value>The connection info.</value>
         IConnectionInfo ConnectionInfo { get; }
         IConnectionInfo ConnectionInfo { get; }
@@ -86,6 +86,9 @@ namespace Renci.SshNet
         /// <summary>
         /// <summary>
         /// Creates a "forwarded-tcpip" SSH channel.
         /// Creates a "forwarded-tcpip" SSH channel.
         /// </summary>
         /// </summary>
+        /// <param name="remoteChannelNumber">The number of the remote channel.</param>
+        /// <param name="remoteWindowSize">The window size of the remote channel.</param>
+        /// <param name="remoteChannelDataPacketSize">The data packet size of the remote channel.</param>
         /// <returns>
         /// <returns>
         /// A new "forwarded-tcpip" SSH channel.
         /// A new "forwarded-tcpip" SSH channel.
         /// </returns>
         /// </returns>

+ 20 - 18
src/Renci.SshNet/ISftpClient.cs

@@ -13,7 +13,7 @@ namespace Renci.SshNet
     /// <summary>
     /// <summary>
     /// Implementation of the SSH File Transfer Protocol (SFTP) over SSH.
     /// Implementation of the SSH File Transfer Protocol (SFTP) over SSH.
     /// </summary>
     /// </summary>
-    public interface ISftpClient : IBaseClient, IDisposable
+    public interface ISftpClient : IBaseClient
     {
     {
         /// <summary>
         /// <summary>
         /// Gets or sets the maximum size of the buffer in bytes.
         /// Gets or sets the maximum size of the buffer in bytes.
@@ -78,12 +78,12 @@ namespace Renci.SshNet
         /// </summary>
         /// </summary>
         /// <param name="path">The file to append the lines to. The file is created if it does not already exist.</param>
         /// <param name="path">The file to append the lines to. The file is created if it does not already exist.</param>
         /// <param name="contents">The lines to append to the file.</param>
         /// <param name="contents">The lines to append to the file.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="path"/> is<see langword="null"/> <para>-or-</para> <paramref name="contents"/> is <see langword="null"/>.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="path"/> is <see langword="null"/>. <para>-or-</para> <paramref name="contents"/> is <see langword="null"/>.</exception>
         /// <exception cref="SshConnectionException">Client is not connected.</exception>
         /// <exception cref="SshConnectionException">Client is not connected.</exception>
         /// <exception cref="SftpPathNotFoundException">The specified path is invalid, or its directory was not found on the remote host.</exception>
         /// <exception cref="SftpPathNotFoundException">The specified path is invalid, or its directory was not found on the remote host.</exception>
         /// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
         /// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
         /// <remarks>
         /// <remarks>
-        /// The characters are written to the file using UTF-8 encoding without a Byte-Order Mark (BOM)
+        /// The characters are written to the file using UTF-8 encoding without a Byte-Order Mark (BOM).
         /// </remarks>
         /// </remarks>
         void AppendAllLines(string path, IEnumerable<string> contents);
         void AppendAllLines(string path, IEnumerable<string> contents);
 
 
@@ -239,7 +239,7 @@ namespace Renci.SshNet
         /// </returns>
         /// </returns>
         /// <exception cref="ArgumentNullException"><paramref name="sourcePath"/> is <see langword="null"/>.</exception>
         /// <exception cref="ArgumentNullException"><paramref name="sourcePath"/> is <see langword="null"/>.</exception>
         /// <exception cref="ArgumentException"><paramref name="destinationPath"/> is <see langword="null"/> or contains only whitespace.</exception>
         /// <exception cref="ArgumentException"><paramref name="destinationPath"/> is <see langword="null"/> or contains only whitespace.</exception>
-        /// <exception cref="SshException">If a problem occurs while copying the file</exception>
+        /// <exception cref="SshException">If a problem occurs while copying the file.</exception>
         IAsyncResult BeginSynchronizeDirectories(string sourcePath, string destinationPath, string searchPattern, AsyncCallback asyncCallback, object state);
         IAsyncResult BeginSynchronizeDirectories(string sourcePath, string destinationPath, string searchPattern, AsyncCallback asyncCallback, object state);
 
 
         /// <summary>
         /// <summary>
@@ -568,7 +568,7 @@ namespace Renci.SshNet
         void EndUploadFile(IAsyncResult asyncResult);
         void EndUploadFile(IAsyncResult asyncResult);
 
 
         /// <summary>
         /// <summary>
-        /// Checks whether file or directory exists;
+        /// Checks whether file or directory exists.
         /// </summary>
         /// </summary>
         /// <param name="path">The path.</param>
         /// <param name="path">The path.</param>
         /// <returns>
         /// <returns>
@@ -592,7 +592,9 @@ namespace Renci.SshNet
         /// <exception cref="SftpPathNotFoundException"><paramref name="path"/> was not found on the remote host.</exception>
         /// <exception cref="SftpPathNotFoundException"><paramref name="path"/> was not found on the remote host.</exception>
         /// <exception cref="ArgumentNullException"><paramref name="path" /> is <see langword="null"/>.</exception>
         /// <exception cref="ArgumentNullException"><paramref name="path" /> is <see langword="null"/>.</exception>
         /// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
         /// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
+#pragma warning disable CA1716 // Identifiers should not match keywords
         ISftpFile Get(string path);
         ISftpFile Get(string path);
+#pragma warning restore CA1716 // Identifiers should not match keywords
 
 
         /// <summary>
         /// <summary>
         /// Gets the <see cref="SftpFileAttributes"/> of the file on the path.
         /// Gets the <see cref="SftpFileAttributes"/> of the file on the path.
@@ -898,31 +900,31 @@ namespace Renci.SshNet
         void RenameFile(string oldPath, string newPath);
         void RenameFile(string oldPath, string newPath);
 
 
         /// <summary>
         /// <summary>
-        /// Asynchronously renames remote file from old path to new path.
+        /// Renames remote file from old path to new path.
         /// </summary>
         /// </summary>
         /// <param name="oldPath">Path to the old file location.</param>
         /// <param name="oldPath">Path to the old file location.</param>
         /// <param name="newPath">Path to the new file location.</param>
         /// <param name="newPath">Path to the new file location.</param>
-        /// <param name="cancellationToken">The <see cref="CancellationToken"/> to observe.</param>
-        /// <returns>A <see cref="Task"/> that represents the asynchronous rename operation.</returns>
-        /// <exception cref="ArgumentNullException"><paramref name="oldPath"/> is <see langword="null"/>. <para>-or-</para> or <paramref name="newPath"/> is <see langword="null"/>.</exception>
+        /// <param name="isPosix">if set to <see langword="true"/> then perform a posix rename.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="oldPath" /> is <see langword="null"/>. <para>-or-</para> or <paramref name="newPath" /> is <see langword="null"/>.</exception>
         /// <exception cref="SshConnectionException">Client is not connected.</exception>
         /// <exception cref="SshConnectionException">Client is not connected.</exception>
         /// <exception cref="SftpPermissionDeniedException">Permission to rename the file was denied by the remote host. <para>-or-</para> A SSH command was denied by the server.</exception>
         /// <exception cref="SftpPermissionDeniedException">Permission to rename the file was denied by the remote host. <para>-or-</para> A SSH command was denied by the server.</exception>
-        /// <exception cref="SshException">A SSH error where <see cref="Exception.Message"/> is the message from the remote host.</exception>
+        /// <exception cref="SshException">A SSH error where <see cref="Exception.Message" /> is the message from the remote host.</exception>
         /// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
         /// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
-        Task RenameFileAsync(string oldPath, string newPath, CancellationToken cancellationToken);
+        void RenameFile(string oldPath, string newPath, bool isPosix);
 
 
         /// <summary>
         /// <summary>
-        /// Renames remote file from old path to new path.
+        /// Asynchronously renames remote file from old path to new path.
         /// </summary>
         /// </summary>
         /// <param name="oldPath">Path to the old file location.</param>
         /// <param name="oldPath">Path to the old file location.</param>
         /// <param name="newPath">Path to the new file location.</param>
         /// <param name="newPath">Path to the new file location.</param>
-        /// <param name="isPosix">if set to <see langword="true"/> then perform a posix rename.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="oldPath" /> is <see langword="null"/>. <para>-or-</para> or <paramref name="newPath" /> is <see langword="null"/>.</exception>
+        /// <param name="cancellationToken">The <see cref="CancellationToken"/> to observe.</param>
+        /// <returns>A <see cref="Task"/> that represents the asynchronous rename operation.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="oldPath"/> is <see langword="null"/>. <para>-or-</para> or <paramref name="newPath"/> is <see langword="null"/>.</exception>
         /// <exception cref="SshConnectionException">Client is not connected.</exception>
         /// <exception cref="SshConnectionException">Client is not connected.</exception>
         /// <exception cref="SftpPermissionDeniedException">Permission to rename the file was denied by the remote host. <para>-or-</para> A SSH command was denied by the server.</exception>
         /// <exception cref="SftpPermissionDeniedException">Permission to rename the file was denied by the remote host. <para>-or-</para> A SSH command was denied by the server.</exception>
-        /// <exception cref="SshException">A SSH error where <see cref="Exception.Message" /> is the message from the remote host.</exception>
+        /// <exception cref="SshException">A SSH error where <see cref="Exception.Message"/> is the message from the remote host.</exception>
         /// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
         /// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
-        void RenameFile(string oldPath, string newPath, bool isPosix);
+        Task RenameFileAsync(string oldPath, string newPath, CancellationToken cancellationToken);
 
 
         /// <summary>
         /// <summary>
         /// Sets the date and time the specified file was last accessed.
         /// Sets the date and time the specified file was last accessed.
@@ -951,7 +953,7 @@ namespace Renci.SshNet
         /// <param name="path">The file for which to set the date and time information.</param>
         /// <param name="path">The file for which to set the date and time information.</param>
         /// <param name="lastWriteTimeUtc">A <see cref="DateTime"/> containing the value to set for the last write date and time of path. This value is expressed in UTC time.</param>
         /// <param name="lastWriteTimeUtc">A <see cref="DateTime"/> containing the value to set for the last write date and time of path. This value is expressed in UTC time.</param>
         void SetLastWriteTimeUtc(string path, DateTime lastWriteTimeUtc);
         void SetLastWriteTimeUtc(string path, DateTime lastWriteTimeUtc);
-        
+
         /// <summary>
         /// <summary>
         /// Sets the specified <see cref="SftpFileAttributes"/> of the file on the specified path.
         /// Sets the specified <see cref="SftpFileAttributes"/> of the file on the specified path.
         /// </summary>
         /// </summary>
@@ -986,7 +988,7 @@ namespace Renci.SshNet
         /// <exception cref="ArgumentNullException"><paramref name="sourcePath"/> is <see langword="null"/>.</exception>
         /// <exception cref="ArgumentNullException"><paramref name="sourcePath"/> is <see langword="null"/>.</exception>
         /// <exception cref="ArgumentException"><paramref name="destinationPath"/> is <see langword="null"/> or contains only whitespace.</exception>
         /// <exception cref="ArgumentException"><paramref name="destinationPath"/> is <see langword="null"/> or contains only whitespace.</exception>
         /// <exception cref="SftpPathNotFoundException"><paramref name="destinationPath"/> was not found on the remote host.</exception>
         /// <exception cref="SftpPathNotFoundException"><paramref name="destinationPath"/> was not found on the remote host.</exception>
-        /// <exception cref="SshException">If a problem occurs while copying the file</exception>
+        /// <exception cref="SshException">If a problem occurs while copying the file.</exception>
         IEnumerable<FileInfo> SynchronizeDirectories(string sourcePath, string destinationPath, string searchPattern);
         IEnumerable<FileInfo> SynchronizeDirectories(string sourcePath, string destinationPath, string searchPattern);
 
 
         /// <summary>
         /// <summary>

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

@@ -13,7 +13,7 @@ namespace Renci.SshNet
         /// Gets or set the number of seconds to wait for an operation to complete.
         /// Gets or set the number of seconds to wait for an operation to complete.
         /// </summary>
         /// </summary>
         /// <value>
         /// <value>
-        /// The number of seconds to wait for an operation to complete, or -1 to wait indefinitely.
+        /// The number of seconds to wait for an operation to complete, or <c>-1</c> to wait indefinitely.
         /// </value>
         /// </value>
         int OperationTimeout { get; }
         int OperationTimeout { get; }
 
 
@@ -41,7 +41,7 @@ namespace Renci.SshNet
         /// Waits a specified time for a given <see cref="WaitHandle"/> to get signaled.
         /// Waits a specified time for a given <see cref="WaitHandle"/> to get signaled.
         /// </summary>
         /// </summary>
         /// <param name="waitHandle">The handle to wait for.</param>
         /// <param name="waitHandle">The handle to wait for.</param>
-        /// <param name="millisecondsTimeout">The number of millieseconds wait for <paramref name="waitHandle"/> to get signaled, or -1 to wait indefinitely.</param>
+        /// <param name="millisecondsTimeout">The number of millieseconds wait for <paramref name="waitHandle"/> to get signaled, or <c>-1</c> to wait indefinitely.</param>
         /// <exception cref="SshException">The connection was closed by the server.</exception>
         /// <exception cref="SshException">The connection was closed by the server.</exception>
         /// <exception cref="SshException">The channel was closed.</exception>
         /// <exception cref="SshException">The channel was closed.</exception>
         /// <exception cref="SshOperationTimeoutException">The handle did not get signaled within the specified timeout.</exception>
         /// <exception cref="SshOperationTimeoutException">The handle did not get signaled within the specified timeout.</exception>
@@ -52,7 +52,7 @@ namespace Renci.SshNet
         /// 32-bit signed integer to specify the time interval in milliseconds.
         /// 32-bit signed integer to specify the time interval in milliseconds.
         /// </summary>
         /// </summary>
         /// <param name="waitHandle">The handle to wait for.</param>
         /// <param name="waitHandle">The handle to wait for.</param>
-        /// <param name="millisecondsTimeout">To number of milliseconds to wait for <paramref name="waitHandle"/> to get signaled, or -1 to wait indefinitely.</param>
+        /// <param name="millisecondsTimeout">To number of milliseconds to wait for <paramref name="waitHandle"/> to get signaled, or <c>-1</c> to wait indefinitely.</param>
         /// <returns>
         /// <returns>
         /// <see langword="true"/> if <paramref name="waitHandle"/> received a signal within the specified timeout;
         /// <see langword="true"/> if <paramref name="waitHandle"/> received a signal within the specified timeout;
         /// otherwise, <see langword="false"/>.
         /// otherwise, <see langword="false"/>.
@@ -72,7 +72,7 @@ namespace Renci.SshNet
         /// </summary>
         /// </summary>
         /// <param name="waitHandleA">The first handle to wait for.</param>
         /// <param name="waitHandleA">The first handle to wait for.</param>
         /// <param name="waitHandleB">The second handle to wait for.</param>
         /// <param name="waitHandleB">The second handle to wait for.</param>
-        /// <param name="millisecondsTimeout">To number of milliseconds to wait for a <see cref="WaitHandle"/> to get signaled, or -1 to wait indefinitely.</param>
+        /// <param name="millisecondsTimeout">To number of milliseconds to wait for a <see cref="WaitHandle"/> to get signaled, or <c>-1</c> to wait indefinitely.</param>
         /// <returns>
         /// <returns>
         /// <c>0</c> if <paramref name="waitHandleA"/> received a signal within the specified timeout and <c>1</c>
         /// <c>0</c> if <paramref name="waitHandleA"/> received a signal within the specified timeout and <c>1</c>
         /// if <paramref name="waitHandleB"/> received a signal within the specified timeout, or <see cref="WaitHandle.WaitTimeout"/>
         /// if <paramref name="waitHandleB"/> received a signal within the specified timeout, or <see cref="WaitHandle.WaitTimeout"/>
@@ -98,7 +98,7 @@ namespace Renci.SshNet
         /// integer to specify the time interval.
         /// integer to specify the time interval.
         /// </summary>
         /// </summary>
         /// <param name="waitHandles">A <see cref="WaitHandle"/> array - constructed using <see cref="CreateWaitHandleArray(WaitHandle[])"/> - containing the objects to wait for.</param>
         /// <param name="waitHandles">A <see cref="WaitHandle"/> array - constructed using <see cref="CreateWaitHandleArray(WaitHandle[])"/> - containing the objects to wait for.</param>
-        /// <param name="millisecondsTimeout">To number of milliseconds to wait for a <see cref="WaitHandle"/> to get signaled, or -1 to wait indefinitely.</param>
+        /// <param name="millisecondsTimeout">To number of milliseconds to wait for a <see cref="WaitHandle"/> to get signaled, or <c>-1</c> to wait indefinitely.</param>
         /// <returns>
         /// <returns>
         /// The array index of the first non-system object that satisfied the wait.
         /// The array index of the first non-system object that satisfied the wait.
         /// </returns>
         /// </returns>

+ 2 - 1
src/Renci.SshNet/KeyboardInteractiveConnectionInfo.cs

@@ -134,12 +134,13 @@ namespace Renci.SshNet
                     kbdInteractive.AuthenticationPrompt += AuthenticationMethod_AuthenticationPrompt;
                     kbdInteractive.AuthenticationPrompt += AuthenticationMethod_AuthenticationPrompt;
                 }
                 }
             }
             }
-
         }
         }
 
 
         private void AuthenticationMethod_AuthenticationPrompt(object sender, AuthenticationPromptEventArgs e)
         private void AuthenticationMethod_AuthenticationPrompt(object sender, AuthenticationPromptEventArgs e)
         {
         {
+#pragma warning disable MA0091 // Sender should be 'this' for instance events
             AuthenticationPrompt?.Invoke(sender, e);
             AuthenticationPrompt?.Invoke(sender, e);
+#pragma warning restore MA0091 // Sender should be 'this' for instance events
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 7 - 1
src/Renci.SshNet/Messages/Authentication/FailureMessage.cs

@@ -25,7 +25,7 @@ namespace Renci.SshNet.Messages.Authentication
         /// Gets a value indicating whether authentication is partially successful.
         /// Gets a value indicating whether authentication is partially successful.
         /// </summary>
         /// </summary>
         /// <value>
         /// <value>
-        ///   <see langword="true"/> if partially successful; otherwise, <see langword="false"/>.
+        /// <see langword="true"/> if partially successful; otherwise, <see langword="false"/>.
         /// </value>
         /// </value>
         public bool PartialSuccess { get; private set; }
         public bool PartialSuccess { get; private set; }
 
 
@@ -38,7 +38,11 @@ namespace Renci.SshNet.Messages.Authentication
             PartialSuccess = ReadBoolean();
             PartialSuccess = ReadBoolean();
             if (PartialSuccess)
             if (PartialSuccess)
             {
             {
+#if NET || NETSTANDARD2_1_OR_GREATER
+                Message = string.Join(',', AllowedAuthentications);
+#else
                 Message = string.Join(",", AllowedAuthentications);
                 Message = string.Join(",", AllowedAuthentications);
+#endif // NET || NETSTANDARD2_1_OR_GREATER
             }
             }
         }
         }
 
 
@@ -47,7 +51,9 @@ namespace Renci.SshNet.Messages.Authentication
         /// </summary>
         /// </summary>
         protected override void SaveData()
         protected override void SaveData()
         {
         {
+#pragma warning disable MA0025 // Implement the functionality instead of throwing NotImplementedException
             throw new NotImplementedException();
             throw new NotImplementedException();
+#pragma warning restore MA0025 // Implement the functionality instead of throwing NotImplementedException
         }
         }
 
 
         internal override void Process(Session session)
         internal override void Process(Session session)

+ 2 - 1
src/Renci.SshNet/Messages/Authentication/InformationResponseMessage.cs

@@ -12,7 +12,7 @@ namespace Renci.SshNet.Messages.Authentication
         /// <summary>
         /// <summary>
         /// Gets authentication responses.
         /// Gets authentication responses.
         /// </summary>
         /// </summary>
-        public IList<string> Responses { get; private set; }
+        public List<string> Responses { get; private set; }
 
 
         /// <summary>
         /// <summary>
         /// Gets the size of the message in bytes.
         /// Gets the size of the message in bytes.
@@ -48,6 +48,7 @@ namespace Renci.SshNet.Messages.Authentication
         protected override void SaveData()
         protected override void SaveData()
         {
         {
             Write((uint) Responses.Count);
             Write((uint) Responses.Count);
+
             foreach (var response in Responses)
             foreach (var response in Responses)
             {
             {
                 Write(response);
                 Write(response);

+ 0 - 1
src/Renci.SshNet/Messages/Authentication/RequestMessage.cs

@@ -108,4 +108,3 @@ namespace Renci.SshNet.Messages.Authentication
         }
         }
     }
     }
 }
 }
-

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

@@ -6,7 +6,7 @@
     internal sealed class RequestMessageNone : RequestMessage
     internal sealed class RequestMessageNone : RequestMessage
     {
     {
         /// <summary>
         /// <summary>
-        /// Initializes a new instance of the <see cref="RequestMessagePassword"/> class.
+        /// Initializes a new instance of the <see cref="RequestMessageNone"/> class.
         /// </summary>
         /// </summary>
         /// <param name="serviceName">Name of the service.</param>
         /// <param name="serviceName">Name of the service.</param>
         /// <param name="username">Authentication username.</param>
         /// <param name="username">Authentication username.</param>

+ 0 - 1
src/Renci.SshNet/Messages/Connection/ChannelCloseMessage.cs

@@ -11,7 +11,6 @@
         /// </summary>
         /// </summary>
         public ChannelCloseMessage()
         public ChannelCloseMessage()
         {
         {
-
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 0 - 1
src/Renci.SshNet/Messages/Connection/ChannelEofMessage.cs

@@ -11,7 +11,6 @@
         /// </summary>
         /// </summary>
         public ChannelEofMessage()
         public ChannelEofMessage()
         {
         {
-
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 0 - 1
src/Renci.SshNet/Messages/Connection/ChannelFailureMessage.cs

@@ -11,7 +11,6 @@
         /// </summary>
         /// </summary>
         public ChannelFailureMessage()
         public ChannelFailureMessage()
         {
         {
-
         }
         }
 
 
         /// <summary>
         /// <summary>

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

@@ -3,7 +3,7 @@
 namespace Renci.SshNet.Messages.Connection
 namespace Renci.SshNet.Messages.Connection
 {
 {
     /// <summary>
     /// <summary>
-    /// Base class for open channel messages
+    /// Base class for open channel messages.
     /// </summary>
     /// </summary>
     public abstract class ChannelOpenInfo : SshData
     public abstract class ChannelOpenInfo : SshData
     {
     {

+ 2 - 2
src/Renci.SshNet/Messages/Connection/ChannelOpen/DirectTcpipChannelInfo.cs

@@ -3,7 +3,7 @@
 namespace Renci.SshNet.Messages.Connection
 namespace Renci.SshNet.Messages.Connection
 {
 {
     /// <summary>
     /// <summary>
-    /// Used to open "direct-tcpip" channel type
+    /// Used to open "direct-tcpip" channel type.
     /// </summary>
     /// </summary>
     internal sealed class DirectTcpipChannelInfo : ChannelOpenInfo
     internal sealed class DirectTcpipChannelInfo : ChannelOpenInfo
     {
     {
@@ -11,7 +11,7 @@ namespace Renci.SshNet.Messages.Connection
         private byte[] _originatorAddress;
         private byte[] _originatorAddress;
 
 
         /// <summary>
         /// <summary>
-        /// Specifies channel open type
+        /// Specifies channel open type.
         /// </summary>
         /// </summary>
         public const string NAME = "direct-tcpip";
         public const string NAME = "direct-tcpip";
 
 

+ 20 - 8
src/Renci.SshNet/Messages/Connection/ChannelOpen/ForwardedTcpipChannelInfo.cs

@@ -3,10 +3,15 @@
 namespace Renci.SshNet.Messages.Connection
 namespace Renci.SshNet.Messages.Connection
 {
 {
     /// <summary>
     /// <summary>
-    /// Used to open "forwarded-tcpip" channel type
+    /// Used to open "forwarded-tcpip" channel type.
     /// </summary>
     /// </summary>
     internal sealed class ForwardedTcpipChannelInfo : ChannelOpenInfo
     internal sealed class ForwardedTcpipChannelInfo : ChannelOpenInfo
     {
     {
+        /// <summary>
+        /// Specifies channel open type.
+        /// </summary>
+        public const string NAME = "forwarded-tcpip";
+
         private byte[] _connectedAddress;
         private byte[] _connectedAddress;
         private byte[] _originatorAddress;
         private byte[] _originatorAddress;
 
 
@@ -21,8 +26,8 @@ namespace Renci.SshNet.Messages.Connection
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Initializes a new <see cref="ForwardedTcpipChannelInfo"/> instance with the specified connector
-        /// address and port, and originator address and port.
+        /// Initializes a new instance of the <see cref="ForwardedTcpipChannelInfo"/> class with the
+        /// specified connector address and port, and originator address and port.
         /// </summary>
         /// </summary>
         public ForwardedTcpipChannelInfo(string connectedAddress, uint connectedPort, string originatorAddress, uint originatorPort)
         public ForwardedTcpipChannelInfo(string connectedAddress, uint connectedPort, string originatorAddress, uint originatorPort)
         {
         {
@@ -32,11 +37,6 @@ namespace Renci.SshNet.Messages.Connection
             OriginatorPort = originatorPort;
             OriginatorPort = originatorPort;
         }
         }
 
 
-        /// <summary>
-        /// Specifies channel open type
-        /// </summary>
-        public const string NAME = "forwarded-tcpip";
-
         /// <summary>
         /// <summary>
         /// Gets the type of the channel to open.
         /// Gets the type of the channel to open.
         /// </summary>
         /// </summary>
@@ -51,6 +51,9 @@ namespace Renci.SshNet.Messages.Connection
         /// <summary>
         /// <summary>
         /// Gets the connected address.
         /// Gets the connected address.
         /// </summary>
         /// </summary>
+        /// <value>
+        /// The connected address.
+        /// </value>
         public string ConnectedAddress
         public string ConnectedAddress
         {
         {
             get { return Utf8.GetString(_connectedAddress, 0, _connectedAddress.Length); }
             get { return Utf8.GetString(_connectedAddress, 0, _connectedAddress.Length); }
@@ -60,11 +63,17 @@ namespace Renci.SshNet.Messages.Connection
         /// <summary>
         /// <summary>
         /// Gets the connected port.
         /// Gets the connected port.
         /// </summary>
         /// </summary>
+        /// <value>
+        /// The connected port.
+        /// </value>
         public uint ConnectedPort { get; private set; }
         public uint ConnectedPort { get; private set; }
 
 
         /// <summary>
         /// <summary>
         /// Gets the originator address.
         /// Gets the originator address.
         /// </summary>
         /// </summary>
+        /// <value>
+        /// The originator address.
+        /// </value>
         public string OriginatorAddress
         public string OriginatorAddress
         {
         {
             get { return Utf8.GetString(_originatorAddress, 0, _originatorAddress.Length); }
             get { return Utf8.GetString(_originatorAddress, 0, _originatorAddress.Length); }
@@ -74,6 +83,9 @@ namespace Renci.SshNet.Messages.Connection
         /// <summary>
         /// <summary>
         /// Gets the originator port.
         /// Gets the originator port.
         /// </summary>
         /// </summary>
+        /// <value>
+        /// The originator port.
+        /// </value>
         public uint OriginatorPort { get; private set; }
         public uint OriginatorPort { get; private set; }
 
 
         /// <summary>
         /// <summary>

+ 2 - 2
src/Renci.SshNet/Messages/Connection/ChannelOpen/SessionChannelOpenInfo.cs

@@ -3,12 +3,12 @@
 namespace Renci.SshNet.Messages.Connection
 namespace Renci.SshNet.Messages.Connection
 {
 {
     /// <summary>
     /// <summary>
-    /// Used to open "session" channel type
+    /// Used to open "session" channel type.
     /// </summary>
     /// </summary>
     internal sealed class SessionChannelOpenInfo : ChannelOpenInfo
     internal sealed class SessionChannelOpenInfo : ChannelOpenInfo
     {
     {
         /// <summary>
         /// <summary>
-        /// Specifies channel open type
+        /// Specifies channel open type.
         /// </summary>
         /// </summary>
         public const string Name = "session";
         public const string Name = "session";
 
 

+ 2 - 2
src/Renci.SshNet/Messages/Connection/ChannelOpen/X11ChannelOpenInfo.cs

@@ -3,14 +3,14 @@
 namespace Renci.SshNet.Messages.Connection
 namespace Renci.SshNet.Messages.Connection
 {
 {
     /// <summary>
     /// <summary>
-    /// Used to open "x11" channel type
+    /// Used to open "x11" channel type.
     /// </summary>
     /// </summary>
     internal sealed class X11ChannelOpenInfo : ChannelOpenInfo
     internal sealed class X11ChannelOpenInfo : ChannelOpenInfo
     {
     {
         private byte[] _originatorAddress;
         private byte[] _originatorAddress;
 
 
         /// <summary>
         /// <summary>
-        /// Specifies channel open type
+        /// Specifies channel open type.
         /// </summary>
         /// </summary>
         public const string Name = "x11";
         public const string Name = "x11";
 
 

+ 0 - 1
src/Renci.SshNet/Messages/Connection/ChannelOpenFailureMessage.cs

@@ -62,7 +62,6 @@
         /// </summary>
         /// </summary>
         public ChannelOpenFailureMessage()
         public ChannelOpenFailureMessage()
         {
         {
-
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 7 - 4
src/Renci.SshNet/Messages/Connection/ChannelOpenFailureReasons.cs

@@ -6,19 +6,22 @@
     internal enum ChannelOpenFailureReasons : uint
     internal enum ChannelOpenFailureReasons : uint
     {
     {
         /// <summary>
         /// <summary>
-        /// SSH_OPEN_ADMINISTRATIVELY_PROHIBITED
+        /// SSH_OPEN_ADMINISTRATIVELY_PROHIBITED.
         /// </summary>
         /// </summary>
         AdministativelyProhibited = 1,
         AdministativelyProhibited = 1,
+
         /// <summary>
         /// <summary>
-        /// SSH_OPEN_CONNECT_FAILED
+        /// SSH_OPEN_CONNECT_FAILED.
         /// </summary>
         /// </summary>
         ConnectFailed = 2,
         ConnectFailed = 2,
+
         /// <summary>
         /// <summary>
-        /// SSH_OPEN_UNKNOWN_CHANNEL_TYPE
+        /// SSH_OPEN_UNKNOWN_CHANNEL_TYPE.
         /// </summary>
         /// </summary>
         UnknownChannelType = 3,
         UnknownChannelType = 3,
+
         /// <summary>
         /// <summary>
-        /// SSH_OPEN_RESOURCE_SHORTAGE
+        /// SSH_OPEN_RESOURCE_SHORTAGE.
         /// </summary>
         /// </summary>
         ResourceShortage = 4
         ResourceShortage = 4
     }
     }

+ 4 - 4
src/Renci.SshNet/Messages/Connection/ChannelRequest/BreakRequestInfo.cs

@@ -1,12 +1,12 @@
 namespace Renci.SshNet.Messages.Connection
 namespace Renci.SshNet.Messages.Connection
 {
 {
     /// <summary>
     /// <summary>
-    /// Represents "break" type channel request information
+    /// Represents "break" type channel request information.
     /// </summary>
     /// </summary>
     internal sealed class BreakRequestInfo : RequestInfo
     internal sealed class BreakRequestInfo : RequestInfo
     {
     {
         /// <summary>
         /// <summary>
-        /// Channel request name
+        /// Channel request name.
         /// </summary>
         /// </summary>
         public const string Name = "break";
         public const string Name = "break";
 
 
@@ -43,7 +43,7 @@
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Initializes a new instance of the <see cref="ExecRequestInfo"/> class.
+        /// Initializes a new instance of the <see cref="BreakRequestInfo"/> class.
         /// </summary>
         /// </summary>
         public BreakRequestInfo()
         public BreakRequestInfo()
         {
         {
@@ -51,7 +51,7 @@
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Initializes a new instance of the <see cref="ExecRequestInfo"/> class.
+        /// Initializes a new instance of the <see cref="BreakRequestInfo"/> class.
         /// </summary>
         /// </summary>
         /// <param name="breakLength">Length of the break.</param>
         /// <param name="breakLength">Length of the break.</param>
         public BreakRequestInfo(uint breakLength)
         public BreakRequestInfo(uint breakLength)

+ 5 - 2
src/Renci.SshNet/Messages/Connection/ChannelRequest/ChannelRequestMessage.cs

@@ -17,7 +17,10 @@
         /// </value>
         /// </value>
         public string RequestName
         public string RequestName
         {
         {
-            get { return _requestName; }
+            get
+            {
+                return _requestName;
+            }
             private set
             private set
             {
             {
                 _requestName = value;
                 _requestName = value;
@@ -53,7 +56,7 @@
         /// </summary>
         /// </summary>
         public ChannelRequestMessage()
         public ChannelRequestMessage()
         {
         {
-            //  Required for dynamically loading request type when it comes from the server
+            // Required for dynamically loading request type when it comes from the server
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 2 - 2
src/Renci.SshNet/Messages/Connection/ChannelRequest/EndOfWriteRequestInfo.cs

@@ -1,12 +1,12 @@
 namespace Renci.SshNet.Messages.Connection
 namespace Renci.SshNet.Messages.Connection
 {
 {
     /// <summary>
     /// <summary>
-    /// Represents "eow@openssh.com" type channel request information
+    /// Represents "eow@openssh.com" type channel request information.
     /// </summary>
     /// </summary>
     public class EndOfWriteRequestInfo : RequestInfo
     public class EndOfWriteRequestInfo : RequestInfo
     {
     {
         /// <summary>
         /// <summary>
-        /// Channel request name
+        /// Channel request name.
         /// </summary>
         /// </summary>
         public const string Name = "eow@openssh.com";
         public const string Name = "eow@openssh.com";
 
 

+ 4 - 4
src/Renci.SshNet/Messages/Connection/ChannelRequest/EnvironmentVariableRequestInfo.cs

@@ -1,7 +1,7 @@
 namespace Renci.SshNet.Messages.Connection
 namespace Renci.SshNet.Messages.Connection
 {
 {
     /// <summary>
     /// <summary>
-    /// Represents "env" type channel request information
+    /// Represents "env" type channel request information.
     /// </summary>
     /// </summary>
     internal sealed class EnvironmentVariableRequestInfo : RequestInfo
     internal sealed class EnvironmentVariableRequestInfo : RequestInfo
     {
     {
@@ -9,7 +9,7 @@
         private byte[] _variableValue;
         private byte[] _variableValue;
 
 
         /// <summary>
         /// <summary>
-        /// Channel request name
+        /// Channel request name.
         /// </summary>
         /// </summary>
         public const string Name = "env";
         public const string Name = "env";
 
 
@@ -25,7 +25,7 @@
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Gets or sets the name of the variable.
+        /// Gets the name of the variable.
         /// </summary>
         /// </summary>
         /// <value>
         /// <value>
         /// The name of the variable.
         /// The name of the variable.
@@ -36,7 +36,7 @@
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Gets or sets the variable value.
+        /// Gets the value of the variable.
         /// </summary>
         /// </summary>
         /// <value>
         /// <value>
         /// The variable value.
         /// The variable value.

+ 3 - 3
src/Renci.SshNet/Messages/Connection/ChannelRequest/ExitSignalRequestInfo.cs

@@ -1,7 +1,7 @@
 namespace Renci.SshNet.Messages.Connection
 namespace Renci.SshNet.Messages.Connection
 {
 {
     /// <summary>
     /// <summary>
-    /// Represents "exit-signal" type channel request information
+    /// Represents "exit-signal" type channel request information.
     /// </summary>
     /// </summary>
     internal sealed class ExitSignalRequestInfo : RequestInfo
     internal sealed class ExitSignalRequestInfo : RequestInfo
     {
     {
@@ -10,7 +10,7 @@
         private byte[] _language;
         private byte[] _language;
 
 
         /// <summary>
         /// <summary>
-        /// Channel request name
+        /// Channel request name.
         /// </summary>
         /// </summary>
         public const string Name = "exit-signal";
         public const string Name = "exit-signal";
 
 
@@ -41,7 +41,7 @@
         /// Gets a value indicating whether core is dumped.
         /// Gets a value indicating whether core is dumped.
         /// </summary>
         /// </summary>
         /// <value>
         /// <value>
-        ///   <see langword="true"/> if core is dumped; otherwise, <see langword="false"/>.
+        /// <see langword="true"/> if core is dumped; otherwise, <see langword="false"/>.
         /// </value>
         /// </value>
         public bool CoreDumped { get; private set; }
         public bool CoreDumped { get; private set; }
 
 

+ 2 - 2
src/Renci.SshNet/Messages/Connection/ChannelRequest/ExitStatusRequestInfo.cs

@@ -1,7 +1,7 @@
 namespace Renci.SshNet.Messages.Connection
 namespace Renci.SshNet.Messages.Connection
 {
 {
     /// <summary>
     /// <summary>
-    /// Represents "exit-status" type channel request information
+    /// Represents "exit-status" type channel request information.
     /// </summary>
     /// </summary>
     internal sealed class ExitStatusRequestInfo : RequestInfo
     internal sealed class ExitStatusRequestInfo : RequestInfo
     {
     {
@@ -30,7 +30,7 @@
         {
         {
             get
             get
             {
             {
-                 var capacity = base.BufferCapacity;
+                var capacity = base.BufferCapacity;
                 capacity += 4; // ExitStatus
                 capacity += 4; // ExitStatus
                 return capacity;
                 return capacity;
             }
             }

+ 3 - 3
src/Renci.SshNet/Messages/Connection/ChannelRequest/KeepAliveRequestInfo.cs

@@ -1,12 +1,12 @@
 namespace Renci.SshNet.Messages.Connection
 namespace Renci.SshNet.Messages.Connection
 {
 {
     /// <summary>
     /// <summary>
-    /// Represents "keepalive@openssh.com" type channel request information
+    /// Represents "keepalive@openssh.com" type channel request information.
     /// </summary>
     /// </summary>
     public class KeepAliveRequestInfo : RequestInfo
     public class KeepAliveRequestInfo : RequestInfo
     {
     {
         /// <summary>
         /// <summary>
-        /// Channel request name
+        /// Channel request name.
         /// </summary>
         /// </summary>
         public const string Name = "keepalive@openssh.com";
         public const string Name = "keepalive@openssh.com";
 
 
@@ -22,7 +22,7 @@
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Initializes a new instance of the <see cref="EndOfWriteRequestInfo"/> class.
+        /// Initializes a new instance of the <see cref="KeepAliveRequestInfo"/> class.
         /// </summary>
         /// </summary>
         public KeepAliveRequestInfo()
         public KeepAliveRequestInfo()
         {
         {

+ 1 - 1
src/Renci.SshNet/Messages/Connection/ChannelRequest/PseudoTerminalInfo.cs → src/Renci.SshNet/Messages/Connection/ChannelRequest/PseudoTerminalRequestInfo.cs

@@ -141,7 +141,7 @@ namespace Renci.SshNet.Messages.Connection
                 // write total length of encoded terminal modes, which is 1 bytes for the opcode / terminal mode
                 // write total length of encoded terminal modes, which is 1 bytes for the opcode / terminal mode
                 // and 4 bytes for the uint argument for each entry; the encoded terminal modes are terminated by
                 // and 4 bytes for the uint argument for each entry; the encoded terminal modes are terminated by
                 // opcode TTY_OP_END (which is 1 byte)
                 // opcode TTY_OP_END (which is 1 byte)
-                Write((uint) TerminalModeValues.Count*(1 + 4) + 1);
+                Write(((uint) TerminalModeValues.Count*(1 + 4)) + 1);
 
 
                 foreach (var item in TerminalModeValues)
                 foreach (var item in TerminalModeValues)
                 {
                 {

+ 1 - 1
src/Renci.SshNet/Messages/Connection/ChannelRequest/RequestInfo.cs

@@ -19,7 +19,7 @@ namespace Renci.SshNet.Messages.Connection
         /// Gets or sets a value indicating whether reply message is needed.
         /// Gets or sets a value indicating whether reply message is needed.
         /// </summary>
         /// </summary>
         /// <value>
         /// <value>
-        ///   <see langword="true"/> if reply message is needed; otherwise, <see langword="false"/>.
+        /// <see langword="true"/> if reply message is needed; otherwise, <see langword="false"/>.
         /// </value>
         /// </value>
         public bool WantReply { get; protected set; }
         public bool WantReply { get; protected set; }
 
 

+ 2 - 2
src/Renci.SshNet/Messages/Connection/ChannelRequest/ShellRequestInfo.cs

@@ -1,12 +1,12 @@
 namespace Renci.SshNet.Messages.Connection
 namespace Renci.SshNet.Messages.Connection
 {
 {
     /// <summary>
     /// <summary>
-    /// Represents "shell" type channel request information
+    /// Represents "shell" type channel request information.
     /// </summary>
     /// </summary>
     internal sealed class ShellRequestInfo : RequestInfo
     internal sealed class ShellRequestInfo : RequestInfo
     {
     {
         /// <summary>
         /// <summary>
-        /// Channel request name
+        /// Channel request name.
         /// </summary>
         /// </summary>
         public const string Name = "shell";
         public const string Name = "shell";
 
 

+ 1 - 1
src/Renci.SshNet/Messages/Connection/ChannelRequest/SignalRequestInfo.cs

@@ -1,7 +1,7 @@
 namespace Renci.SshNet.Messages.Connection
 namespace Renci.SshNet.Messages.Connection
 {
 {
     /// <summary>
     /// <summary>
-    /// Represents "signal" type channel request information
+    /// Represents "signal" type channel request information.
     /// </summary>
     /// </summary>
     internal sealed class SignalRequestInfo : RequestInfo
     internal sealed class SignalRequestInfo : RequestInfo
     {
     {

+ 2 - 2
src/Renci.SshNet/Messages/Connection/ChannelRequest/SubsystemRequestInfo.cs

@@ -1,14 +1,14 @@
 namespace Renci.SshNet.Messages.Connection
 namespace Renci.SshNet.Messages.Connection
 {
 {
     /// <summary>
     /// <summary>
-    /// Represents "subsystem" type channel request information
+    /// Represents "subsystem" type channel request information.
     /// </summary>
     /// </summary>
     internal sealed class SubsystemRequestInfo : RequestInfo
     internal sealed class SubsystemRequestInfo : RequestInfo
     {
     {
         private byte[] _subsystemName;
         private byte[] _subsystemName;
 
 
         /// <summary>
         /// <summary>
-        /// Channel request name
+        /// Channel request name.
         /// </summary>
         /// </summary>
         public const string Name = "subsystem";
         public const string Name = "subsystem";
 
 

+ 2 - 2
src/Renci.SshNet/Messages/Connection/ChannelRequest/WindowChangeRequestInfo.cs

@@ -1,12 +1,12 @@
 namespace Renci.SshNet.Messages.Connection
 namespace Renci.SshNet.Messages.Connection
 {
 {
     /// <summary>
     /// <summary>
-    /// Represents "window-change" type channel request information
+    /// Represents "window-change" type channel request information.
     /// </summary>
     /// </summary>
     internal sealed class WindowChangeRequestInfo : RequestInfo
     internal sealed class WindowChangeRequestInfo : RequestInfo
     {
     {
         /// <summary>
         /// <summary>
-        /// Channe request name
+        /// Channe request name.
         /// </summary>
         /// </summary>
         public const string Name = "window-change";
         public const string Name = "window-change";
 
 

+ 1 - 1
src/Renci.SshNet/Messages/Connection/ChannelRequest/X11ForwardingRequestInfo.cs

@@ -32,7 +32,7 @@
         public bool IsSingleConnection { get; set; }
         public bool IsSingleConnection { get; set; }
 
 
         /// <summary>
         /// <summary>
-        /// Gets or sets the authentication protocol.
+        /// Gets the authentication protocol.
         /// </summary>
         /// </summary>
         /// <value>
         /// <value>
         /// The authentication protocol.
         /// The authentication protocol.

+ 2 - 2
src/Renci.SshNet/Messages/Connection/ChannelRequest/XonXoffRequestInfo.cs

@@ -1,7 +1,7 @@
 namespace Renci.SshNet.Messages.Connection
 namespace Renci.SshNet.Messages.Connection
 {
 {
     /// <summary>
     /// <summary>
-    /// Represents "xon-xoff" type channel request information
+    /// Represents "xon-xoff" type channel request information.
     /// </summary>
     /// </summary>
     internal sealed class XonXoffRequestInfo : RequestInfo
     internal sealed class XonXoffRequestInfo : RequestInfo
     {
     {
@@ -25,7 +25,7 @@
         /// Gets or sets a value indicating whether client can do.
         /// Gets or sets a value indicating whether client can do.
         /// </summary>
         /// </summary>
         /// <value>
         /// <value>
-        ///   <see langword="true"/> if client can do; otherwise, <see langword="false"/>.
+        /// <see langword="true"/> if client can do; otherwise, <see langword="false"/>.
         /// </value>
         /// </value>
         public bool ClientCanDo { get; set; }
         public bool ClientCanDo { get; set; }
 
 

+ 0 - 1
src/Renci.SshNet/Messages/Connection/ChannelSuccessMessage.cs

@@ -11,7 +11,6 @@
         /// </summary>
         /// </summary>
         public ChannelSuccessMessage()
         public ChannelSuccessMessage()
         {
         {
-
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 1 - 1
src/Renci.SshNet/Messages/Connection/GlobalRequestMessage.cs

@@ -23,7 +23,7 @@
         /// Gets a value indicating whether message reply should be sent..
         /// Gets a value indicating whether message reply should be sent..
         /// </summary>
         /// </summary>
         /// <value>
         /// <value>
-        ///   <see langword="true"/> if message reply should be sent; otherwise, <see langword="false"/>.
+        /// <see langword="true"/> if message reply should be sent; otherwise, <see langword="false"/>.
         /// </value>
         /// </value>
         public bool WantReply { get; private set; }
         public bool WantReply { get; private set; }
 
 

+ 3 - 2
src/Renci.SshNet/Messages/Connection/GlobalRequestName.cs

@@ -6,11 +6,12 @@
     public enum GlobalRequestName
     public enum GlobalRequestName
     {
     {
         /// <summary>
         /// <summary>
-        /// tcpip-forward
+        /// tcpip-forward.
         /// </summary>
         /// </summary>
         TcpIpForward,
         TcpIpForward,
+
         /// <summary>
         /// <summary>
-        /// cancel-tcpip-forward
+        /// cancel-tcpip-forward.
         /// </summary>
         /// </summary>
         CancelTcpIpForward,
         CancelTcpIpForward,
     }
     }

+ 59 - 54
src/Renci.SshNet/Messages/Message.cs

@@ -8,7 +8,7 @@ using Renci.SshNet.Compression;
 namespace Renci.SshNet.Messages
 namespace Renci.SshNet.Messages
 {
 {
     /// <summary>
     /// <summary>
-    /// Base class for all SSH protocol messages
+    /// Base class for all SSH protocol messages.
     /// </summary>
     /// </summary>
     public abstract class Message : SshData
     public abstract class Message : SshData
     {
     {
@@ -29,6 +29,7 @@ namespace Renci.SshNet.Messages
         /// <summary>
         /// <summary>
         /// Writes the message to the specified <see cref="SshDataStream"/>.
         /// Writes the message to the specified <see cref="SshDataStream"/>.
         /// </summary>
         /// </summary>
+        /// <param name="stream">The <see cref="SshDataStream"/> to write the message to.</param>
         protected override void WriteBytes(SshDataStream stream)
         protected override void WriteBytes(SshDataStream stream)
         {
         {
             var enumerator = GetType().GetCustomAttributes<MessageAttribute>(inherit: true).GetEnumerator();
             var enumerator = GetType().GetCustomAttributes<MessageAttribute>(inherit: true).GetEnumerator();
@@ -55,58 +56,61 @@ namespace Renci.SshNet.Messages
 
 
             var messageLength = BufferCapacity;
             var messageLength = BufferCapacity;
 
 
-            SshDataStream sshDataStream;
-
             if (messageLength == -1 || compressor != null)
             if (messageLength == -1 || compressor != null)
             {
             {
-                sshDataStream = new SshDataStream(DefaultCapacity);
+                using (var sshDataStream = new SshDataStream(DefaultCapacity))
+                {
+                    // skip:
+                    // * 4 bytes for the outbound packet sequence
+                    // * 4 bytes for the packet data length
+                    // * one byte for the packet padding length
+                    _ = sshDataStream.Seek(outboundPacketSequenceSize + 4 + 1, SeekOrigin.Begin);
 
 
-                // skip:
-                // * 4 bytes for the outbound packet sequence
-                // * 4 bytes for the packet data length
-                // * one byte for the packet padding length
-                _ = sshDataStream.Seek(outboundPacketSequenceSize + 4 + 1, SeekOrigin.Begin);
+                    if (compressor != null)
+                    {
+                        // obtain uncompressed message payload
+                        using (var uncompressedDataStream = new SshDataStream(messageLength != -1 ? messageLength : DefaultCapacity))
+                        {
+                            WriteBytes(uncompressedDataStream);
 
 
-                if (compressor != null)
-                {
-                    // obtain uncompressed message payload
-                    var uncompressedDataStream = new SshDataStream(messageLength != -1 ? messageLength : DefaultCapacity);
-                    WriteBytes(uncompressedDataStream);
+                            // compress message payload
+                            var compressedMessageData = compressor.Compress(uncompressedDataStream.ToArray());
 
 
-                    // compress message payload
-                    var compressedMessageData = compressor.Compress(uncompressedDataStream.ToArray());
+                            // add compressed message payload
+                            sshDataStream.Write(compressedMessageData, 0, compressedMessageData.Length);
+                        }
+                    }
+                    else
+                    {
+                        // add message payload
+                        WriteBytes(sshDataStream);
+                    }
 
 
-                    // add compressed message payload
-                    sshDataStream.Write(compressedMessageData, 0, compressedMessageData.Length);
-                }
-                else
-                {
-                    // add message payload
-                    WriteBytes(sshDataStream);
-                }
+                    messageLength = (int) sshDataStream.Length - (outboundPacketSequenceSize + 4 + 1);
 
 
-                messageLength = (int) sshDataStream.Length - (outboundPacketSequenceSize + 4 + 1);
+                    var packetLength = messageLength + 4 + 1;
 
 
-                var packetLength = messageLength + 4 + 1;
+                    // determine the padding length
+                    var paddingLength = GetPaddingLength(paddingMultiplier, packetLength);
 
 
-                // determine the padding length
-                var paddingLength = GetPaddingLength(paddingMultiplier, packetLength);
+                    // add padding bytes
+                    var paddingBytes = new byte[paddingLength];
+                    CryptoAbstraction.GenerateRandom(paddingBytes);
+                    sshDataStream.Write(paddingBytes, 0, paddingLength);
 
 
-                // add padding bytes
-                var paddingBytes = new byte[paddingLength];
-                CryptoAbstraction.GenerateRandom(paddingBytes);
-                sshDataStream.Write(paddingBytes, 0, paddingLength);
+                    var packetDataLength = GetPacketDataLength(messageLength, paddingLength);
 
 
-                var packetDataLength = GetPacketDataLength(messageLength, paddingLength);
+                    // skip bytes for outbound packet sequence
+                    _ = sshDataStream.Seek(outboundPacketSequenceSize, SeekOrigin.Begin);
 
 
-                // skip bytes for outbound packet sequence
-                _ = sshDataStream.Seek(outboundPacketSequenceSize, SeekOrigin.Begin);
+                    // add packet data length
+                    sshDataStream.Write(packetDataLength);
 
 
-                // add packet data length
-                sshDataStream.Write(packetDataLength);
+                    // add packet padding length
+                    sshDataStream.WriteByte(paddingLength);
 
 
-                // add packet padding length
-                sshDataStream.WriteByte(paddingLength);
+                    return sshDataStream.ToArray();
+                }
             }
             }
             else
             else
             {
             {
@@ -118,27 +122,28 @@ namespace Renci.SshNet.Messages
                 var packetDataLength = GetPacketDataLength(messageLength, paddingLength);
                 var packetDataLength = GetPacketDataLength(messageLength, paddingLength);
 
 
                 // lets construct an SSH data stream of the exact size required
                 // lets construct an SSH data stream of the exact size required
-                sshDataStream = new SshDataStream(packetLength + paddingLength + outboundPacketSequenceSize);
+                using (var sshDataStream = new SshDataStream(packetLength + paddingLength + outboundPacketSequenceSize))
+                {
+                    // skip bytes for outbound packet sequenceSize
+                    _ = sshDataStream.Seek(outboundPacketSequenceSize, SeekOrigin.Begin);
 
 
-                // skip bytes for outbound packet sequenceSize
-                _ = sshDataStream.Seek(outboundPacketSequenceSize, SeekOrigin.Begin);
+                    // add packet data length
+                    sshDataStream.Write(packetDataLength);
 
 
-                // add packet data length
-                sshDataStream.Write(packetDataLength);
+                    // add packet padding length
+                    sshDataStream.WriteByte(paddingLength);
 
 
-                // add packet padding length
-                sshDataStream.WriteByte(paddingLength);
+                    // add message payload
+                    WriteBytes(sshDataStream);
 
 
-                // add message payload
-                WriteBytes(sshDataStream);
+                    // add padding bytes
+                    var paddingBytes = new byte[paddingLength];
+                    CryptoAbstraction.GenerateRandom(paddingBytes);
+                    sshDataStream.Write(paddingBytes, 0, paddingLength);
 
 
-                // add padding bytes
-                var paddingBytes = new byte[paddingLength];
-                CryptoAbstraction.GenerateRandom(paddingBytes);
-                sshDataStream.Write(paddingBytes, 0, paddingLength);
+                    return sshDataStream.ToArray();
+                }
             }
             }
-
-            return sshDataStream.ToArray();
         }
         }
 
 
         private static uint GetPacketDataLength(int messageLength, byte paddingLength)
         private static uint GetPacketDataLength(int messageLength, byte paddingLength)

+ 4 - 5
src/Renci.SshNet/Messages/MessageAttribute.cs

@@ -2,7 +2,6 @@
 
 
 namespace Renci.SshNet.Messages
 namespace Renci.SshNet.Messages
 {
 {
-
     /// <summary>
     /// <summary>
     /// Indicates that a class represents SSH message. This class cannot be inherited.
     /// Indicates that a class represents SSH message. This class cannot be inherited.
     /// </summary>
     /// </summary>
@@ -10,20 +9,20 @@ namespace Renci.SshNet.Messages
     public sealed class MessageAttribute : Attribute
     public sealed class MessageAttribute : Attribute
     {
     {
         /// <summary>
         /// <summary>
-        /// Gets or sets message name as defined in RFC 4250.
+        /// Gets the message name as defined in RFC 4250.
         /// </summary>
         /// </summary>
         /// <value>
         /// <value>
         /// The name.
         /// The name.
         /// </value>
         /// </value>
-        public string Name { get; set; }
+        public string Name { get; }
 
 
         /// <summary>
         /// <summary>
-        /// Gets or sets message number as defined in RFC 4250.
+        /// Gets the message number as defined in RFC 4250.
         /// </summary>
         /// </summary>
         /// <value>
         /// <value>
         /// The number.
         /// The number.
         /// </value>
         /// </value>
-        public byte Number { get; set; }
+        public byte Number { get; }
 
 
         /// <summary>
         /// <summary>
         /// Initializes a new instance of the <see cref="MessageAttribute"/> class.
         /// Initializes a new instance of the <see cref="MessageAttribute"/> class.

+ 3 - 3
src/Renci.SshNet/Messages/ServiceName.cs

@@ -1,17 +1,17 @@
 namespace Renci.SshNet.Messages
 namespace Renci.SshNet.Messages
 {
 {
     /// <summary>
     /// <summary>
-    /// Specifies list of supported services
+    /// Specifies list of supported services.
     /// </summary>
     /// </summary>
     public enum ServiceName
     public enum ServiceName
     {
     {
         /// <summary>
         /// <summary>
-        /// ssh-userauth
+        /// ssh-userauth.
         /// </summary>
         /// </summary>
         UserAuthentication,
         UserAuthentication,
 
 
         /// <summary>
         /// <summary>
-        /// ssh-connection
+        /// ssh-connection.
         /// </summary>
         /// </summary>
         Connection
         Connection
     }
     }

+ 1 - 1
src/Renci.SshNet/Messages/Transport/DebugMessage.cs

@@ -13,7 +13,7 @@
         /// Gets a value indicating whether the message to be always displayed.
         /// Gets a value indicating whether the message to be always displayed.
         /// </summary>
         /// </summary>
         /// <value>
         /// <value>
-        /// 	<see langword="true"/> if the message always to be displayed; otherwise, <see langword="false"/>.
+        /// <see langword="true"/> if the message always to be displayed; otherwise, <see langword="false"/>.
         /// </value>
         /// </value>
         public bool IsAlwaysDisplay { get; private set; }
         public bool IsAlwaysDisplay { get; private set; }
 
 

+ 33 - 16
src/Renci.SshNet/Messages/Transport/DisconnectReason.cs

@@ -9,65 +9,82 @@
         /// Disconnect reason is not provided.
         /// Disconnect reason is not provided.
         /// </summary>
         /// </summary>
         None = 0,
         None = 0,
+
         /// <summary>
         /// <summary>
-        /// SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT
+        /// SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT.
         /// </summary>
         /// </summary>
         HostNotAllowedToConnect = 1,
         HostNotAllowedToConnect = 1,
+
         /// <summary>
         /// <summary>
-        /// SSH_DISCONNECT_PROTOCOL_ERROR
+        /// SSH_DISCONNECT_PROTOCOL_ERROR.
         /// </summary>
         /// </summary>
         ProtocolError = 2,
         ProtocolError = 2,
+
         /// <summary>
         /// <summary>
-        /// SSH_DISCONNECT_KEY_EXCHANGE_FAILED
+        /// SSH_DISCONNECT_KEY_EXCHANGE_FAILED.
         /// </summary>
         /// </summary>
         KeyExchangeFailed = 3,
         KeyExchangeFailed = 3,
+
         /// <summary>
         /// <summary>
-        /// SSH_DISCONNECT_RESERVED
+        /// SSH_DISCONNECT_RESERVED.
         /// </summary>
         /// </summary>
+#pragma warning disable CA1700 // Do not name enum values 'Reserved'
         Reserved = 4,
         Reserved = 4,
+#pragma warning restore CA1700 // Do not name enum values 'Reserved'
+
         /// <summary>
         /// <summary>
-        /// SSH_DISCONNECT_MAC_ERROR
+        /// SSH_DISCONNECT_MAC_ERROR.
         /// </summary>
         /// </summary>
         MacError = 5,
         MacError = 5,
+
         /// <summary>
         /// <summary>
-        /// SSH_DISCONNECT_COMPRESSION_ERROR
+        /// SSH_DISCONNECT_COMPRESSION_ERROR.
         /// </summary>
         /// </summary>
         CompressionError = 6,
         CompressionError = 6,
+
         /// <summary>
         /// <summary>
-        /// SSH_DISCONNECT_SERVICE_NOT_AVAILABLE
+        /// SSH_DISCONNECT_SERVICE_NOT_AVAILABLE.
         /// </summary>
         /// </summary>
         ServiceNotAvailable = 7,
         ServiceNotAvailable = 7,
+
         /// <summary>
         /// <summary>
-        /// SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED
+        /// SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED.
         /// </summary>
         /// </summary>
         ProtocolVersionNotSupported = 8,
         ProtocolVersionNotSupported = 8,
+
         /// <summary>
         /// <summary>
-        /// SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE
+        /// SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE.
         /// </summary>
         /// </summary>
         HostKeyNotVerifiable = 9,
         HostKeyNotVerifiable = 9,
+
         /// <summary>
         /// <summary>
-        /// SSH_DISCONNECT_CONNECTION_LOST
+        /// SSH_DISCONNECT_CONNECTION_LOST.
         /// </summary>
         /// </summary>
         ConnectionLost = 10,
         ConnectionLost = 10,
+
         /// <summary>
         /// <summary>
-        /// SSH_DISCONNECT_BY_APPLICATION
+        /// SSH_DISCONNECT_BY_APPLICATION.
         /// </summary>
         /// </summary>
         ByApplication = 11,
         ByApplication = 11,
+
         /// <summary>
         /// <summary>
-        /// SSH_DISCONNECT_TOO_MANY_CONNECTIONS
+        /// SSH_DISCONNECT_TOO_MANY_CONNECTIONS.
         /// </summary>
         /// </summary>
         TooManyConnections = 12,
         TooManyConnections = 12,
+
         /// <summary>
         /// <summary>
-        /// SSH_DISCONNECT_AUTH_CANCELLED_BY_USER
+        /// SSH_DISCONNECT_AUTH_CANCELLED_BY_USER.
         /// </summary>
         /// </summary>
         AuthenticationCanceledByUser = 13,
         AuthenticationCanceledByUser = 13,
+
         /// <summary>
         /// <summary>
-        /// SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE
+        /// SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE.
         /// </summary>
         /// </summary>
         NoMoreAuthenticationMethodsAvailable = 14,
         NoMoreAuthenticationMethodsAvailable = 14,
+
         /// <summary>
         /// <summary>
-        /// SSH_DISCONNECT_ILLEGAL_USER_NAME
+        /// SSH_DISCONNECT_ILLEGAL_USER_NAME.
         /// </summary>
         /// </summary>
-        IllegalUserName = 15,
+        IllegalUserName = 15
     }
     }
 }
 }

+ 3 - 1
src/Renci.SshNet/Messages/Transport/IKeyExchangedAllowed.cs

@@ -1,9 +1,11 @@
 namespace Renci.SshNet.Messages.Transport
 namespace Renci.SshNet.Messages.Transport
 {
 {
     /// <summary>
     /// <summary>
-    /// Indicates that message that implement this interface is allowed during key exchange phase
+    /// Indicates that message that implement this interface is allowed during key exchange phase.
     /// </summary>
     /// </summary>
+#pragma warning disable CA1040 // Avoid empty interfaces
     public interface IKeyExchangedAllowed
     public interface IKeyExchangedAllowed
+#pragma warning restore CA1040 // Avoid empty interfaces
     {
     {
     }
     }
 }
 }

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio