27RCSID(
"$Id: 8ee0c51352a0ab98ff64d91fbb8217480f331f68 $")
29#include <freeradius-devel/io/schedule.h>
30#include <freeradius-devel/server/base.h>
31#include <freeradius-devel/unlang/xlat_priv.h>
32#include <freeradius-devel/util/debug.h>
33#include <freeradius-devel/util/heap.h>
53 return CMP(a->
node->call.id, b->node->call.id);
66 return CMP(a->
node->call.id, b->node->call.id);
83 DEBUG4(
"Cleaning up xlat thread instance (%p/%p)", xt, xt->
data);
107 size_t extra_headers = 0;
108 size_t extra_mem = 0;
125 extra_mem +=
sizeof(*call->
func->
mctx);
128 if (extra_headers || extra_mem) {
147 talloc_set_name(xt->
data,
"xlat_%s_thread_t", call->
func->
name);
167 DEBUG4(
"Alloced xlat thread instance (%p/%p)", xt, xt->
data);
189 call = &xi->
node->call;
201 DEBUG4(
"Cleaning up xlat instance (%p/%p)", xi, xi->
data);
219 (void)talloc_get_type_abort(node,
xlat_exp_t);
245 talloc_set_name(xi->
data,
"xlat_%s_t", call->
func->
name);
254 "Method environment for module %s, xlat %s declared, "
273 .dict_def = call->dict,
274 .list_def = request_attr_request
312 return node->group->instantiated;
342 TALLOC_FREE(call->
inst);
386 if (
head->flags.needs_resolving) {
390 if (
head->instantiated)
return 0;
393 if (ret < 0)
return ret;
395 head->instantiated =
true;
462 DEBUG3(
"Instantiating xlat \"%s\" node %p, instance %p, new thread instance %p",
531 fr_assert(!xi->node->flags.needs_resolving);
556 fr_assert(!node->call.func->thread_detach);
558 if (node->call.inst) {
560 if (ret < 0)
return ret;
562 talloc_set_destructor(node->call.inst, NULL);
563 TALLOC_FREE(node->call.inst);
566 if (node->call.thread_inst) {
567 if (!node->call.ephemeral) {
569 if (ret < 0)
return ret;
572 talloc_set_destructor(node->call.thread_inst, NULL);
573 TALLOC_FREE(node->call.inst);
597 static uint64_t call_id;
608 DEBUG3(
"Instantiating xlat \"%s\" node %p, new instance %p", call->
func->
name, node, call->
inst);
620 node->call.id = call_id++;
624 TALLOC_FREE(call->
inst);
638 return node->group->instantiated;
665 "xlat.runtime_el likely not set in tmpl rules when it should've been. "
666 "Use unlang_interpret_event_list() to get the current event list from the request");
674 if (
head->instantiated)
return 0;
681 if (ret < 0)
return ret;
683 head->instantiated =
true;
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
call_env_t * call_env_alloc(TALLOC_CTX *ctx, char const *name, call_env_method_t const *call_env_method, tmpl_rules_t const *t_rules, CONF_SECTION *cs, call_env_ctx_t const *cec)
Given a call_env_method, parse all call_env_pair_t in the context of a specific call to an xlat or mo...
Structures and functions for handling call environments.
@ CALL_ENV_CTX_TYPE_XLAT
The callenv is registered to an xlat.
size_t inst_size
Size of per call env.
struct call_env_ctx_s call_env_ctx_t
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
int fr_heap_insert(fr_heap_t **hp, void *data)
Insert a new element into the heap.
void * fr_heap_pop(fr_heap_t **hp)
Remove a node from the heap.
int fr_heap_extract(fr_heap_t **hp, void *data)
Remove a node from the heap.
static bool fr_heap_entry_inserted(fr_heap_index_t heap_idx)
Check if an entry is inserted into a heap.
static void * fr_heap_peek_at(fr_heap_t *h, fr_heap_index_t idx)
Peek at a specific index in the heap.
static unsigned int fr_heap_num_elements(fr_heap_t *h)
Return the number of elements in the heap.
#define fr_heap_talloc_alloc(_ctx, _cmp, _talloc_type, _field, _init)
Creates a heap that verifies elements are of a specific talloc type.
#define fr_heap_foreach(_heap, _type, _data)
Iterate over the contents of a heap.
Stores all information relating to an event list.
module_instance_t const * mi
Instance of the module being instantiated.
void * thread
Thread specific instance data.
static module_ctx_t * module_ctx_from_inst(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx)
Allocate a module calling ctx on the heap based on an instance ctx.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for module calls.
char const * name
Instance name e.g. user_database.
CONF_SECTION * conf
Module's instance configuration.
void * data
Thread specific instance data.
static module_thread_instance_t * module_thread(module_instance_t const *mi)
Retrieve module/thread specific instance for a module.
Optional arguments passed to vp_tmpl functions.
#define talloc_get_type_abort_const
#define talloc_zero_pooled_object(_ctx, _type, _num_subobjects, _total_subobjects_size)
static fr_event_list_t * el
fr_heap_index_t idx
Entry in heap of xlat instances.
xlat_exp_t * node
Node this data relates to.
void * data
Thread specific instance data.
xlat_exp_t const * node
Node this data relates to.
fr_heap_index_t idx
Entry in heap of xlat thread instances.
fr_event_list_t * el
Event list associated with this thread.
void * data
xlat node specific instance data.
#define XLAT_VERIFY(_node)
int xlat_resolve(xlat_exp_head_t *head, xlat_res_rules_t const *xr_rules)
Walk over an xlat tree recursively, resolving any unresolved functions or references.
call_env_t const * call_env
Per call environment.
module_ctx_t const * mctx
A synthesised module calling ctx containing module global and thread instance data.
Instance data for an xlat expansion node.
Thread specific instance data for xlat expansion node.
#define XLAT_THREAD_INST_CTX(_inst, _thread, _ex, _mctx, _el, _uctx)
Wrapper to create a xlat_thread_inst_ctx_t as a compound literal.
#define XLAT_INST_CTX(_inst, _ex, _mctx, _uctx)
Wrapper to create a xlat_inst_ctx_t as a compound literal.
int xlat_eval_walk(xlat_exp_head_t *head, xlat_walker_t walker, xlat_type_t type, void *uctx)
Walk over all xlat nodes (depth first) in a xlat expansion, calling a callback.
xlat_thread_inst_t * xlat_thread_instance_find(xlat_exp_t const *node)
Retrieve xlat/thread specific instance data.
static int _xlat_inst_detach(xlat_inst_t *xi)
Destructor for xlat_inst_t.
int xlat_instance_register_func(xlat_exp_t *node)
Callback for creating "permanent" instance data for a xlat_exp_t.
void xlat_thread_detach(void)
Destroy any thread specific xlat instances.
static int xlat_instance_register(xlat_exp_head_t *head)
Create instance data for "permanent" xlats.
static int _xlat_instantiate_ephemeral_walker(xlat_exp_t *node, void *uctx)
Callback for creating "ephemeral" instance data for a xlat_exp_t.
static int xlat_instantiate_ephemeral(xlat_exp_head_t *head, fr_event_list_t *el)
Create instance data for "ephemeral" xlats.
int xlat_instantiate(void)
Call instantiation functions for all registered, "permanent" xlats.
static int8_t _xlat_inst_cmp(void const *one, void const *two)
Compare two xlat instances based on node pointer.
static int8_t _xlat_thread_inst_cmp(void const *one, void const *two)
Compare two thread instances based on node pointer.
int xlat_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Create thread specific instance tree and create thread instances.
static int _xlat_inst_walker(xlat_exp_t *node, UNUSED void *uctx)
static xlat_inst_t * xlat_inst_alloc(xlat_exp_t *node)
Allocate instance data for an xlat expansion.
static int _xlat_thread_inst_detach(xlat_thread_inst_t *xt)
Destructor for xlat_thread_inst_t.
void xlat_instances_free(void)
Walk over all registered instance data and free them explicitly.
static fr_heap_t * xlat_inst_tree
Holds instance data created by xlat_instantiate.
static int xlat_instantiate_init(void)
Initialise the xlat instance data code.
int xlat_finalize(xlat_exp_head_t *head, fr_event_list_t *runtime_el)
Bootstrap static xlats, or instantiate ephemeral ones.
static _Thread_local fr_heap_t * xlat_thread_inst_tree
Holds thread specific instance data created by xlat_instantiate.
int xlat_instance_unregister_func(xlat_exp_t *node)
Remove a node from the list of xlat instance data.
static xlat_thread_inst_t * xlat_thread_inst_alloc(TALLOC_CTX *ctx, fr_event_list_t *el, xlat_inst_t *xi)
Create thread instances where needed.
char const * name
Name of xlat function.
char const * thread_inst_type
C type of thread instance structure.
module_inst_ctx_t * mctx
Original module instantiation ctx if this xlat was registered by a module.
bool ephemeral
Instance data is ephemeral (not inserted) into the instance tree.
xlat_instantiate_t instantiate
Instantiation function.
size_t thread_inst_size
Size of the thread instance data to pre-allocate.
xlat_detach_t detach
Destructor for when xlat instances are freed.
void * thread_uctx
uctx to pass to instantiation functions.
call_env_method_t const * call_env_method
Optional tmpl expansions performed before calling the xlat.
size_t inst_size
Size of instance data to pre-allocate.
@ XLAT_GROUP
encapsulated string of xlats
@ XLAT_INVALID
Bad expansion.
xlat_thread_instantiate_t thread_instantiate
Thread instantiation function.
xlat_thread_inst_t * thread_inst
Thread specific instance.
xlat_inst_t * inst
Instance data for the xlat_t.
char const * inst_type
C type of instance structure.
xlat_t const * func
The xlat expansion to expand format with.
uint64_t id
Identifier unique to each permanent xlat node.
xlat_type_t _CONST type
type of this expansion.
xlat_thread_detach_t thread_detach
Destructor for when xlat thread instance data is freed.
void * uctx
uctx to pass to instantiation functions.