25RCSID(
"$Id: 0aa072e860ced14c67e41a1ccb3c644ca0941bea $")
27#define LOG_PREFIX mctx->mi->name
29#include <brotli/encode.h>
30#include <brotli/decode.h>
32#include <freeradius-devel/util/atexit.h>
33#include <freeradius-devel/util/value.h>
35#include <freeradius-devel/server/module_rlm.h>
36#include <freeradius-devel/server/cf_parse.h>
38#include <freeradius-devel/unlang/xlat.h>
39#include <freeradius-devel/unlang/xlat_func.h>
64 {
L(
"font"), BROTLI_MODE_FONT },
65 {
L(
"generic"), BROTLI_MODE_GENERIC },
66 {
L(
"text"), BROTLI_MODE_TEXT },
94static inline CC_HINT(always_inline)
100 MEM(pool = talloc_pool(NULL, 4096));
109 void *ptr = talloc_size(uctx, size);
124 if (ret < 0)
return ret;
127 if ((
value > BROTLI_MAX_QUALITY) || (
value < BROTLI_MIN_QUALITY)) {
128 cf_log_err(ci,
"Allowed values are between %d-%d, got %d", BROTLI_MIN_QUALITY, BROTLI_MAX_QUALITY,
value);
141 if (ret < 0)
return ret;
144 if ((
value > BROTLI_MAX_WINDOW_BITS) || (
value < BROTLI_MIN_WINDOW_BITS)) {
145 cf_log_err(ci,
"Allowed values are between %d-%d, got %d", BROTLI_MIN_WINDOW_BITS, BROTLI_MAX_WINDOW_BITS,
value);
158 if (ret < 0)
return ret;
161 if ((
value > BROTLI_MAX_INPUT_BLOCK_BITS) || (
value < BROTLI_MIN_INPUT_BLOCK_BITS)) {
162 cf_log_err(ci,
"Allowed values are between %d-%d, got %d", BROTLI_MIN_INPUT_BLOCK_BITS, BROTLI_MAX_INPUT_BLOCK_BITS,
value);
190 BrotliEncoderState *state;
193 size_t available_out = 0, total_out = 0, total_in = 0;
208 total_in += vb->vb_length;
209 available_out += BrotliEncoderMaxCompressedSize(vb->vb_length);
218 BrotliEncoderSetParameter(state, BROTLI_PARAM_MODE,
inst->compress.mode);
219 BrotliEncoderSetParameter(state, BROTLI_PARAM_QUALITY,
inst->compress.quality);
220 BrotliEncoderSetParameter(state, BROTLI_PARAM_LGWIN,
inst->compress.window_bits);
221 if (
inst->compress.block_bits_is_set) BrotliEncoderSetParameter(state, BROTLI_PARAM_LGBLOCK,
inst->compress.block_bits);
222 BrotliEncoderSetParameter(state, BROTLI_PARAM_LARGE_WINDOW,
inst->large_window ? BROTLI_TRUE : BROTLI_FALSE);
223 BrotliEncoderSetParameter(state, BROTLI_PARAM_SIZE_HINT, total_in);
231 size_t available_in = vb->vb_length;
232 const uint8_t *next_in = vb->vb_octets;
233 bool more = fr_value_box_list_next(&data_vb->vb_group, vb) != NULL;
245 bret = BrotliEncoderCompressStream(state,
246 more ? BROTLI_OPERATION_PROCESS : BROTLI_OPERATION_FINISH,
247 &available_in, &next_in, &available_out, &out_buff, &total_out);
248 if (bret == BROTLI_FALSE) {
249 fr_assert_msg(0,
"BrotliEncoderCompressStream returned false, this shouldn't happen");
250 RERROR(
"BrotliEncoderCompressStream failed");
254 }
while (more && (available_in > 0) && (BrotliEncoderHasMoreOutput(state) == BROTLI_FALSE));
272 BrotliEncoderDestroyInstance(state);
273 talloc_free_children(pool);
299 BrotliDecoderState *state;
305 size_t available_out;
306 size_t total_out = 0;
319 total_in = data_vb->vb_length;
320 in_buff = data_vb->vb_octets;
321 available_out = (data_vb->vb_length * 2);
327 BrotliDecoderSetParameter(state, BROTLI_DECODER_PARAM_LARGE_WINDOW,
inst->large_window ? BROTLI_TRUE : BROTLI_FALSE);
330 switch (BrotliDecoderDecompressStream(state, &total_in, &in_buff, &available_out, &out_buff, &total_out)) {
332 case BROTLI_DECODER_RESULT_ERROR:
334 BrotliDecoderErrorCode error = BrotliDecoderGetErrorCode(state);
335 REDEBUG(
"Decompressing brotli data failed - %s", BrotliDecoderErrorString(error));
340 case BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT:
341 REDEBUG(
"Incomplete or truncated brotli data provided. Decompressor wants more input...");
345 case BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT:
347 size_t extra = out_vb->vb_length;
352 if ((out_vb->vb_length + extra) >
inst->decompress.max_size) {
353 RERROR(
"Decompressed data exceeds maximum size of %zu",
inst->decompress.max_size);
359 available_out += extra;
363 case BROTLI_DECODER_RESULT_SUCCESS:
364 if (BrotliDecoderIsFinished(state) == BROTLI_TRUE) {
374 BrotliDecoderDestroyInstance(state);
375 talloc_free_children(pool);
#define fr_atexit_thread_local(_name, _free, _uctx)
#define L(_str)
Helper for initialising arrays of string literals.
int cf_table_parse_int(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int.
int cf_pair_parse_value(TALLOC_CTX *ctx, void *out, UNUSED void *base, CONF_ITEM *ci, conf_parser_t const *rule)
Parses a CONF_PAIR into a C data type.
#define CONF_PARSER_TERMINATOR
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#define FR_CONF_OFFSET_IS_SET(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct,...
#define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
#define FR_CONF_OFFSET_TYPE_FLAGS(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Defines a CONF_PAIR to C data type mapping.
Common header for all CONF_* types.
#define cf_log_err(_cf, _fmt,...)
static int fr_dcursor_insert(fr_dcursor_t *cursor, void *v)
Insert directly after the current item.
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
static xlat_action_t brotli_xlat_decompress(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Decompress a brotli string.
static xlat_action_t brotli_xlat_compress(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Produce a brotli compressed string.
@ FR_TYPE_INT32
32 Bit signed integer.
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
@ FR_TYPE_OCTETS
Raw octets.
module_instance_t const * mi
Instance of the module being instantiated.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for instantiation calls.
xlat_t * module_rlm_xlat_register(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
module_t common
Common fields presented by all modules.
static const conf_parser_t config[]
static const conf_parser_t module_decompress_config[]
static int block_bits_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
static void brotli_talloc_free(UNUSED void *uctx, void *to_free)
static const conf_parser_t module_compress_config[]
bool large_window
non-standard "large", window size.
int quality
Default quality to use when compressing data.
static xlat_arg_parser_t const brotli_xlat_compress_args[]
static fr_table_num_sorted_t const brotli_mode[]
static xlat_arg_parser_t const brotli_xlat_decompress_args[]
static int mod_bootstrap(module_inst_ctx_t const *mctx)
static int window_bits_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
rlm_brotli_decompress_t decompress
Decompression settings.
static int quality_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
size_t max_size
Maximum amount we attempt to decode.
BrotliEncoderMode mode
Default mode to use when compressing data.
static TALLOC_CTX * brotli_pool_get(void)
bool block_bits_is_set
Whether block_bits has been set.
int block_bits
Default block bits to use when compressing data.
int window_bits
Default window bits to use when compressing data.
rlm_brotli_compress_t compress
Compression settings.
static _Thread_local TALLOC_CTX * brotli_pool
Thread-local pool for brotli state.
static const conf_parser_t module_config[]
static void * brotli_talloc_alloc(void *uctx, size_t size)
size_t inst_size
Size of the module's instance data.
void * data
Module's instance data.
void * boot
Data allocated during the boostrap phase.
eap_aka_sim_process_conf_t * inst
An element in a lexicographically sorted array of name to num mappings.
#define talloc_get_type_abort_const
bool required
Argument must be present, and non-empty.
#define XLAT_ARGS(_list,...)
Populate local variables with value boxes from the input list.
#define XLAT_ARG_PARSER_TERMINATOR
@ XLAT_ACTION_FAIL
An xlat function failed.
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition for a single argument consumend by an xlat function.
#define fr_type_is_group(_x)
int fr_value_box_mem_alloc(TALLOC_CTX *ctx, uint8_t **out, fr_value_box_t *dst, fr_dict_attr_t const *enumv, size_t len, bool tainted)
Pre-allocate an octets buffer for filling by the caller.
int fr_value_box_mem_realloc(TALLOC_CTX *ctx, uint8_t **out, fr_value_box_t *dst, size_t len)
Change the length of a buffer already allocated to a value box.
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
#define fr_value_box_list_foreach(_list_head, _iter)
static size_t char ** out
module_ctx_t const * mctx
Synthesised module calling ctx.
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.