diff --git a/.circleci/checksum.txt b/.circleci/checksum.txt index 5d4b569c0..9b522fb67 100644 --- a/.circleci/checksum.txt +++ b/.circleci/checksum.txt @@ -1,13 +1,12 @@ -95482048463cdc99c77a69951654de7b28fd6880 ../Projects/Argon2/Argon2.csproj -ebafae4e8160057cbf408cb13114479ca26e1b58 ../Projects/Scripts.Tests/Scripts.Tests.csproj -6c6a48220658bdfa7b2e1e173077fd139ed4af2c ../Projects/Scripts/Scripts.csproj -6213c10f697b45729bab15f7870c42dcf49b026b ../Projects/Server.Tests/Server.Tests.csproj -4b3626e04f76dff1ab445e207658a3b386fce4e5 ../Projects/Server/Server.csproj -a663d309b6b86c7632ea5cd175468dd5180808c1 ../Projects/Argon2/Argon2.cs +6b0276b603e867108643104978963ddd2e599e58 ../Projects/Argon2/Argon2.csproj +214715e88298b66715dee7c06080fc083f2c9e26 ../Projects/Argon2/Argon2.cs 1e89625abe364f895346d0c5753f3ca6653cf7df ../Projects/Argon2/Argon2Context.cs abbb34d85f55ca1d78a400b4d46afbd6965f642b ../Projects/Argon2/Argon2Error.cs 00ef35a6809d4959bdda1de01f45e39ff388270f ../Projects/Argon2/Argon2Exception.cs -53164d1621e24adefc6917379d36d7273551f457 ../Projects/Argon2/Argon2PasswordHasher.cs +58979ca359777ae45a6233264f0741ba23203959 ../Projects/Argon2/Argon2PasswordHasher.cs a137d2fe0478d065d478366168f80ab9eaaa9c3a ../Projects/Argon2/Argon2Type.cs c09f7a2f9690d56ca838aafb28640c09950c5a8c ../Projects/Argon2/HashMetadata.cs -b5da07548eb41ec9bd35bc2def006f23698b357e ../Projects/Argon2/Utility.cs +c9fb8b37bd035c6597047d4279f9b6e6384db944 ../Projects/Argon2/Utility.cs +c9fb8b37bd035c6597047d4279f9b6e6384db944 ../Projects/ZLib/Utility.cs +a4c3595dada3e596ab3131886616d5c27107ec7f ../Projects/ZLib/ZLib.cs +d129d82f8607e97090088a6e1956706d886e8294 ../Projects/ZLib/ZLib.csproj diff --git a/.circleci/config.yml b/.circleci/config.yml index 7c8138fb3..ba1b5fc68 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,15 +21,15 @@ jobs: keys: - dotnet-packages-v1-{{ arch }}-{{ checksum ".circleci/checksum.txt" }} - run: - name: Build Argon2 - command: dotnet build -c Release -r linux-x64 Projects/Argon2/Argon2.csproj - - run: - name: Install ModernUO dependencies - command: dotnet restore + name: Build native libraries + command: /mnt/ramdisk/Tools/build-native-libraries.sh - save_cache: paths: - /mnt/ramdisk/packages key: dotnet-packages-v1-{{ arch }}-{{ checksum ".circleci/checksum.txt" }} + - run: + name: Install ModernUO dependencies + command: dotnet restore - run: name: Building ModernUO for Linux (Debug) command: dotnet build -c Debug -r linux-x64 @@ -42,15 +42,15 @@ jobs: keys: - dotnet-packages-v1-{{ arch }}-{{ checksum ".circleci/checksum.txt" }} - run: - name: Build Argon2 - command: dotnet build -c Debug -r win-x64 Projects/Argon2/Argon2.csproj + name: Build native libraries + command: Tools\build-native-libraries.cmd + - save_cache: + paths: + - packages + key: dotnet-packages-v1-{{ arch }}-{{ checksum ".circleci/checksum.txt" }} - run: name: Install ModernUO dependencies command: dotnet restore - - save_cache: - paths: - - /mnt/ramdisk/packages - key: dotnet-packages-v1-{{ arch }}-{{ checksum ".circleci/checksum.txt" }} - run: name: Building ModernUO for Windows (Debug) command: dotnet build -c Debug -r win-x64 @@ -64,15 +64,15 @@ jobs: keys: - dotnet-packages-v1-{{ arch }}-{{ checksum ".circleci/checksum.txt" }} - run: - name: Build Argon2 - command: dotnet build -c Debug -r linux-x64 Projects/Argon2/Argon2.csproj - - run: - name: Install ModernUO dependencies - command: dotnet restore + name: Build native libraries + command: /mnt/ramdisk/Tools/build-native-libraries.sh - save_cache: paths: - /mnt/ramdisk/packages key: dotnet-packages-v1-{{ arch }}-{{ checksum ".circleci/checksum.txt" }} + - run: + name: Install ModernUO dependencies + command: dotnet restore - run: name: Building with Analyzers command: dotnet build -c Analyze -r linux-x64 @@ -86,15 +86,15 @@ jobs: keys: - dotnet-packages-v1-{{ arch }}-{{ checksum ".circleci/checksum.txt" }} - run: - name: Build Argon2 - command: dotnet build -c Debug -r linux-x64 Projects/Argon2/Argon2.csproj - - run: - name: Install ModernUO dependencies - command: dotnet restore + name: Build native libraries + command: /mnt/ramdisk/Tools/build-native-libraries.sh - save_cache: paths: - /mnt/ramdisk/packages - key: dotnet-packages-linux-{{ checksum ".circleci/checksum.txt" }} + key: dotnet-packages-v1-{{ arch }}-{{ checksum ".circleci/checksum.txt" }} + - run: + name: Install ModernUO dependencies + command: dotnet restore - run: name: Running unit tests command: dotnet test -r linux-x64 diff --git a/.circleci/genchecksum.sh b/.circleci/genchecksum.sh index 1d30da007..c19eed6d5 100755 --- a/.circleci/genchecksum.sh +++ b/.circleci/genchecksum.sh @@ -1 +1 @@ -sha1sum ../Projects/*/*.csproj ../Projects/Argon2/*.cs > "checksum.txt" +sha1sum ../Projects/Argon2/*.csproj ../Projects/Argon2/*.cs ../Projects/ZLib/*.cs ../Projects/ZLib/*.csproj > "checksum.txt" diff --git a/.gitignore b/.gitignore index cce99125e..9d92a34e8 100644 --- a/.gitignore +++ b/.gitignore @@ -10,9 +10,12 @@ /Distribution/System.IO.Pipelines.dll /Distribution/libdrng.dll /Distribution/zlib.dll +/Distribution/libz.dylib +/Distribution/libz.so /Distribution/Microsoft.Bcl.AsyncInterfaces.dll /Distribution/System.ComponentModel.Annotations.dll /Distribution/System.Runtime.CompilerServices.Unsafe.dll +/Distribution/ZLib.Bindings.dll /Distribution/Data/modernuo.json /Distribution/runtimes /Distribution/nohup.out diff --git a/ModernUO.sln b/ModernUO.sln index e1d9f033b..2d214caef 100644 --- a/ModernUO.sln +++ b/ModernUO.sln @@ -1,4 +1,4 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 +Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.29102.190 MinimumVisualStudioVersion = 10.0.40219.1 @@ -12,6 +12,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server.Tests", "Projects\Se EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scripts.Tests", "Projects\Scripts.Tests\Scripts.Tests.csproj", "{3C4797F9-603E-44EF-8E8C-9275CC9EA74B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Zlib", "Projects\ZLib\ZLib.csproj", "{3B030CD2-DB29-4BC2-9C90-D90804B30757}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Analyze|x64 = Analyze|x64 @@ -49,6 +51,12 @@ Global {97150E9D-5561-4D3C-9B78-E795544507D0}.Debug|x64.Build.0 = Debug|x64 {97150E9D-5561-4D3C-9B78-E795544507D0}.Release|x64.ActiveCfg = Release|x64 {97150E9D-5561-4D3C-9B78-E795544507D0}.Release|x64.Build.0 = Release|x64 + {3B030CD2-DB29-4BC2-9C90-D90804B30757}.Analyze|x64.ActiveCfg = Debug|Any CPU + {3B030CD2-DB29-4BC2-9C90-D90804B30757}.Analyze|x64.Build.0 = Debug|Any CPU + {3B030CD2-DB29-4BC2-9C90-D90804B30757}.Debug|x64.ActiveCfg = Debug|Any CPU + {3B030CD2-DB29-4BC2-9C90-D90804B30757}.Debug|x64.Build.0 = Debug|Any CPU + {3B030CD2-DB29-4BC2-9C90-D90804B30757}.Release|x64.ActiveCfg = Release|Any CPU + {3B030CD2-DB29-4BC2-9C90-D90804B30757}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Projects/Argon2/Argon2.cs b/Projects/Argon2/Argon2.cs index 9be9b86be..e13789e04 100644 --- a/Projects/Argon2/Argon2.cs +++ b/Projects/Argon2/Argon2.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using System.Text; @@ -25,7 +24,7 @@ namespace Server.Accounting.Security static Argon2() { - if (RuntimeUtility.Unix) + if (RuntimeUtility.IsUnix) Library = new UnixArgon2(); else Library = new WindowsArgon2(); diff --git a/Projects/Argon2/Argon2.csproj b/Projects/Argon2/Argon2.csproj index b76f1e543..6fb0b3db8 100644 --- a/Projects/Argon2/Argon2.csproj +++ b/Projects/Argon2/Argon2.csproj @@ -1,7 +1,7 @@  win-x64;linux-x64;osx-x64 - 1.0.0 + 1.1.0 Server Argon2.Bindings x64 @@ -9,10 +9,9 @@ netcoreapp3.1 true true - true + false false Debug;Release;Analyze - WINDOWS 1.0.0 x64 @@ -33,10 +32,4 @@ PreserveNewest - - - - diff --git a/Projects/Argon2/Utility.cs b/Projects/Argon2/Utility.cs index e000e30ed..b450eb6da 100644 --- a/Projects/Argon2/Utility.cs +++ b/Projects/Argon2/Utility.cs @@ -4,10 +4,10 @@ namespace Server { internal static class RuntimeUtility { - public static bool IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - public static bool IsDarwin = RuntimeInformation.IsOSPlatform(OSPlatform.OSX); - public static bool IsFreeBSD = RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD); - public static bool IsLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || IsFreeBSD; - public static bool Unix = IsDarwin || IsFreeBSD || IsLinux; + internal static readonly bool IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + internal static readonly bool IsDarwin = RuntimeInformation.IsOSPlatform(OSPlatform.OSX); + internal static readonly bool IsFreeBSD = RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD); + internal static readonly bool IsLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || IsFreeBSD; + internal static readonly bool IsUnix = IsDarwin || IsFreeBSD || IsLinux; } } diff --git a/Projects/Scripts/Multis/HouseFoundation.cs b/Projects/Scripts/Multis/HouseFoundation.cs index 8e82b1740..c171362b0 100644 --- a/Projects/Scripts/Multis/HouseFoundation.cs +++ b/Projects/Scripts/Multis/HouseFoundation.cs @@ -10,6 +10,7 @@ using Server.Items; using Server.Mobiles; using Server.Network; using Server.Spells; +using Server.Compression; namespace Server.Multis { @@ -2324,7 +2325,7 @@ namespace Server.Multis byte[] inflatedBuffer = m_PlaneBuffers[i]; int deflatedLength = m_DeflatedBuffer.Length; - ZLibError ce = NetworkCompression.Pack(m_DeflatedBuffer, ref deflatedLength, inflatedBuffer, size, + ZLibError ce = ZLib.Pack(m_DeflatedBuffer, ref deflatedLength, inflatedBuffer, size, ZLibQuality.Default); if (ce != ZLibError.Okay) @@ -2360,7 +2361,7 @@ namespace Server.Multis byte[] inflatedBuffer = m_StairBuffers[i]; int deflatedLength = m_DeflatedBuffer.Length; - ZLibError ce = NetworkCompression.Pack(m_DeflatedBuffer, ref deflatedLength, inflatedBuffer, size, + ZLibError ce = ZLib.Pack(m_DeflatedBuffer, ref deflatedLength, inflatedBuffer, size, ZLibQuality.Default); if (ce != ZLibError.Okay) diff --git a/Projects/Scripts/Scripts.csproj b/Projects/Scripts/Scripts.csproj index a30ebe1c3..1e99d260f 100644 --- a/Projects/Scripts/Scripts.csproj +++ b/Projects/Scripts/Scripts.csproj @@ -66,7 +66,8 @@ - + + diff --git a/Projects/Server/MultiData.cs b/Projects/Server/MultiData.cs index b7112ffdc..e2c3b7186 100644 --- a/Projects/Server/MultiData.cs +++ b/Projects/Server/MultiData.cs @@ -22,7 +22,7 @@ using System; using System.Buffers; using System.Collections.Generic; using System.IO; -using Server.Network; +using Server.Compression; namespace Server { @@ -174,7 +174,7 @@ namespace Server if (compressionMethod == 1) { data = new byte[decompressedSize]; - NetworkCompression.Unpack(data, ref decompressedSize, sourceData, compressedSize); + ZLib.Unpack(data, ref decompressedSize, sourceData, compressedSize); } else { diff --git a/Projects/Server/Network/NetworkCompression.cs b/Projects/Server/Network/NetworkCompression.cs index 5dea0bc7f..ed178821d 100644 --- a/Projects/Server/Network/NetworkCompression.cs +++ b/Projects/Server/Network/NetworkCompression.cs @@ -19,8 +19,6 @@ ***************************************************************************/ using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; namespace Server.Network { @@ -45,9 +43,6 @@ namespace Server.Network // If our input exceeds this length, we cannot possibly compress it within the buffer private const int DefiniteOverflow = (BufferSize * 8 - TerminalCodeLength) / MinimalCodeLength; - // If our input exceeds this length, we may potentially overflow the buffer - private const int PossibleOverflow = (BufferSize * 8 - TerminalCodeLength) / MaximalCodeLength; - private static readonly int[] _huffmanTable = { 0x2, 0x000, 0x5, 0x01F, 0x6, 0x022, 0x7, 0x034, 0x7, 0x075, 0x6, 0x028, 0x6, 0x03B, 0x7, 0x032, @@ -85,16 +80,6 @@ namespace Server.Network 0x4, 0x00D }; - public static readonly ICompressor Compressor; - - static NetworkCompression() - { - if (Core.Unix) - Compressor = new UnixCompressor(); - else - Compressor = new Compressor(); - } - public static unsafe void Compress(ReadOnlySpan input, int offset, int count, Span output, out int length) { if (input == null) throw new ArgumentNullException(nameof(input)); @@ -181,194 +166,5 @@ namespace Server.Network } } } - - public static int MaxPackSize(int sourceLength) => (int)Compressor.CompressBound((ulong)sourceLength); - - public static unsafe ZLibError Pack(Span dest, ref int destLength, ReadOnlySpan source, int sourceLength) - { - var destLengthLong = (ulong)destLength; - fixed (byte* dPtr = &MemoryMarshal.GetReference(dest), sPtr = &MemoryMarshal.GetReference(source)) - { - var e = Compressor.Compress(Unsafe.AsRef(dPtr), ref destLengthLong, Unsafe.AsRef(sPtr), - (ulong)sourceLength); - destLength = (int)destLengthLong; - return e; - } - } - - public static unsafe ZLibError Pack(Span dest, ref int destLength, ReadOnlySpan source, ZLibQuality quality) - { - var destLengthLong = (ulong)destLength; - fixed (byte* dPtr = &MemoryMarshal.GetReference(dest), sPtr = &MemoryMarshal.GetReference(source)) - { - var e = Compressor.Compress(Unsafe.AsRef(dPtr), ref destLengthLong, Unsafe.AsRef(sPtr), - (ulong)source.Length, quality); - destLength = (int)destLengthLong; - return e; - } - } - - public static unsafe ZLibError Pack(Span dest, ref int destLength, ReadOnlySpan source, int sourceLength, - ZLibQuality quality) - { - var destLengthLong = (ulong)destLength; - fixed (byte* dPtr = &MemoryMarshal.GetReference(dest), sPtr = &MemoryMarshal.GetReference(source)) - { - var e = Compressor.Compress(Unsafe.AsRef(dPtr), ref destLengthLong, Unsafe.AsRef(sPtr), - (ulong)sourceLength, quality); - destLength = (int)destLengthLong; - return e; - } - } - - public static unsafe ZLibError Unpack(Span dest, ref int destLength, ReadOnlySpan source, int sourceLength) - { - var destLengthLong = (ulong)destLength; - fixed (byte* dPtr = &MemoryMarshal.GetReference(dest), sPtr = &MemoryMarshal.GetReference(source)) - { - var e = Compressor.Decompress(Unsafe.AsRef(dPtr), ref destLengthLong, Unsafe.AsRef(sPtr), - (ulong)sourceLength); - destLength = (int)destLengthLong; - return e; - } - } - - public static ulong MaxPackSize(ulong sourceLength) => Compressor.CompressBound(sourceLength); - - public static unsafe ZLibError Pack(Span dest, ref ulong destLength, ReadOnlySpan source, ulong sourceLength) - { - fixed (byte* dPtr = &MemoryMarshal.GetReference(dest), sPtr = &MemoryMarshal.GetReference(source)) - { - return Compressor.Compress(Unsafe.AsRef(dPtr), ref destLength, Unsafe.AsRef(sPtr), sourceLength); - } - } - - public static unsafe ZLibError Pack(Span dest, ref ulong destLength, ReadOnlySpan source, - ZLibQuality quality) - { - fixed (byte* dPtr = &MemoryMarshal.GetReference(dest), sPtr = &MemoryMarshal.GetReference(source)) - { - return Compressor.Compress(Unsafe.AsRef(dPtr), ref destLength, Unsafe.AsRef(sPtr), (ulong)source.Length, - quality); - } - } - - public static unsafe ZLibError Pack(Span dest, ref ulong destLength, ReadOnlySpan source, ulong sourceLength, - ZLibQuality quality) - { - fixed (byte* dPtr = &MemoryMarshal.GetReference(dest), sPtr = &MemoryMarshal.GetReference(source)) - { - return Compressor.Compress(Unsafe.AsRef(dPtr), ref destLength, Unsafe.AsRef(sPtr), sourceLength, quality); - } - } - - public static unsafe ZLibError Unpack(Span dest, ref ulong destLength, ReadOnlySpan source, - ulong sourceLength) - { - fixed (byte* dPtr = &MemoryMarshal.GetReference(dest), sPtr = &MemoryMarshal.GetReference(source)) - { - return Compressor.Decompress(Unsafe.AsRef(dPtr), ref destLength, Unsafe.AsRef(sPtr), sourceLength); - } - } - } - - public interface ICompressor - { - string Version { get; } - ZLibError Compress(in int dest, ref ulong destLength, in int source, ulong sourceLength); - ZLibError Compress(in int dest, ref ulong destLength, in int source, ulong sourceLength, ZLibQuality quality); - ZLibError Decompress(in int dest, ref ulong destLength, in int source, ulong sourceLength); - ulong CompressBound(ulong sourceLength); - } - - public class Compressor : ICompressor - { - public string Version => SafeNativeMethods.zlibVersion(); - - public ZLibError Compress(in int dest, ref ulong destLength, in int source, ulong sourceLength) => - SafeNativeMethods.compress(dest, ref destLength, source, sourceLength); - - public ZLibError Compress(in int dest, ref ulong destLength, in int source, ulong sourceLength, - ZLibQuality quality) => SafeNativeMethods.compress2(dest, ref destLength, source, sourceLength, quality); - - public ZLibError Decompress(in int dest, ref ulong destLength, in int source, ulong sourceLength) => - SafeNativeMethods.uncompress(dest, ref destLength, source, sourceLength); - - public ulong CompressBound(ulong sourceLength) => SafeNativeMethods.compressBound(sourceLength); - - private static class SafeNativeMethods - { - [DllImport("zlib", CharSet = CharSet.Unicode)] - internal static extern string zlibVersion(); - - [DllImport("zlib")] - internal static extern ZLibError compress(in int dest, ref ulong destLength, in int source, ulong sourceLength); - - [DllImport("zlib")] - internal static extern ZLibError compress2(in int dest, ref ulong destLength, in int source, ulong sourceLength, - ZLibQuality quality); - - [DllImport("zlib")] - internal static extern ZLibError uncompress(in int dest, ref ulong destLength, in int source, ulong sourceLength); - - [DllImport("zlib")] - internal static extern ulong compressBound(ulong sourceLen); - } - } - - public class UnixCompressor : ICompressor - { - public string Version => SafeNativeMethods.zlibVersion(); - - public ZLibError Compress(in int dest, ref ulong destLength, in int source, ulong sourceLength) => - SafeNativeMethods.compress(dest, ref destLength, source, sourceLength); - - public ZLibError Compress(in int dest, ref ulong destLength, in int source, ulong sourceLength, - ZLibQuality quality) => SafeNativeMethods.compress2(dest, ref destLength, source, sourceLength, quality); - - public ZLibError Decompress(in int dest, ref ulong destLength, in int source, ulong sourceLength) => - SafeNativeMethods.uncompress(dest, ref destLength, source, sourceLength); - - public ulong CompressBound(ulong sourceLength) => SafeNativeMethods.compressBound(sourceLength); - - internal static class SafeNativeMethods - { - [DllImport("libz", CharSet = CharSet.Unicode)] - internal static extern string zlibVersion(); - - [DllImport("libz")] - internal static extern ZLibError compress(in int dest, ref ulong destLength, in int source, ulong sourceLength); - - [DllImport("libz")] - internal static extern ZLibError compress2(in int dest, ref ulong destLength, in int source, ulong sourceLength, - ZLibQuality quality); - - [DllImport("libz")] - internal static extern ZLibError uncompress(in int dest, ref ulong destLength, in int source, ulong sourceLength); - - [DllImport("libz")] - internal static extern ulong compressBound(ulong sourceLen); - } - } - - public enum ZLibError - { - VersionError = -6, - BufferError = -5, - MemoryError = -4, - DataError = -3, - StreamError = -2, - FileError = -1, - Okay = 0, - StreamEnd = 1, - NeedDictionary = 2 - } - - public enum ZLibQuality - { - Default = -1, - None = 0, - Speed = 1, - Size = 9 } } diff --git a/Projects/Server/Network/Packets.cs b/Projects/Server/Network/Packets.cs index f9e273ae7..d62cb17ee 100644 --- a/Projects/Server/Network/Packets.cs +++ b/Projects/Server/Network/Packets.cs @@ -26,6 +26,7 @@ using System.Net; using System.Text; using System.Threading; using Server.Accounting; +using Server.Compression; using Server.ContextMenus; using Server.Gumps; using Server.HuePickers; @@ -2119,7 +2120,7 @@ namespace Server.Network var packLength = wantLength; - NetworkCompression.Pack(packBuffer, ref packLength, buffer, length, ZLibQuality.Default); + ZLib.Pack(packBuffer, ref packLength, buffer, length, ZLibQuality.Default); Stream.Write(4 + packLength); Stream.Write(length); diff --git a/Projects/Server/Server.csproj b/Projects/Server/Server.csproj index a629ba630..bf6baba94 100644 --- a/Projects/Server/Server.csproj +++ b/Projects/Server/Server.csproj @@ -29,6 +29,11 @@ + + + + + @@ -67,16 +72,17 @@ libdrng.dll Always - + + diff --git a/Projects/ZLib/Utility.cs b/Projects/ZLib/Utility.cs new file mode 100644 index 000000000..b450eb6da --- /dev/null +++ b/Projects/ZLib/Utility.cs @@ -0,0 +1,13 @@ +using System.Runtime.InteropServices; + +namespace Server +{ + internal static class RuntimeUtility + { + internal static readonly bool IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + internal static readonly bool IsDarwin = RuntimeInformation.IsOSPlatform(OSPlatform.OSX); + internal static readonly bool IsFreeBSD = RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD); + internal static readonly bool IsLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || IsFreeBSD; + internal static readonly bool IsUnix = IsDarwin || IsFreeBSD || IsLinux; + } +} diff --git a/Projects/ZLib/ZLib.cs b/Projects/ZLib/ZLib.cs new file mode 100644 index 000000000..b8520d8ea --- /dev/null +++ b/Projects/ZLib/ZLib.cs @@ -0,0 +1,208 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Server.Compression +{ + public static class ZLib + { + public static readonly ICompressor Compressor; + + static ZLib() + { + if (RuntimeUtility.IsUnix) + Compressor = new UnixCompressor(); + else + Compressor = new Compressor(); + } + + public static int MaxPackSize(int sourceLength) => (int)Compressor.CompressBound((ulong)sourceLength); + + public static unsafe ZLibError Pack(Span dest, ref int destLength, ReadOnlySpan source, int sourceLength) + { + var destLengthLong = (ulong)destLength; + fixed (byte* dPtr = &MemoryMarshal.GetReference(dest), sPtr = &MemoryMarshal.GetReference(source)) + { + var e = Compressor.Compress(Unsafe.AsRef(dPtr), ref destLengthLong, Unsafe.AsRef(sPtr), + (ulong)sourceLength); + destLength = (int)destLengthLong; + return e; + } + } + + public static unsafe ZLibError Pack(Span dest, ref int destLength, ReadOnlySpan source, ZLibQuality quality) + { + var destLengthLong = (ulong)destLength; + fixed (byte* dPtr = &MemoryMarshal.GetReference(dest), sPtr = &MemoryMarshal.GetReference(source)) + { + var e = Compressor.Compress(Unsafe.AsRef(dPtr), ref destLengthLong, Unsafe.AsRef(sPtr), + (ulong)source.Length, quality); + destLength = (int)destLengthLong; + return e; + } + } + + public static unsafe ZLibError Pack(Span dest, ref int destLength, ReadOnlySpan source, int sourceLength, + ZLibQuality quality) + { + var destLengthLong = (ulong)destLength; + fixed (byte* dPtr = &MemoryMarshal.GetReference(dest), sPtr = &MemoryMarshal.GetReference(source)) + { + var e = Compressor.Compress(Unsafe.AsRef(dPtr), ref destLengthLong, Unsafe.AsRef(sPtr), + (ulong)sourceLength, quality); + destLength = (int)destLengthLong; + return e; + } + } + + public static unsafe ZLibError Unpack(Span dest, ref int destLength, ReadOnlySpan source, int sourceLength) + { + var destLengthLong = (ulong)destLength; + fixed (byte* dPtr = &MemoryMarshal.GetReference(dest), sPtr = &MemoryMarshal.GetReference(source)) + { + var e = Compressor.Decompress(Unsafe.AsRef(dPtr), ref destLengthLong, Unsafe.AsRef(sPtr), + (ulong)sourceLength); + destLength = (int)destLengthLong; + return e; + } + } + + public static ulong MaxPackSize(ulong sourceLength) => Compressor.CompressBound(sourceLength); + + public static unsafe ZLibError Pack(Span dest, ref ulong destLength, ReadOnlySpan source, ulong sourceLength) + { + fixed (byte* dPtr = &MemoryMarshal.GetReference(dest), sPtr = &MemoryMarshal.GetReference(source)) + { + return Compressor.Compress(Unsafe.AsRef(dPtr), ref destLength, Unsafe.AsRef(sPtr), sourceLength); + } + } + + public static unsafe ZLibError Pack(Span dest, ref ulong destLength, ReadOnlySpan source, + ZLibQuality quality) + { + fixed (byte* dPtr = &MemoryMarshal.GetReference(dest), sPtr = &MemoryMarshal.GetReference(source)) + { + return Compressor.Compress(Unsafe.AsRef(dPtr), ref destLength, Unsafe.AsRef(sPtr), (ulong)source.Length, + quality); + } + } + + public static unsafe ZLibError Pack(Span dest, ref ulong destLength, ReadOnlySpan source, ulong sourceLength, + ZLibQuality quality) + { + fixed (byte* dPtr = &MemoryMarshal.GetReference(dest), sPtr = &MemoryMarshal.GetReference(source)) + { + return Compressor.Compress(Unsafe.AsRef(dPtr), ref destLength, Unsafe.AsRef(sPtr), sourceLength, quality); + } + } + + public static unsafe ZLibError Unpack(Span dest, ref ulong destLength, ReadOnlySpan source, + ulong sourceLength) + { + fixed (byte* dPtr = &MemoryMarshal.GetReference(dest), sPtr = &MemoryMarshal.GetReference(source)) + { + return Compressor.Decompress(Unsafe.AsRef(dPtr), ref destLength, Unsafe.AsRef(sPtr), sourceLength); + } + } + } + + public interface ICompressor + { + string Version { get; } + ZLibError Compress(in int dest, ref ulong destLength, in int source, ulong sourceLength); + ZLibError Compress(in int dest, ref ulong destLength, in int source, ulong sourceLength, ZLibQuality quality); + ZLibError Decompress(in int dest, ref ulong destLength, in int source, ulong sourceLength); + ulong CompressBound(ulong sourceLength); + } + + public class Compressor : ICompressor + { + public string Version => SafeNativeMethods.zlibVersion(); + + public ZLibError Compress(in int dest, ref ulong destLength, in int source, ulong sourceLength) => + SafeNativeMethods.compress(dest, ref destLength, source, sourceLength); + + public ZLibError Compress(in int dest, ref ulong destLength, in int source, ulong sourceLength, + ZLibQuality quality) => SafeNativeMethods.compress2(dest, ref destLength, source, sourceLength, quality); + + public ZLibError Decompress(in int dest, ref ulong destLength, in int source, ulong sourceLength) => + SafeNativeMethods.uncompress(dest, ref destLength, source, sourceLength); + + public ulong CompressBound(ulong sourceLength) => SafeNativeMethods.compressBound(sourceLength); + + private static class SafeNativeMethods + { + [DllImport("zlib", CharSet = CharSet.Unicode)] + internal static extern string zlibVersion(); + + [DllImport("zlib")] + internal static extern ZLibError compress(in int dest, ref ulong destLength, in int source, ulong sourceLength); + + [DllImport("zlib")] + internal static extern ZLibError compress2(in int dest, ref ulong destLength, in int source, ulong sourceLength, + ZLibQuality quality); + + [DllImport("zlib")] + internal static extern ZLibError uncompress(in int dest, ref ulong destLength, in int source, ulong sourceLength); + + [DllImport("zlib")] + internal static extern ulong compressBound(ulong sourceLen); + } + } + + public class UnixCompressor : ICompressor + { + public string Version => SafeNativeMethods.zlibVersion(); + + public ZLibError Compress(in int dest, ref ulong destLength, in int source, ulong sourceLength) => + SafeNativeMethods.compress(dest, ref destLength, source, sourceLength); + + public ZLibError Compress(in int dest, ref ulong destLength, in int source, ulong sourceLength, + ZLibQuality quality) => SafeNativeMethods.compress2(dest, ref destLength, source, sourceLength, quality); + + public ZLibError Decompress(in int dest, ref ulong destLength, in int source, ulong sourceLength) => + SafeNativeMethods.uncompress(dest, ref destLength, source, sourceLength); + + public ulong CompressBound(ulong sourceLength) => SafeNativeMethods.compressBound(sourceLength); + + internal static class SafeNativeMethods + { + [DllImport("libz", CharSet = CharSet.Unicode)] + internal static extern string zlibVersion(); + + [DllImport("libz")] + internal static extern ZLibError compress(in int dest, ref ulong destLength, in int source, ulong sourceLength); + + [DllImport("libz")] + internal static extern ZLibError compress2(in int dest, ref ulong destLength, in int source, ulong sourceLength, + ZLibQuality quality); + + [DllImport("libz")] + internal static extern ZLibError uncompress(in int dest, ref ulong destLength, in int source, ulong sourceLength); + + [DllImport("libz")] + internal static extern ulong compressBound(ulong sourceLen); + } + } + + public enum ZLibError + { + VersionError = -6, + BufferError = -5, + MemoryError = -4, + DataError = -3, + StreamError = -2, + FileError = -1, + Okay = 0, + StreamEnd = 1, + NeedDictionary = 2 + } + + public enum ZLibQuality + { + Default = -1, + None = 0, + Speed = 1, + Size = 9 + } +} diff --git a/Projects/ZLib/ZLib.csproj b/Projects/ZLib/ZLib.csproj new file mode 100644 index 000000000..179b5261c --- /dev/null +++ b/Projects/ZLib/ZLib.csproj @@ -0,0 +1,35 @@ + + + win-x64;linux-x64;osx-x64 + 1.0.0 + Server + ZLib.Bindings + x64 + 8.0 + netcoreapp3.1 + true + true + false + false + Debug;Release;Analyze + 1.0.0 + x64 + + + + true + runtimes/win-x64/native + PreserveNewest + + + true + runtimes/osx-x64/native + PreserveNewest + + + true + runtimes/linux-x64/native + PreserveNewest + + + diff --git a/Projects/ZLib/runtimes/linux-x64/native/libz.so b/Projects/ZLib/runtimes/linux-x64/native/libz.so new file mode 100755 index 000000000..52e459724 Binary files /dev/null and b/Projects/ZLib/runtimes/linux-x64/native/libz.so differ diff --git a/Projects/ZLib/runtimes/osx-x64/native/libz.dylib b/Projects/ZLib/runtimes/osx-x64/native/libz.dylib new file mode 100755 index 000000000..385ea372a Binary files /dev/null and b/Projects/ZLib/runtimes/osx-x64/native/libz.dylib differ diff --git a/Projects/Server/Assemblies/zlib.dll b/Projects/ZLib/runtimes/win-x64/native/zlib.dll similarity index 100% rename from Projects/Server/Assemblies/zlib.dll rename to Projects/ZLib/runtimes/win-x64/native/zlib.dll diff --git a/Tools/build-native-libraries.cmd b/Tools/build-native-libraries.cmd new file mode 100755 index 000000000..aa6b6a79a --- /dev/null +++ b/Tools/build-native-libraries.cmd @@ -0,0 +1,4 @@ +dotnet build -c Release Projects/Argon2/Argon2.csproj +dotnet pack -o ./packages Projects/Argon2/Argon2.csproj +dotnet build -c Release Projects/ZLib/ZLib.csproj +dotnet pack -o ./packages Projects/ZLib/ZLib.csproj diff --git a/Tools/build-native-libraries.sh b/Tools/build-native-libraries.sh new file mode 100755 index 000000000..e5e7c9be7 --- /dev/null +++ b/Tools/build-native-libraries.sh @@ -0,0 +1,4 @@ +dotnet build -c Release Projects/Argon2/Argon2.csproj +dotnet pack -o ./packages Projects/Argon2/Argon2.csproj +dotnet build -c Release Projects/ZLib/ZLib.csproj +dotnet pack -o ./packages Projects/ZLib/ZLib.csproj