* @param[in] request The current request.
* @param[in] fmt string to expand.
*/
-typedef ssize_t (*xlat_func_t)(TALLOC_CTX *ctx, char **out, size_t outlen,
+typedef ssize_t (*xlat_func_sync_t)(TALLOC_CTX *ctx, char **out, size_t outlen,
void const *mod_inst, void const *xlat_inst,
REQUEST *request, char const *fmt);
* @param[in] xlat_thread_inst Thread specific xlat instance.
* @param[in] request The current request.
* @param[in] in Input arguments.
+ * @param[in] uctx passed to registration function.
* @return
* - XLAT_ACTION_YIELD xlat function is waiting on an I/O event and
* has pushed a resumption function onto the stack.
#define XLAT_DEFAULT_BUF_LEN 2048
int xlat_register(void *mod_inst, char const *name,
- xlat_func_t func, xlat_escape_t escape,
+ xlat_func_sync_t func, xlat_escape_t escape,
xlat_instantiate_t instantiate, size_t inst_size,
size_t buf_len, bool async_safe);
int xlat_async_register(TALLOC_CTX *ctx,
- char const *name, xlat_func_t func,
+ char const *name, xlat_func_async_t func,
xlat_instantiate_t instantiate, size_t inst_size,
xlat_thread_instantiate_t thread_instantiate, size_t thread_inst_size,
void *uctx);
switch (node->type) {
case XLAT_FUNC:
- {
- fr_value_box_t *value;
- char *str;
- char *result_str;
- ssize_t slen;
+ switch (node->xlat->type) {
+ case XLAT_FUNC_SYNC:
+ {
+ fr_value_box_t *value;
+ char *str;
+ char *result_str;
+ ssize_t slen;
- result_str = fr_value_box_list_asprint(NULL, result, NULL, '\0');
- if (!result_str) return XLAT_ACTION_FAIL;
+ result_str = fr_value_box_list_asprint(NULL, result, NULL, '\0');
+ if (!result_str) return XLAT_ACTION_FAIL;
- if (node->xlat->buf_len > 0) {
- str = talloc_array(ctx, char, node->xlat->buf_len);
- str[0] = '\0'; /* Be sure the string is \0 terminated */
- }
+ if (node->xlat->buf_len > 0) {
+ str = talloc_array(ctx, char, node->xlat->buf_len);
+ str[0] = '\0'; /* Be sure the string is \0 terminated */
+ }
- XLAT_DEBUG("** [%i] %s(func) - %%{%s:%pS}", unlang_stack_depth(request), __FUNCTION__,
- node->fmt, result_str);
+ XLAT_DEBUG("** [%i] %s(func) - %%{%s:%pS}", unlang_stack_depth(request), __FUNCTION__,
+ node->fmt, result_str);
- slen = node->xlat->func(ctx, &str, node->xlat->buf_len,
- node->xlat->mod_inst, NULL, request, result_str);
- if (slen < 0) {
+ slen = node->xlat->func.sync(ctx, &str, node->xlat->buf_len,
+ node->xlat->mod_inst, NULL, request, result_str);
+ if (slen < 0) {
+ talloc_free(result_str);
+ talloc_free(str);
+ return XLAT_ACTION_FAIL;
+ }
+ if (slen == 0) break; /* Zero length result */
+ (void)talloc_get_type_abort(str, char);
+
+ /*
+ * Shrink the buffer
+ */
+ if ((node->xlat->buf_len > 0) && (slen > 0)) MEM(str = talloc_realloc_bstr(str, (size_t)slen));
+
+ /*
+ * Fixup talloc lineage and assign the
+ * output of the function to a box.
+ */
+ MEM(value = fr_value_box_alloc(ctx, FR_TYPE_STRING, NULL, false));
+ fr_value_box_strdup_buffer_shallow(value, value, NULL, talloc_steal(value, str), false);
+
+ RDEBUG2("EXPAND %%{%s:...}", node->xlat->name);
+ RDEBUG2(" --> %pV", value);
+ fr_cursor_append(out, value); /* Append the result of the expansion */
talloc_free(result_str);
- talloc_free(str);
- return XLAT_ACTION_FAIL;
}
- if (slen == 0) break; /* Zero length result */
- (void)talloc_get_type_abort(str, char);
+ break;
- /*
- * Shrink the buffer
- */
- if ((node->xlat->buf_len > 0) && (slen > 0)) MEM(str = talloc_realloc_bstr(str, (size_t)slen));
+ case XLAT_FUNC_ASYNC:
+ {
+ xlat_action_t action;
- /*
- * Fixup talloc lineage and assign the
- * output of the function to a box.
- */
- MEM(value = fr_value_box_alloc(ctx, FR_TYPE_STRING, NULL, false));
- fr_value_box_strdup_buffer_shallow(value, value, NULL, talloc_steal(value, str), false);
+ /* Fixme - Pass in instance and thread instance */
+ action = node->xlat->func.async(ctx, out, NULL, NULL, request, result, node->xlat->uctx);
+ switch (action) {
+ case XLAT_ACTION_PUSH_CHILD:
+ case XLAT_ACTION_YIELD:
+ case XLAT_ACTION_FAIL:
+ return action;
- RDEBUG2("EXPAND %%{%s:...}", node->xlat->name);
- RDEBUG2(" --> %pV", value);
- fr_cursor_append(out, value); /* Append the result of the expansion */
- talloc_free(result_str);
- }
+ case XLAT_ACTION_DONE: /* Process the result */
+ break;
+ }
+
+ RDEBUG2("EXPAND %%{%s:...}", node->xlat->name);
+ if (fr_cursor_current(out)) {
+ RDEBUG2(" --> %pV", fr_cursor_current(out)); /* Fixme - print multiple values */
+ } else {
+ RDEBUG2(" -->");
+ }
+ break;
+ }
+ }
break;
case XLAT_ALTERNATE:
XLAT_DEBUG("** [%i] %s(virtual) - %%{%s}", unlang_stack_depth(request), __FUNCTION__,
node->fmt);
- slen = node->xlat->func(ctx, &str, node->xlat->buf_len, node->xlat->mod_inst,
+ slen = node->xlat->func.sync(ctx, &str, node->xlat->buf_len, node->xlat->mod_inst,
NULL, request, NULL);
if (slen < 0) goto fail;
if (slen == 0) continue;
str = talloc_array(ctx, char, node->xlat->buf_len);
str[0] = '\0'; /* Be sure the string is \0 terminated */
}
- slen = node->xlat->func(ctx, &str, node->xlat->buf_len, node->xlat->mod_inst, NULL, request, NULL);
+ slen = node->xlat->func.sync(ctx, &str, node->xlat->buf_len, node->xlat->mod_inst, NULL, request, NULL);
if (slen < 0) {
talloc_free(str);
return NULL;
str = talloc_array(ctx, char, node->xlat->buf_len);
str[0] = '\0'; /* Be sure the string is \0 terminated */
}
- slen = node->xlat->func(ctx, &str, node->xlat->buf_len, node->xlat->mod_inst, NULL, request, child);
+ slen = node->xlat->func.sync(ctx, &str, node->xlat->buf_len, node->xlat->mod_inst, NULL, request, child);
talloc_free(child);
if (slen < 0) {
talloc_free(str);
* - -1 on failure.
*/
int xlat_register(void *mod_inst, char const *name,
- xlat_func_t func, xlat_escape_t escape,
+ xlat_func_sync_t func, xlat_escape_t escape,
xlat_instantiate_t instantiate, size_t inst_size,
size_t buf_len, bool async_safe)
{
new = true;
}
- c->func = func;
- c->type = XLAT_FUNC_BOXED;
+ c->func.sync = func;
+ c->type = XLAT_FUNC_SYNC;
c->buf_len = buf_len;
c->escape = escape;
c->mod_inst = mod_inst;
* - -1 on failure.
*/
int xlat_async_register(TALLOC_CTX *ctx,
- char const *name, xlat_func_t func,
+ char const *name, xlat_func_async_t func,
xlat_instantiate_t instantiate, size_t inst_size,
xlat_thread_instantiate_t thread_instantiate, size_t thread_inst_size,
void *uctx)
new = true;
}
- c->func = func;
- c->type = XLAT_FUNC_BOXED;
+ c->func.async = func;
+ c->type = XLAT_FUNC_ASYNC;
c->instantiate = instantiate;
c->thread_instantiate = thread_instantiate;
c->inst_size = inst_size;
c->thread_inst_size = thread_inst_size;
- c->async_safe = true;
+ c->async_safe = false; /* async safe in this case means it might yield */
c->uctx = uctx;
talloc_set_destructor(c, _xlat_free);
*out = NULL;
}
- rcode = xlat->func(ctx, out, xlat->buf_len, xlat->mod_inst, NULL, request, fmt);
+ rcode = xlat->func.sync(ctx, out, xlat->buf_len, xlat->mod_inst, NULL, request, fmt);
if (rcode <= 0) {
TALLOC_FREE(*out);
continue;
} else {
*out = NULL;
}
- slen = xlat->func(ctx, out, xlat->buf_len, xlat->mod_inst, NULL, request, fmt);
+ slen = xlat->func.sync(ctx, out, xlat->buf_len, xlat->mod_inst, NULL, request, fmt);
if (slen <= 0) TALLOC_FREE(*out);
return slen;
} else {
*out = NULL;
}
- rcode = xlat->func(ctx, out, xlat->buf_len, xlat->mod_inst, NULL, request, fmt);
+ rcode = xlat->func.sync(ctx, out, xlat->buf_len, xlat->mod_inst, NULL, request, fmt);
if (rcode > 0) return rcode;
TALLOC_FREE(*out);
}