2
0
Эх сурвалжийг харах

Add ZlibStream and refactor compression related code for fufutre zlib support.

olegkap_cp 14 жил өмнө
parent
commit
8680a84416

+ 57 - 3
Renci.SshClient/Local.testsettings

@@ -1,10 +1,64 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <TestSettings name="Local" id="87bdbcdb-d02e-4dbe-a98f-b42f48afe198" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
   <Description>These are default test settings for a local test run.</Description>
-  <Deployment enabled="false" />
   <Execution>
-    <TestTypeSpecific />
-    <AgentRule name="Execution Agents">
+    <TestTypeSpecific>
+      <UnitTestRunConfig testTypeId="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b">
+        <AssemblyResolution>
+          <TestDirectory useLoadContext="true" />
+        </AssemblyResolution>
+      </UnitTestRunConfig>
+      <WebTestRunConfiguration testTypeId="4e7599fa-5ecb-43e9-a887-cd63cf72d207">
+        <Browser name="Internet Explorer 7.0">
+          <Headers>
+            <Header name="User-Agent" value="Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)" />
+            <Header name="Accept" value="*/*" />
+            <Header name="Accept-Language" value="{{$IEAcceptLanguage}}" />
+            <Header name="Accept-Encoding" value="GZIP" />
+          </Headers>
+        </Browser>
+      </WebTestRunConfiguration>
+    </TestTypeSpecific>
+    <AgentRule name="LocalMachineDefaultRole">
+      <DataCollectors>
+        <DataCollector uri="datacollector://microsoft/CodeCoverage/1.0" assemblyQualifiedName="Microsoft.VisualStudio.TestTools.CodeCoverage.CoveragePlugIn, Microsoft.VisualStudio.QualityTools.Plugins.CodeCoverage, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" friendlyName="Code Coverage">
+          <Configuration>
+            <CodeCoverage xmlns="">
+              <Regular>
+                <CodeCoverageItem binaryFile="Renci.SshNet\bin\Debug\Renci.SshNet.dll" pdbFile="Renci.SshNet\bin\Debug\Renci.SshNet.pdb" instrumentInPlace="true" />
+              </Regular>
+            </CodeCoverage>
+          </Configuration>
+        </DataCollector>
+        <DataCollector uri="datacollector://microsoft/TestImpact/1.0" assemblyQualifiedName="Microsoft.VisualStudio.TraceCollector.TestImpactDataCollector, Microsoft.VisualStudio.TraceCollector, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" friendlyName="Test Impact">
+          <Configuration>
+            <WorkerProcessList xmlns="">
+              <WorkerProcess>w3wp.exe</WorkerProcess>
+            </WorkerProcessList>
+            <MaximumConcurrentTests xmlns="">32</MaximumConcurrentTests>
+            <InstrumentIIS xmlns="">False</InstrumentIIS>
+            <RemoteInstrumentIIS xmlns="">False</RemoteInstrumentIIS>
+            <ProcessList IsExclusionList="True" xmlns="">
+              <Process>devenv.exe</Process>
+              <Process>mtm.exe</Process>
+              <Process>TestAgentConfigUI.exe</Process>
+              <Process>TestControllerConfigUI.exe</Process>
+              <Process>DW20.exe</Process>
+              <Process>TFSMgmt.exe</Process>
+              <Process>TFSJobAgent.exe</Process>
+              <Process>TFSBuildServiceHost.exe</Process>
+            </ProcessList>
+            <ModuleList IsExclusionList="True" xmlns="">
+              <Module>PublicKeyToken:B77A5C561934E089</Module>
+              <Module>PublicKeyToken:B03F5F7F11D50A3A</Module>
+              <Module>PublicKeyToken:31BF3856AD364E35</Module>
+              <Module>PublicKeyToken:89845DCD8080CC91</Module>
+              <Module>PublicKeyToken:71E9BCE111E9429C</Module>
+              <Module>Microsoft.</Module>
+            </ModuleList>
+          </Configuration>
+        </DataCollector>
+      </DataCollectors>
     </AgentRule>
   </Execution>
 </TestSettings>

+ 6 - 0
Renci.SshClient/Renci.SshNet.NET35/Renci.SshNet.NET35.csproj

@@ -169,6 +169,9 @@
     <Compile Include="..\Renci.SshNet\Common\SshPassPhraseNullOrEmptyException.NET40.cs">
       <Link>Common\SshPassPhraseNullOrEmptyException.NET40.cs</Link>
     </Compile>
+    <Compile Include="..\Renci.SshNet\Compression\CompressionMode.cs">
+      <Link>Compression\CompressionMode.cs</Link>
+    </Compile>
     <Compile Include="..\Renci.SshNet\Compression\Compressor.cs">
       <Link>Compression\Compressor.cs</Link>
     </Compile>
@@ -178,6 +181,9 @@
     <Compile Include="..\Renci.SshNet\Compression\ZlibOpenSsh.cs">
       <Link>Compression\ZlibOpenSsh.cs</Link>
     </Compile>
+    <Compile Include="..\Renci.SshNet\Compression\ZlibStream.cs">
+      <Link>Compression\ZlibStream.cs</Link>
+    </Compile>
     <Compile Include="..\Renci.SshNet\ConnectionInfo.cs">
       <Link>ConnectionInfo.cs</Link>
     </Compile>

+ 7 - 1
Renci.SshClient/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj

@@ -162,6 +162,9 @@
     <Compile Include="..\Renci.SshNet\Common\SshPassPhraseNullOrEmptyException.cs">
       <Link>Common\SshPassPhraseNullOrEmptyException.cs</Link>
     </Compile>
+    <Compile Include="..\Renci.SshNet\Compression\CompressionMode.cs">
+      <Link>Compression\CompressionMode.cs</Link>
+    </Compile>
     <Compile Include="..\Renci.SshNet\Compression\Compressor.cs">
       <Link>Compression\Compressor.cs</Link>
     </Compile>
@@ -171,6 +174,9 @@
     <Compile Include="..\Renci.SshNet\Compression\ZlibOpenSsh.cs">
       <Link>Compression\ZlibOpenSsh.cs</Link>
     </Compile>
+    <Compile Include="..\Renci.SshNet\Compression\ZlibStream.cs">
+      <Link>Compression\ZlibStream.cs</Link>
+    </Compile>
     <Compile Include="..\Renci.SshNet\ConnectionInfo.cs">
       <Link>ConnectionInfo.cs</Link>
     </Compile>
@@ -682,7 +688,7 @@
       <FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}">
         <SilverlightProjectProperties />
       </FlavorProperties>
-      <UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" />
+      <UserProperties ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
     </VisualStudio>
   </ProjectExtensions>
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

+ 7 - 1
Renci.SshClient/Renci.SshNet.WindowsPhone/Renci.SshNet.WindowsPhone.csproj

@@ -158,6 +158,9 @@
     <Compile Include="..\Renci.SshNet\Common\SshPassPhraseNullOrEmptyException.cs">
       <Link>Common\SshPassPhraseNullOrEmptyException.cs</Link>
     </Compile>
+    <Compile Include="..\Renci.SshNet\Compression\CompressionMode.cs">
+      <Link>Compression\CompressionMode.cs</Link>
+    </Compile>
     <Compile Include="..\Renci.SshNet\Compression\Compressor.cs">
       <Link>Compression\Compressor.cs</Link>
     </Compile>
@@ -167,6 +170,9 @@
     <Compile Include="..\Renci.SshNet\Compression\ZlibOpenSsh.cs">
       <Link>Compression\ZlibOpenSsh.cs</Link>
     </Compile>
+    <Compile Include="..\Renci.SshNet\Compression\ZlibStream.cs">
+      <Link>Compression\ZlibStream.cs</Link>
+    </Compile>
     <Compile Include="..\Renci.SshNet\ConnectionInfo.cs">
       <Link>ConnectionInfo.cs</Link>
     </Compile>
@@ -684,7 +690,7 @@
   <Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight for Phone\$(TargetFrameworkVersion)\Microsoft.Silverlight.CSharp.targets" />
   <ProjectExtensions>
     <VisualStudio>
-      <UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="77C294BB-1DC2-49DC-BE16-963F8F22794D" />
+      <UserProperties ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
     </VisualStudio>
   </ProjectExtensions>
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

+ 8 - 0
Renci.SshClient/Renci.SshNet/Compression/CompressionMode.cs

@@ -0,0 +1,8 @@
+namespace Renci.SshNet.Compression
+{
+    public enum CompressionMode
+    {
+        Compress = 0,
+        Decompress = 1,
+    }
+}

+ 116 - 3
Renci.SshClient/Renci.SshNet/Compression/Compressor.cs

@@ -1,17 +1,46 @@
 using System.Collections.Generic;
 using Renci.SshNet.Security;
+using System.IO;
+using System;
+
 namespace Renci.SshNet.Compression
 {
     /// <summary>
     /// Represents base class for compression algorithm implementation
     /// </summary>
-    public abstract class Compressor : Algorithm
+    public abstract class Compressor : Algorithm, IDisposable
     {
+        private readonly ZlibStream _compressor;
+        private readonly ZlibStream _decompressor;
+
+        private MemoryStream _compressorStream;
+        private MemoryStream _decompressorStream;
+
+        /// <summary>
+        /// Gets or sets a value indicating whether compression is active.
+        /// </summary>
+        /// <value>
+        ///   <c>true</c> if compression is active; otherwise, <c>false</c>.
+        /// </value>
+        protected bool IsActive { get; set; }
+
         /// <summary>
         /// Gets the session.
         /// </summary>
         protected Session Session { get; private set; }
 
+        /// <summary>
+        /// Initializes a new instance of the <see cref="Compressor"/> class.
+        /// </summary>
+        public Compressor()
+        {
+            this._compressorStream = new MemoryStream();
+            this._decompressorStream = new MemoryStream();
+
+            this._compressor = new ZlibStream(this._compressorStream, CompressionMode.Compress);
+            this._decompressor = new ZlibStream(this._decompressorStream, CompressionMode.Decompress);
+        }
+
         /// <summary>
         /// Initializes the algorithm
         /// </summary>
@@ -26,13 +55,97 @@ namespace Renci.SshNet.Compression
         /// </summary>
         /// <param name="data">Data to compress.</param>
         /// <returns>Compressed data</returns>
-        public abstract byte[] Compress(byte[] data);
+        public virtual byte[] Compress(byte[] data)
+        {
+            if (!this.IsActive)
+            {
+                return data;
+            }
+
+            this._compressorStream.SetLength(0);
+
+            this._compressor.Write(data, 0, data.Length);
+
+            return this._compressorStream.ToArray();
+        }
 
         /// <summary>
         /// Decompresses the specified data.
         /// </summary>
         /// <param name="data">Compressed data.</param>
         /// <returns>Decompressed data.</returns>
-        public abstract byte[] Decompress(byte[] data);
+        public virtual byte[] Decompress(byte[] data)
+        {
+            if (!this.IsActive)
+            {
+                return data;
+            }
+
+            this._decompressorStream.SetLength(0);
+
+            this._decompressor.Write(data, 0, data.Length);
+
+            return this._decompressorStream.ToArray();
+        }
+
+        #region IDisposable Members
+
+        private bool _isDisposed = false;
+
+        /// <summary>
+        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
+        /// </summary>
+        public void Dispose()
+        {
+            Dispose(true);
+
+            GC.SuppressFinalize(this);
+        }
+
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources
+        /// </summary>
+        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged ResourceMessages.</param>
+        protected virtual void Dispose(bool disposing)
+        {
+            // Check to see if Dispose has already been called.
+            if (!this._isDisposed)
+            {
+                // If disposing equals true, dispose all managed
+                // and unmanaged ResourceMessages.
+                if (disposing)
+                {
+                    // Dispose managed ResourceMessages.
+                    if (this._compressorStream != null)
+                    {
+                        this._compressorStream.Dispose();
+                        this._compressorStream = null;
+                    }
+
+                    if (this._decompressorStream != null)
+                    {
+                        this._decompressorStream.Dispose();
+                        this._decompressorStream = null;
+                    }
+                }
+
+                // Note disposing has been done.
+                this._isDisposed = true;
+            }
+        }
+
+        /// <summary>
+        /// Releases unmanaged resources and performs other cleanup operations before the
+        /// <see cref="SshCommand"/> is reclaimed by garbage collection.
+        /// </summary>
+        ~Compressor()
+        {
+            // Do not re-create Dispose clean-up code here.
+            // Calling Dispose(false) is optimal in terms of
+            // readability and maintainability.
+            Dispose(false);
+        }
+
+        #endregion
     }
 }

+ 2 - 44
Renci.SshClient/Renci.SshNet/Compression/Zlib.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.IO;
 
 namespace Renci.SshNet.Compression
 {
@@ -8,8 +9,6 @@ namespace Renci.SshNet.Compression
     /// </summary>
     internal class Zlib : Compressor
     {
-        private bool _active;
-
         /// <summary>
         /// Gets algorithm name.
         /// </summary>
@@ -25,48 +24,7 @@ namespace Renci.SshNet.Compression
         public override void Init(Session session)
         {
             base.Init(session);
-
-            session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
-        }
-
-        private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs<Messages.Authentication.SuccessMessage> e)
-        {
-            this._active = true;
-            this.Session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
-        }
-
-        /// <summary>
-        /// Compresses the specified data.
-        /// </summary>
-        /// <param name="data">Data to compress.</param>
-        /// <returns>
-        /// Compressed data
-        /// </returns>
-        public override byte[] Compress(byte[] data)
-        {
-            if (!this._active)
-            {
-                return data;
-            }
-
-            throw new NotImplementedException();
-        }
-
-        /// <summary>
-        /// Decompresses the specified data.
-        /// </summary>
-        /// <param name="data">Compressed data.</param>
-        /// <returns>
-        /// Decompressed data.
-        /// </returns>
-        public override byte[] Decompress(byte[] data)
-        {
-            if (!this._active)
-            {
-                return data;
-            }
-
-            throw new NotImplementedException();
+            this.IsActive = true;
         }
     }
 }

+ 3 - 76
Renci.SshClient/Renci.SshNet/Compression/ZlibOpenSsh.cs

@@ -1,15 +1,14 @@
 using System;
 using System.Collections.Generic;
+using System.IO;
 
 namespace Renci.SshNet.Compression
 {
     /// <summary>
     /// Represents "zlib@openssh.org" compression implementation
     /// </summary>
-    internal class ZlibOpenSsh : Compressor
+    public class ZlibOpenSsh : Compressor
     {
-        private bool _active;
-
         /// <summary>
         /// Gets algorithm name.
         /// </summary>
@@ -31,80 +30,8 @@ namespace Renci.SshNet.Compression
 
         private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs<Messages.Authentication.SuccessMessage> e)
         {
-            this._active = true;
+            this.IsActive = true;
             this.Session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
         }
-
-        /// <summary>
-        /// Compresses the specified data.
-        /// </summary>
-        /// <param name="data">Data to compress.</param>
-        /// <returns>
-        /// Compressed data
-        /// </returns>
-        public override byte[] Compress(byte[] data)
-        {
-            if (!this._active)
-            {
-                return data;
-            }
-            throw new NotImplementedException();
-
-            //using (var output = new MemoryStream())
-            //{
-            //    using (var input = new MemoryStream(data.ToArray()))
-            //    using (var compress = new DeflateStream(output, CompressionMode.Compress))
-            //    {
-            //        compress.FlushMode = FlushType.Partial;
-
-            //        input.CopyTo(compress);
-
-            //        var result = new List<byte>();
-
-            //        result.Add(0x78);
-            //        result.Add(0x9c);
-
-            //        result.AddRange(output.ToArray());
-
-            //        return result;
-            //    }
-            //}
-        }
-
-        /// <summary>
-        /// Decompresses the specified data.
-        /// </summary>
-        /// <param name="data">Compressed data.</param>
-        /// <returns>
-        /// Decompressed data.
-        /// </returns>
-        public override byte[] Decompress(byte[] data)
-        {
-            if (!this._active)
-            {
-                return data;
-            }
-
-            throw new NotImplementedException();
-
-            //Create the decompressed file.
-            //using (var output = new MemoryStream())
-            //{
-            //    using (var input = new MemoryStream(data.ToArray()))
-            //    {
-            //        input.ReadByte();
-            //        input.ReadByte();
-
-            //        using (var decompress = new DeflateStream(input, CompressionMode.Decompress))
-            //        {
-            //            // Copy the decompression stream 
-            //            // into the output file.
-            //            decompress.CopyTo(output);
-            //        }
-            //    }
-
-            //    return output.ToArray();
-            //}
-        }
     }
 }

+ 35 - 0
Renci.SshClient/Renci.SshNet/Compression/ZlibStream.cs

@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+    public class ZlibStream
+    {
+        //private readonly Ionic.Zlib.ZlibStream _baseStream;
+
+        public ZlibStream(Stream stream, CompressionMode mode)
+        {
+            //switch (mode)
+            //{
+            //    case CompressionMode.Compress:
+            //        this._baseStream = new Ionic.Zlib.ZlibStream(stream, Ionic.Zlib.CompressionMode.Compress, Ionic.Zlib.CompressionLevel.Default);
+            //        break;
+            //    case CompressionMode.Decompress:
+            //        this._baseStream = new Ionic.Zlib.ZlibStream(stream, Ionic.Zlib.CompressionMode.Decompress, Ionic.Zlib.CompressionLevel.Default);
+            //        break;
+            //    default:
+            //        break;
+            //}
+
+            //this._baseStream.FlushMode = Ionic.Zlib.FlushType.Partial;
+        }
+
+        public void Write(byte[] buffer, int offset, int count)
+        {
+            //this._baseStream.Write(buffer, offset, count);
+        }
+    }
+}

+ 2 - 2
Renci.SshClient/Renci.SshNet/ConnectionInfo.cs

@@ -203,8 +203,8 @@ namespace Renci.SshNet
 
             this.CompressionAlgorithms = new Dictionary<string, Type>()
             {
-                {"none", null}, 
-                {"zlib", typeof(Zlib)}, 
+                //{"none", null}, 
+                //{"zlib", typeof(Zlib)}, 
                 {"zlib@openssh.com", typeof(ZlibOpenSsh)}, 
             };
 

+ 4 - 1
Renci.SshClient/Renci.SshNet/Renci.SshNet.csproj

@@ -116,9 +116,13 @@
     <Compile Include="Common\SshOperationTimeoutException.NET40.cs" />
     <Compile Include="Common\SshPassPhraseNullOrEmptyException.cs" />
     <Compile Include="Common\SshPassPhraseNullOrEmptyException.NET40.cs" />
+    <Compile Include="Compression\CompressionMode.cs" />
     <Compile Include="Compression\Compressor.cs" />
     <Compile Include="Compression\Zlib.cs" />
     <Compile Include="Compression\ZlibOpenSsh.cs" />
+    <Compile Include="Compression\ZlibStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="ConnectionInfo.cs">
       <SubType>Code</SubType>
     </Compile>
@@ -394,7 +398,6 @@
   <ItemGroup>
     <Content Include="Documentation\SshClient.shfbproj" />
   </ItemGroup>
-  <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.