1
1
/* * @file
2
2
3
- Transforms content using gzip, deflate or brotli
3
+ Transforms content using gzip, deflate, brotli or zstd
4
4
5
5
@section license License
6
6
23
23
24
24
#include < cstring>
25
25
#include < zlib.h>
26
+ #if HAVE_ZSTD_H
27
+ #include < zstd.h>
28
+ #endif
26
29
27
30
#include " ts/apidefs.h"
28
31
#include " tscore/ink_config.h"
@@ -71,6 +74,10 @@ const int BROTLI_COMPRESSION_LEVEL = 6;
71
74
const int BROTLI_LGW = 16 ;
72
75
#endif
73
76
77
+ #if HAVE_ZSTD_H
78
+ const int ZSTD_COMPRESSION_LEVEL = 6 ;
79
+ #endif
80
+
74
81
static const char *global_hidden_header_name = nullptr ;
75
82
76
83
static TSMutex compress_config_mutex = nullptr ;
@@ -191,6 +198,16 @@ data_alloc(int compression_type, int compression_algorithms)
191
198
data->bstrm .avail_out = 0 ;
192
199
data->bstrm .total_out = 0 ;
193
200
}
201
+ #endif
202
+ #if HAVE_ZSTD_H
203
+ data->zstd_ctx = nullptr ;
204
+ if (compression_type & COMPRESSION_TYPE_ZSTD) {
205
+ debug (" zstd compression. Create Zstd Compression Context." );
206
+ data->zstd_ctx = ZSTD_createCCtx ();
207
+ if (!data->zstd_ctx ) {
208
+ fatal (" Zstd Compression Context Creation Failed" );
209
+ }
210
+ }
194
211
#endif
195
212
return data;
196
213
}
@@ -212,6 +229,11 @@ data_destroy(Data *data)
212
229
#if HAVE_BROTLI_ENCODE_H
213
230
BrotliEncoderDestroyInstance (data->bstrm .br );
214
231
#endif
232
+ #if HAVE_ZSTD_H
233
+ if (data->zstd_ctx ) {
234
+ ZSTD_freeCCtx (data->zstd_ctx );
235
+ }
236
+ #endif
215
237
216
238
TSfree (data);
217
239
}
@@ -233,6 +255,9 @@ content_encoding_header(TSMBuffer bufp, TSMLoc hdr_loc, const int compression_ty
233
255
} else if (compression_type & COMPRESSION_TYPE_DEFLATE && (algorithm & ALGORITHM_DEFLATE)) {
234
256
value = TS_HTTP_VALUE_DEFLATE;
235
257
value_len = TS_HTTP_LEN_DEFLATE;
258
+ } else if (compression_type & COMPRESSION_TYPE_ZSTD && (algorithm & ALGORITHM_ZSTD)) {
259
+ value = " zstd" ;
260
+ value_len = strlen (" zstd" );
236
261
}
237
262
238
263
if (value_len == 0 ) {
@@ -357,6 +382,16 @@ compress_transform_init(TSCont contp, Data *data)
357
382
data->downstream_vio = TSVConnWrite (downstream_conn, contp, data->downstream_reader , INT64_MAX);
358
383
}
359
384
385
+ #if HAVE_ZSTD_H
386
+ if (data->compression_type & COMPRESSION_TYPE_ZSTD) {
387
+ zstd_compress_init (data);
388
+ if (!data->zstd_cctx ) {
389
+ TSError (" Failed to create Zstandard compression context" );
390
+ return ;
391
+ }
392
+ }
393
+ #endif
394
+
360
395
TSHandleMLocRelease (bufp, TS_NULL_MLOC, hdr_loc);
361
396
}
362
397
@@ -462,6 +497,40 @@ brotli_transform_one(Data *data, const char *upstream_buffer, int64_t upstream_l
462
497
}
463
498
#endif
464
499
500
+ #if HAVE_ZSTD_H
501
+ static void
502
+ zstd_compress_init (Data *data)
503
+ {
504
+ data->zstd_cctx = ZSTD_createCCtx ();
505
+ if (!data->zstd_cctx ) {
506
+ error (" Failed to initialize Zstd compression context" );
507
+ }
508
+ }
509
+
510
+ static void
511
+ zstd_compress_finish (Data *data)
512
+ {
513
+ if (data->zstd_cctx ) {
514
+ ZSTD_freeCCtx (data->zstd_cctx );
515
+ data->zstd_cctx = nullptr ;
516
+ }
517
+ }
518
+
519
+ static void
520
+ zstd_compress_one (Data *data, const char *upstream_buffer, int64_t upstream_length)
521
+ {
522
+ char output_buffer[ZSTD_CStreamOutSize ()];
523
+ size_t compressed_size = ZSTD_compressCCtx (data->zstd_cctx , output_buffer, sizeof (output_buffer), upstream_buffer,
524
+ upstream_length, ZSTD_COMPRESSION_LEVEL);
525
+ if (ZSTD_isError (compressed_size)) {
526
+ error (" Zstd compression failed: %s" , ZSTD_getErrorName (compressed_size));
527
+ return ;
528
+ }
529
+ TSIOBufferWrite (data->downstream_buffer , output_buffer, compressed_size);
530
+ data->downstream_length += compressed_size;
531
+ }
532
+ #endif
533
+
465
534
static void
466
535
compress_transform_one (Data *data, TSIOBufferReader upstream_reader, int amount)
467
536
{
@@ -488,6 +557,11 @@ compress_transform_one(Data *data, TSIOBufferReader upstream_reader, int amount)
488
557
if (data->compression_type & COMPRESSION_TYPE_BROTLI && (data->compression_algorithms & ALGORITHM_BROTLI)) {
489
558
brotli_transform_one (data, upstream_buffer, upstream_length);
490
559
} else
560
+ #endif
561
+ #if HAVE_ZSTD_H
562
+ if (data->compression_type & COMPRESSION_TYPE_ZSTD && (data->compression_algorithms & ALGORITHM_ZSTD)) {
563
+ zstd_compress_one (data, upstream_buffer, upstream_length);
564
+ } else
491
565
#endif
492
566
if ((data->compression_type & (COMPRESSION_TYPE_GZIP | COMPRESSION_TYPE_DEFLATE)) &&
493
567
(data->compression_algorithms & (ALGORITHM_GZIP | ALGORITHM_DEFLATE))) {
@@ -576,6 +650,12 @@ compress_transform_finish(Data *data)
576
650
brotli_transform_finish (data);
577
651
debug (" compress_transform_finish: brotli compression finish" );
578
652
} else
653
+ #endif
654
+ #if HAVE_ZSTD_H
655
+ if (data->compression_type & COMPRESSION_TYPE_ZSTD && data->compression_algorithms & ALGORITHM_ZSTD) {
656
+ zstd_compress_finish (data);
657
+ debug (" compress_transform_finish: zstd compression finish" );
658
+ } else
579
659
#endif
580
660
if ((data->compression_type & (COMPRESSION_TYPE_GZIP | COMPRESSION_TYPE_DEFLATE)) &&
581
661
(data->compression_algorithms & (ALGORITHM_GZIP | ALGORITHM_DEFLATE))) {
@@ -771,6 +851,11 @@ transformable(TSHttpTxn txnp, bool server, HostConfiguration *host_configuration
771
851
compression_acceptable = 1 ;
772
852
}
773
853
*compress_type |= COMPRESSION_TYPE_GZIP;
854
+ } else if (strncasecmp (value, " zstd" , sizeof (" zstd" ) - 1 ) == 0 ) {
855
+ if (*algorithms & ALGORITHM_ZSTD) {
856
+ compression_acceptable = 1 ;
857
+ }
858
+ *compress_type |= COMPRESSION_TYPE_ZSTD;
774
859
}
775
860
}
776
861
0 commit comments