25 RCSID(
"$Id: 7b3928c13189dbc7d818be506d729cc2f74c4811 $")
27 #define LOG_PREFIX mctx->mi->name
31 #include <brotli/encode.h>
32 #include <brotli/decode.h>
34 #include <freeradius-devel/util/atexit.h>
35 #include <freeradius-devel/util/value.h>
37 #include <freeradius-devel/server/module_rlm.h>
38 #include <freeradius-devel/server/cf_parse.h>
40 #include <freeradius-devel/unlang/xlat.h>
41 #include <freeradius-devel/unlang/xlat_func.h>
66 {
L(
"font"), BROTLI_MODE_FONT },
67 {
L(
"generic"), BROTLI_MODE_GENERIC },
68 {
L(
"text"), BROTLI_MODE_TEXT },
96 static inline CC_HINT(always_inline)
102 MEM(pool = talloc_pool(NULL, 4096));
111 void *ptr = talloc_size(
uctx, size);
126 if (ret < 0)
return ret;
129 if ((
value > BROTLI_MAX_QUALITY) || (
value < BROTLI_MIN_QUALITY)) {
130 cf_log_err(ci,
"Allowed values are between %d-%d, got %d", BROTLI_MIN_QUALITY, BROTLI_MAX_QUALITY,
value);
143 if (ret < 0)
return ret;
146 if ((
value > BROTLI_MAX_WINDOW_BITS) || (
value < BROTLI_MIN_WINDOW_BITS)) {
147 cf_log_err(ci,
"Allowed values are between %d-%d, got %d", BROTLI_MIN_WINDOW_BITS, BROTLI_MAX_WINDOW_BITS,
value);
160 if (ret < 0)
return ret;
163 if ((
value > BROTLI_MAX_INPUT_BLOCK_BITS) || (
value < BROTLI_MIN_INPUT_BLOCK_BITS)) {
164 cf_log_err(ci,
"Allowed values are between %d-%d, got %d", BROTLI_MIN_INPUT_BLOCK_BITS, BROTLI_MAX_INPUT_BLOCK_BITS,
value);
192 BrotliEncoderState *state;
195 size_t available_out = 0, total_out = 0, total_in = 0;
210 total_in += vb->vb_length;
211 available_out += BrotliEncoderMaxCompressedSize(vb->vb_length);
220 BrotliEncoderSetParameter(state, BROTLI_PARAM_MODE,
inst->compress.mode);
221 BrotliEncoderSetParameter(state, BROTLI_PARAM_QUALITY,
inst->compress.quality);
222 BrotliEncoderSetParameter(state, BROTLI_PARAM_LGWIN,
inst->compress.window_bits);
223 if (
inst->compress.block_bits_is_set) BrotliEncoderSetParameter(state, BROTLI_PARAM_LGBLOCK,
inst->compress.block_bits);
224 BrotliEncoderSetParameter(state, BROTLI_PARAM_LARGE_WINDOW,
inst->large_window ? BROTLI_TRUE : BROTLI_FALSE);
225 BrotliEncoderSetParameter(state, BROTLI_PARAM_SIZE_HINT, total_in);
233 size_t available_in = vb->vb_length;
234 const uint8_t *next_in = vb->vb_octets;
235 bool more = fr_value_box_list_next(&data_vb->vb_group, vb) != NULL;
247 bret = BrotliEncoderCompressStream(state,
248 more ? BROTLI_OPERATION_PROCESS : BROTLI_OPERATION_FINISH,
249 &available_in, &next_in, &available_out, &out_buff, &total_out);
250 if (bret == BROTLI_FALSE) {
251 fr_assert_msg(0,
"BrotliEncoderCompressStream returned false, this shouldn't happen");
252 RERROR(
"BrotliEncoderCompressStream failed");
256 }
while (more && (available_in > 0) && (BrotliEncoderHasMoreOutput(state) == BROTLI_FALSE));
274 BrotliEncoderDestroyInstance(state);
275 talloc_free_children(pool);
301 BrotliDecoderState *state;
307 size_t available_out;
308 size_t total_out = 0;
321 total_in = data_vb->vb_length;
322 in_buff = data_vb->vb_octets;
323 available_out = (data_vb->vb_length * 2);
329 BrotliDecoderSetParameter(state, BROTLI_DECODER_PARAM_LARGE_WINDOW,
inst->large_window ? BROTLI_TRUE : BROTLI_FALSE);
332 switch (BrotliDecoderDecompressStream(state, &total_in, &in_buff, &available_out, &out_buff, &total_out)) {
334 case BROTLI_DECODER_RESULT_ERROR:
336 BrotliDecoderErrorCode error = BrotliDecoderGetErrorCode(state);
337 REDEBUG(
"Decompressing brotli data failed - %s", BrotliDecoderErrorString(error));
342 case BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT:
343 REDEBUG(
"Incomplete or truncated brotli data provided. Decompressor wants more input...");
347 case BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT:
349 size_t extra = out_vb->vb_length;
354 if ((out_vb->vb_length + extra) >
inst->decompress.max_size) {
355 RERROR(
"Decompressed data exceeds maximum size of %zu",
inst->decompress.max_size);
361 available_out += extra;
365 case BROTLI_DECODER_RESULT_SUCCESS:
366 if (BrotliDecoderIsFinished(state) == BROTLI_TRUE) {
376 BrotliDecoderDestroyInstance(state);
377 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
#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.
fr_dcursor_eval_t void const * uctx
#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.
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 TALLOC_CTX * brotli_pool_get(void)
static void * brotli_talloc_alloc(void *uctx, size_t size)
void * data
Module's instance data.
void * boot
Data allocated during the boostrap phase.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
An element in a lexicographically sorted array of name to num mappings.
Functions which we wish were included in the standard talloc distribution.
#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.