Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop ancient zlib dependency in favor of native .NET library calls. #897

Merged
merged 1 commit into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions WowPacketParser/Misc/FlushCode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace WowPacketParser.Misc
{
public enum FlushCode
{
NoFlush = 0,
SyncFlush = 2,
Finish = 4,
Block = 5
}
}
78 changes: 6 additions & 72 deletions WowPacketParser/Misc/Packet.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using Google.Protobuf.WellKnownTypes;
using Ionic.Zlib;
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using WowPacketParser.Enums;
using WowPacketParser.Enums.Version;
Expand Down Expand Up @@ -95,26 +95,7 @@ public void AddSniffData(StoreNameType type, int id, string data)
Storage.SniffData.Add(item, TimeSpan);
}

public bool TryInflate(int inflatedSize, int index, byte[] arr, ref byte[] newarr)
{
try
{
if (!SessionHandler.ZStreams.ContainsKey(index))
SessionHandler.ZStreams[index] = new ZlibCodec(CompressionMode.Decompress);
SessionHandler.ZStreams[index].InputBuffer = arr;
SessionHandler.ZStreams[index].NextIn = 0;
SessionHandler.ZStreams[index].AvailableBytesIn = arr.Length;
SessionHandler.ZStreams[index].OutputBuffer = newarr;
SessionHandler.ZStreams[index].NextOut = 0;
SessionHandler.ZStreams[index].AvailableBytesOut = inflatedSize;
SessionHandler.ZStreams[index].Inflate(FlushType.Sync);
return true;
}
catch (ZlibException)
{
return false;
}
}
public void ResetInflateStream() => ZLibHelper.ResetInflateStream(ConnectionIndex);

public Packet Inflate(int inflatedSize, bool keepStream = true)
{
Expand All @@ -127,36 +108,12 @@ public Packet Inflate(int inflatedSize, bool keepStream = true)
if (keepStream)
{
int idx = ConnectionIndex;
while (!TryInflate(inflatedSize, idx, arr, ref newarr) && idx <= 4)
while (!ZLibHelper.TryInflate(inflatedSize, idx, arr, ref newarr) && idx <= 4)
idx += 1;
}
else
{
/*try
{
var inflater = new Inflater(true);
inflater.SetInput(arr, 0, arr.Length);
inflater.Inflate(newarr, 0, inflatedSize);
}
catch (ICSharpCode.SharpZipLib.SharpZipBaseException)
{
var inflater = new Inflater(true);
inflater.SetInput(arr, 0, arr.Length);
inflater.Inflate(newarr, 0, inflatedSize);
}*/
var stream = new ZlibCodec(CompressionMode.Decompress)
{
InputBuffer = arr,
NextIn = 0,
AvailableBytesIn = arr.Length,
OutputBuffer = newarr,
NextOut = 0,
AvailableBytesOut = inflatedSize
};

stream.Inflate(FlushType.None);
stream.Inflate(FlushType.Finish);
stream.EndInflate();
ZLibHelper.Inflate(inflatedSize, arr, newarr);
}

// Cannot use "using" here
Expand All @@ -178,35 +135,12 @@ public Packet Inflate(int arrSize, int inflatedSize, bool keepStream = true)
if (keepStream)
{
int idx = ConnectionIndex;
while (!TryInflate(inflatedSize, idx, arr, ref newarr) && idx <= 4)
while (!ZLibHelper.TryInflate(inflatedSize, idx, arr, ref newarr) && idx <= 4)
idx += 1;
}
else
{
/*try
{
var inflater = new Inflater(true);
inflater.SetInput(arr, 0, arr.Length);
inflater.Inflate(newarr, 0, inflatedSize);
}
catch (ICSharpCode.SharpZipLib.SharpZipBaseException)
{
var inflater = new Inflater(true);
inflater.SetInput(arr, 0, arr.Length);
inflater.Inflate(newarr, 0, inflatedSize);
}*/
var stream = new ZlibCodec(CompressionMode.Decompress)
{
InputBuffer = arr,
NextIn = 0,
AvailableBytesIn = arr.Length,
OutputBuffer = newarr,
NextOut = 0,
AvailableBytesOut = inflatedSize
};
stream.Inflate(FlushType.None);
stream.Inflate(FlushType.Finish);
stream.EndInflate();
ZLibHelper.Inflate(inflatedSize, arr, newarr);
}

// Cannot use "using" here
Expand Down
80 changes: 80 additions & 0 deletions WowPacketParser/Misc/ZLibHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System;
using System.Runtime.InteropServices;
using WowPacketParser.Parsing.Parsers;

namespace WowPacketParser.Misc
{
internal partial class ZLibHelper
{
private const string CompressionLib = "compression_native";

[LibraryImport(CompressionLib, EntryPoint = "CompressionNative_InflateInit2_")]
private static partial int InflateInit2(ref ZStream zStream, int windowBits);

[LibraryImport(CompressionLib, EntryPoint = "CompressionNative_Inflate")]
private static partial int Inflate(ref ZStream zStream, FlushCode flush);

[LibraryImport(CompressionLib, EntryPoint = "CompressionNative_InflateEnd")]
private static partial int InflateEnd(ref ZStream zStream);

public static void ResetInflateStream(int connectionIndex)
{
ref var zStream = ref CollectionsMarshal.GetValueRefOrAddDefault(SessionHandler.ZStreams, connectionIndex, out bool exists);

InflateInit2(ref zStream, 15);
}

public static unsafe bool TryInflate(int inflatedSize, int index, byte[] arr, ref byte[] newarr)
{
try
{
ref var zStream = ref CollectionsMarshal.GetValueRefOrAddDefault(SessionHandler.ZStreams, index, out bool exists);

if (!exists)
{
var initResult = InflateInit2(ref zStream, 15);

if (initResult != 0)
return false;
}

fixed (byte* compressedData = arr)
fixed (byte* uncompressedData = newarr)
{
zStream.AvailIn = (uint)arr.Length;
zStream.NextIn = compressedData;
zStream.AvailOut = (uint)inflatedSize;
zStream.NextOut = uncompressedData;

Inflate(ref zStream, FlushCode.SyncFlush);
}

return true;
}
catch (Exception)
{
return false;
}
}

public static unsafe void Inflate(int inflatedSize, byte[] arr, byte[] newarr)
{
ZStream zStream = default;

InflateInit2(ref zStream, 15);

fixed (byte* compressedData = arr)
fixed (byte* uncompressedData = newarr)
{
zStream.AvailIn = (uint)arr.Length;
zStream.NextIn = compressedData;
zStream.AvailOut = (uint)inflatedSize;
zStream.NextOut = uncompressedData;

Inflate(ref zStream, FlushCode.NoFlush);
Inflate(ref zStream, FlushCode.Finish);
InflateEnd(ref zStream);
}
}
}
}
17 changes: 17 additions & 0 deletions WowPacketParser/Misc/ZStream.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.Runtime.InteropServices;

namespace WowPacketParser.Misc
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public unsafe struct ZStream
{
internal byte* NextIn;
internal byte* NextOut;
internal nint Msg;

readonly nint InternalState;

internal uint AvailIn;
internal uint AvailOut;
}
}
5 changes: 2 additions & 3 deletions WowPacketParser/Parsing/Parsers/SessionHandler.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Ionic.Zlib;
using System;
using System.Collections.Generic;
using System.Text;
Expand All @@ -10,7 +9,7 @@ namespace WowPacketParser.Parsing.Parsers
public static class SessionHandler
{
public static WowGuid LoginGuid;
public static Dictionary<int, ZlibCodec> ZStreams = new Dictionary<int, ZlibCodec>();
public static Dictionary<int, ZStream> ZStreams = new Dictionary<int, ZStream>();

[Parser(Opcode.SMSG_AUTH_CHALLENGE, ClientVersionBuild.Zero, ClientVersionBuild.V4_0_1a_13205)]
public static void HandleServerAuthChallenge(Packet packet)
Expand Down Expand Up @@ -559,7 +558,7 @@ public static void HandleMessageOfTheDay(Packet packet)
public static void HandleResetCompressionContext(Packet packet)
{
packet.ReadInt32("Unk?");
ZStreams[packet.ConnectionIndex] = new ZlibCodec(CompressionMode.Decompress);
packet.ResetInflateStream();
}
}
}
19 changes: 19 additions & 0 deletions WowPacketParser/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using WowPacketParser.Loading;
using WowPacketParser.Misc;
Expand All @@ -15,6 +17,23 @@ public static class Program
{
private static void Main(string[] args)
{
NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), (libraryName, assembly, searchPath) =>
{
if (libraryName.Equals("compression_native", StringComparison.OrdinalIgnoreCase))
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return NativeLibrary.Load("System.IO.Compression.Native.dll", assembly, searchPath);

if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
return NativeLibrary.Load("libSystem.IO.Compression.Native.dylib", assembly, searchPath);

if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return NativeLibrary.Load("libSystem.IO.Compression.Native.so", assembly, searchPath);
}

return default;
});

SetUpWindowTitle();
SetUpConsole();

Expand Down
1 change: 0 additions & 1 deletion WowPacketParser/WowPacketParser.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Iconic.Zlib.Netstandard" Version="1.0.0" />
<PackageReference Include="MySql.Data" Version="8.3.0" />
<PackageReference Include="RawScape.Wintellect.PowerCollections" Version="1.0.1" />
<PackageReference Include="Sigil" Version="5.0.0" />
Expand Down
Loading