/
githubmirror
/
gnutls
Обзор
Документация
Войти
/
githubmirror
/
gnutls
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
lib/compress.c
357 строк
8 KB
Andreas Metzler
Use HAVE_ZLIB for both automake and autoconf
21 сен 2024, 12:27
Не верифицирован
21 сен 2024, 12:27
18ba7ac
Код
Авторство
О чём код?
/* * Copyright (C) 2017-2022 Red Hat, Inc. * * Authors: Nikos Mavrogiannopoulos, * Zoltan Fridrich * * This file is part of GnuTLS. * * The GnuTLS is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <https://www.gnu.org/licenses/> * */ #include "config.h" #include "compress.h" #ifdef _WIN32 #define RTLD_NOW 0 #define RTLD_GLOBAL 0 #else #include <dlfcn.h> #endif #ifndef Z_LIBRARY_SONAME #define Z_LIBRARY_SONAME "none" #endif #ifndef BROTLIENC_LIBRARY_SONAME #define BROTLIENC_LIBRARY_SONAME "none" #endif #ifndef BROTLIDEC_LIBRARY_SONAME #define BROTLIDEC_LIBRARY_SONAME "none" #endif #ifndef ZSTD_LIBRARY_SONAME #define ZSTD_LIBRARY_SONAME "none" #endif #ifdef HAVE_ZLIB #include "dlwrap/zlib.h" #endif #ifdef HAVE_LIBBROTLI #include "dlwrap/brotlienc.h" #include "dlwrap/brotlidec.h" #endif #ifdef HAVE_LIBZSTD #include "dlwrap/zstd.h" #endif #ifdef HAVE_ZLIB static void zlib_deinit(void) { gnutls_zlib_unload_library(); } static int zlib_init(void) { if (gnutls_zlib_ensure_library(Z_LIBRARY_SONAME, RTLD_NOW | RTLD_GLOBAL) < 0) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); return 0; } #endif /* HAVE_ZLIB */ #ifdef HAVE_LIBBROTLI static void brotli_deinit(void) { gnutls_brotlienc_unload_library(); gnutls_brotlidec_unload_library(); } static int brotli_init(void) { if (gnutls_brotlienc_ensure_library(BROTLIENC_LIBRARY_SONAME, RTLD_NOW | RTLD_GLOBAL) < 0) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); if (gnutls_brotlidec_ensure_library(BROTLIDEC_LIBRARY_SONAME, RTLD_NOW | RTLD_GLOBAL) < 0) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); return 0; } #endif /* HAVE_LIBBROTLI */ #ifdef HAVE_LIBZSTD static void zstd_deinit(void) { gnutls_zstd_unload_library(); } static int zstd_init(void) { if (gnutls_zstd_ensure_library(ZSTD_LIBRARY_SONAME, RTLD_NOW | RTLD_GLOBAL) < 0) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); return 0; } #endif /* HAVE_LIBZSTD */ typedef struct { gnutls_compression_method_t id; const char *name; int (*init)(void); void (*deinit)(void); } comp_entry; static comp_entry comp_algs[] = { { GNUTLS_COMP_NULL, "NULL", NULL, NULL }, #ifdef HAVE_ZLIB { GNUTLS_COMP_ZLIB, "ZLIB", zlib_init, zlib_deinit }, #endif #ifdef HAVE_LIBBROTLI { GNUTLS_COMP_BROTLI, "BROTLI", brotli_init, brotli_deinit }, #endif #ifdef HAVE_LIBZSTD { GNUTLS_COMP_ZSTD, "ZSTD", zstd_init, zstd_deinit }, #endif { GNUTLS_COMP_UNKNOWN, NULL, NULL, NULL } }; static const gnutls_compression_method_t alg_list[] = { GNUTLS_COMP_NULL, #ifdef HAVE_ZLIB GNUTLS_COMP_ZLIB, #endif #ifdef HAVE_LIBBROTLI GNUTLS_COMP_BROTLI, #endif #ifdef HAVE_LIBZSTD GNUTLS_COMP_ZSTD, #endif 0 }; /* Initialize given compression method * * Calling any of the compression functions without first initializing * the respective compression method results in undefined behavior. */ int _gnutls_compression_init_method(gnutls_compression_method_t method) { comp_entry *p; for (p = comp_algs; p->name; ++p) if (p->id == method) return p->init ? p->init() : GNUTLS_E_INVALID_REQUEST; return GNUTLS_E_INVALID_REQUEST; } /* Deinitialize all compression methods * * If no compression methods were initialized, * this function does nothing. */ void _gnutls_compression_deinit(void) { comp_entry *p; for (p = comp_algs; p->name; ++p) if (p->deinit) p->deinit(); } /** * gnutls_compression_get_name: * @algorithm: is a Compression algorithm * * Convert a #gnutls_compression_method_t value to a string. * * Returns: a pointer to a string that contains the name of the * specified compression algorithm, or %NULL. **/ const char *gnutls_compression_get_name(gnutls_compression_method_t algorithm) { const comp_entry *p; for (p = comp_algs; p->name; ++p) if (p->id == algorithm) return p->name; return NULL; } /** * gnutls_compression_get_id: * @name: is a compression method name * * The names are compared in a case insensitive way. * * Returns: an id of the specified in a string compression method, or * %GNUTLS_COMP_UNKNOWN on error. **/ gnutls_compression_method_t gnutls_compression_get_id(const char *name) { const comp_entry *p; for (p = comp_algs; p->name; ++p) if (!strcasecmp(p->name, name)) return p->id; return GNUTLS_COMP_UNKNOWN; } /** * gnutls_compression_list: * * Get a list of compression methods. * * Returns: a zero-terminated list of #gnutls_compression_method_t * integers indicating the available compression methods. **/ const gnutls_compression_method_t *gnutls_compression_list(void) { return alg_list; } /*************************/ /* Compression functions */ /*************************/ size_t _gnutls_compress_bound(gnutls_compression_method_t alg, size_t src_len) { switch (alg) { #ifdef HAVE_ZLIB case GNUTLS_COMP_ZLIB: return GNUTLS_ZLIB_FUNC(compressBound)(src_len); #endif #ifdef HAVE_LIBBROTLI case GNUTLS_COMP_BROTLI: return GNUTLS_BROTLIENC_FUNC(BrotliEncoderMaxCompressedSize)( src_len); #endif #ifdef HAVE_LIBZSTD case GNUTLS_COMP_ZSTD: return GNUTLS_ZSTD_FUNC(ZSTD_compressBound)(src_len); #endif default: return 0; } return 0; } int _gnutls_compress(gnutls_compression_method_t alg, uint8_t *dst, size_t dst_len, const uint8_t *src, size_t src_len) { int ret = GNUTLS_E_COMPRESSION_FAILED; switch (alg) { #ifdef HAVE_ZLIB case GNUTLS_COMP_ZLIB: { int err; uLongf comp_len = dst_len; err = GNUTLS_ZLIB_FUNC(compress)(dst, &comp_len, src, src_len); if (err != Z_OK) return gnutls_assert_val(GNUTLS_E_COMPRESSION_FAILED); ret = comp_len; } break; #endif #ifdef HAVE_LIBBROTLI case GNUTLS_COMP_BROTLI: { BROTLI_BOOL err; size_t comp_len = dst_len; err = GNUTLS_BROTLIENC_FUNC(BrotliEncoderCompress)( BROTLI_DEFAULT_QUALITY, BROTLI_DEFAULT_WINDOW, BROTLI_DEFAULT_MODE, src_len, src, &comp_len, dst); if (!err) return gnutls_assert_val(GNUTLS_E_COMPRESSION_FAILED); ret = comp_len; } break; #endif #ifdef HAVE_LIBZSTD case GNUTLS_COMP_ZSTD: { size_t comp_len; comp_len = GNUTLS_ZSTD_FUNC(ZSTD_compress)( dst, dst_len, src, src_len, ZSTD_CLEVEL_DEFAULT); if (GNUTLS_ZSTD_FUNC(ZSTD_isError)(comp_len)) return gnutls_assert_val(GNUTLS_E_COMPRESSION_FAILED); ret = comp_len; } break; #endif default: return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); } #ifdef COMPRESSION_DEBUG _gnutls_debug_log("Compression ratio: %f\n", (float)((float)ret / (float)src_len)); #endif return ret; } int _gnutls_decompress(gnutls_compression_method_t alg, uint8_t *dst, size_t dst_len, const uint8_t *src, size_t src_len) { int ret = GNUTLS_E_DECOMPRESSION_FAILED; switch (alg) { #ifdef HAVE_ZLIB case GNUTLS_COMP_ZLIB: { int err; uLongf plain_len = dst_len; err = GNUTLS_ZLIB_FUNC(uncompress)(dst, &plain_len, src, src_len); if (err != Z_OK) return gnutls_assert_val(GNUTLS_E_DECOMPRESSION_FAILED); ret = plain_len; } break; #endif #ifdef HAVE_LIBBROTLI case GNUTLS_COMP_BROTLI: { BrotliDecoderResult err; size_t plain_len = dst_len; err = GNUTLS_BROTLIDEC_FUNC( BrotliDecoderDecompress)(src_len, src, &plain_len, dst); if (err != BROTLI_DECODER_RESULT_SUCCESS) return gnutls_assert_val(GNUTLS_E_DECOMPRESSION_FAILED); ret = plain_len; } break; #endif #ifdef HAVE_LIBZSTD case GNUTLS_COMP_ZSTD: { size_t plain_len; plain_len = GNUTLS_ZSTD_FUNC(ZSTD_decompress)(dst, dst_len, src, src_len); if (GNUTLS_ZSTD_FUNC(ZSTD_isError)(plain_len)) return gnutls_assert_val(GNUTLS_E_DECOMPRESSION_FAILED); ret = plain_len; } break; #endif default: return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); } return ret; }