Skip to content

Commit 00e7ec9

Browse files
committed
Add support for zstd compressed chunks
1 parent 7cdb211 commit 00e7ec9

File tree

2 files changed

+52
-4
lines changed

2 files changed

+52
-4
lines changed

Diff for: SteamKit2/SteamKit2/Steam/CDN/DepotChunk.cs

+8-4
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,18 @@ public static int Process( DepotManifest.ChunkData info, ReadOnlySpan<byte> data
5959
throw new InvalidDataException( $"Not enough data in the decrypted depot chunk (was {buffer.Length} bytes)." );
6060
}
6161

62-
var decryptedStream = new MemoryStream( buffer, 0, written );
63-
64-
if ( buffer[ 0 ] == 'V' && buffer[ 1 ] == 'Z' && buffer[ 2 ] == 'a' )
62+
if ( buffer[ 0 ] == 'V' && buffer[ 1 ] == 'S' && buffer[ 2 ] == 'Z' && buffer[ 3 ] == 'a' ) // Zstd
63+
{
64+
writtenDecompressed = VZstdUtil.Decompress( buffer.AsSpan( 0, written ), destination );
65+
}
66+
else if ( buffer[ 0 ] == 'V' && buffer[ 1 ] == 'Z' && buffer[ 2 ] == 'a' ) // LZMA
6567
{
68+
using var decryptedStream = new MemoryStream( buffer, 0, written );
6669
writtenDecompressed = VZipUtil.Decompress( decryptedStream, destination, verifyChecksum: false );
6770
}
68-
else if ( buffer[ 0 ] == 'P' && buffer[ 1 ] == 'K' && buffer[ 2 ] == 0x03 && buffer[ 3 ] == 0x04 )
71+
else if ( buffer[ 0 ] == 'P' && buffer[ 1 ] == 'K' && buffer[ 2 ] == 0x03 && buffer[ 3 ] == 0x04 ) // PKzip
6972
{
73+
using var decryptedStream = new MemoryStream( buffer, 0, written );
7074
writtenDecompressed = ZipUtil.Decompress( decryptedStream, destination, verifyChecksum: false );
7175
}
7276
else

Diff for: SteamKit2/SteamKit2/Util/VZstdUtil.cs

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using System;
2+
using System.Buffers;
3+
using System.IO;
4+
using System.Runtime.InteropServices;
5+
6+
namespace SteamKit2
7+
{
8+
static class VZstdUtil
9+
{
10+
private const uint VZstdHeader = 0x56535A61;
11+
12+
public static int Decompress( ReadOnlySpan<byte> buffer, byte[] destination )
13+
{
14+
if ( MemoryMarshal.Read<uint>( buffer ) != VZstdHeader )
15+
{
16+
throw new InvalidDataException( "Expecting VZstdHeader at start of stream" );
17+
}
18+
19+
var sizeCompressed = MemoryMarshal.Read<int>( buffer[ ^15.. ] ); // TODO: I am not convinced this is correct -- maybe its the frame size
20+
var sizeDecompressed = MemoryMarshal.Read<int>( buffer[ ^11.. ] );
21+
22+
if ( buffer[ ^3 ] != 'z' || buffer[ ^2 ] != 's' || buffer[ ^1 ] != 'v' )
23+
{
24+
throw new InvalidDataException( "Expecting VZstdFooter at end of stream" );
25+
}
26+
27+
if ( destination.Length < sizeDecompressed )
28+
{
29+
throw new ArgumentException( "The destination buffer is smaller than the decompressed data size.", nameof( destination ) );
30+
}
31+
32+
using var zstdDecompressor = new ZstdSharp.Decompressor();
33+
34+
var input = buffer[ 4..^12 ];
35+
36+
if ( !zstdDecompressor.TryUnwrap( input, destination, out var sizeWritten ) || sizeDecompressed != sizeWritten )
37+
{
38+
throw new InvalidDataException( $"Failed to decompress Zstd (expected {sizeDecompressed} bytes, got {sizeWritten})." );
39+
}
40+
41+
return sizeDecompressed;
42+
}
43+
}
44+
}

0 commit comments

Comments
 (0)