+27
-13
src/goose_ws_ffi.erl
+27
-13
src/goose_ws_ffi.erl
···
145
DictPath = filename:join(PrivDir, "zstd_dictionary"),
146
case file:read_file(DictPath) of
147
{ok, DictData} ->
148
-
%% Create decompression dictionary (returns reference directly)
149
DDict = ezstd:create_ddict(DictData),
150
-
{ok, DDict};
151
{error, Err} ->
152
-
io:format("Failed to read zstd dictionary: ~p~n", [Err]),
153
{error, Err}
154
end;
155
_ ->
···
166
{gun_ws, _AnyConnPid, _AnyStreamRef, {binary, Binary}} ->
167
%% If compression is enabled, decompress the binary data
168
case {Compress, Decompressor} of
169
-
{true, {ok, DDict}} ->
170
-
try
171
-
%% decompress_using_ddict returns the decompressed data directly
172
-
Decompressed = ezstd:decompress_using_ddict(Binary, DDict),
173
-
%% Ensure it's treated as a binary (not iolist)
174
-
DecompressedBin = iolist_to_binary([Decompressed]),
175
-
HandlerPid ! {ws_text, DecompressedBin}
176
-
catch
177
-
Error:Reason:_Stacktrace ->
178
-
io:format("Decompression failed: ~p:~p~n", [Error, Reason])
179
end;
180
_ ->
181
%% No compression, ignore binary messages
···
145
DictPath = filename:join(PrivDir, "zstd_dictionary"),
146
case file:read_file(DictPath) of
147
{ok, DictData} ->
148
+
%% Create decompression context and dictionary
149
+
DCtx = ezstd:create_decompression_context(1024 * 1024),
150
DDict = ezstd:create_ddict(DictData),
151
+
%% Select the dictionary for the decompression context
152
+
ok = ezstd:select_ddict(DCtx, DDict),
153
+
{ok, {DCtx, DDict}};
154
{error, Err} ->
155
+
io:format("Failed to load zstd dictionary: ~p~n", [Err]),
156
{error, Err}
157
end;
158
_ ->
···
169
{gun_ws, _AnyConnPid, _AnyStreamRef, {binary, Binary}} ->
170
%% If compression is enabled, decompress the binary data
171
case {Compress, Decompressor} of
172
+
{true, {ok, {DCtx, DDict}}} ->
173
+
%% Try decompress_using_ddict first (works for frames with content size)
174
+
case ezstd:decompress_using_ddict(Binary, DDict) of
175
+
Result when is_binary(Result) ->
176
+
HandlerPid ! {ws_text, Result};
177
+
Result when is_list(Result) ->
178
+
HandlerPid ! {ws_text, iolist_to_binary(Result)};
179
+
{error, <<"failed to decompress: ZSTD_CONTENTSIZE_UNKNOWN">>} ->
180
+
%% Frame doesn't have content size, use streaming with dictionary-loaded context
181
+
case ezstd:decompress_streaming(DCtx, Binary) of
182
+
StreamResult when is_binary(StreamResult) ->
183
+
HandlerPid ! {ws_text, StreamResult};
184
+
StreamResult when is_list(StreamResult) ->
185
+
HandlerPid ! {ws_text, iolist_to_binary(StreamResult)};
186
+
{error, _StreamReason} ->
187
+
%% Skip frames that fail to decompress
188
+
ok
189
+
end;
190
+
{error, _Reason} ->
191
+
%% Skip frames that fail to decompress
192
+
ok
193
end;
194
_ ->
195
%% No compression, ignore binary messages