From: Arran Cudbard-Bell Date: Tue, 21 Nov 2017 21:33:36 +0000 (+0000) Subject: Wire in async xlat functions X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e179780f7025c77b031bf9225f62627ef57e1b65;p=thirdparty%2Ffreeradius-server.git Wire in async xlat functions --- diff --git a/src/include/xlat.h b/src/include/xlat.h index 21315c79b6e..c86640165e7 100644 --- a/src/include/xlat.h +++ b/src/include/xlat.h @@ -62,7 +62,7 @@ typedef size_t (*xlat_escape_t)(REQUEST *request, char *out, size_t outlen, char * @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); @@ -76,6 +76,7 @@ typedef ssize_t (*xlat_func_t)(TALLOC_CTX *ctx, char **out, size_t outlen, * @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. @@ -144,12 +145,12 @@ size_t xlat_snprint(char *buffer, size_t bufsize, xlat_exp_t const *node); #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); diff --git a/src/main/xlat.h b/src/main/xlat.h index 583e29a1b40..e5f90164291 100644 --- a/src/main/xlat.h +++ b/src/main/xlat.h @@ -36,14 +36,18 @@ * */ typedef enum { - XLAT_FUNC_STRING, //!< Ingests and excretes strings. - XLAT_FUNC_BOXED //!< Ingests and excretes value boxes. -} xlat_func_type_t; + XLAT_FUNC_SYNC, //!< Ingests and excretes strings. + XLAT_FUNC_ASYNC //!< Ingests and excretes value boxes (and may yield) +} xlat_func_sync_type_t; typedef struct xlat_t { char const *name; //!< Name of xlat function. - xlat_func_t func; //!< xlat function. - xlat_func_type_t type; //!< Type of xlat function. + + union { + xlat_func_sync_t sync; //!< synchronous xlat function (async safe). + xlat_func_async_t async; //!< async xlat function (async unsafe). + } func; + xlat_func_sync_type_t type; //!< Type of xlat function. xlat_instantiate_t instantiate; //!< Instantiation function. xlat_thread_instantiate_t thread_instantiate; //!< Thread instantiation function. diff --git a/src/main/xlat_eval.c b/src/main/xlat_eval.c index 5c4edf56567..16c293ab9c4 100644 --- a/src/main/xlat_eval.c +++ b/src/main/xlat_eval.c @@ -515,50 +515,79 @@ xlat_action_t xlat_frame_eval_repeat(TALLOC_CTX *ctx, fr_cursor_t *out, 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: @@ -694,7 +723,7 @@ xlat_action_t xlat_frame_eval(TALLOC_CTX *ctx, fr_cursor_t *out, xlat_exp_t cons 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; @@ -861,7 +890,7 @@ static char *xlat_aprint(TALLOC_CTX *ctx, REQUEST *request, xlat_exp_t const * c 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; @@ -939,7 +968,7 @@ static char *xlat_aprint(TALLOC_CTX *ctx, REQUEST *request, xlat_exp_t const * c 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); diff --git a/src/main/xlat_func.c b/src/main/xlat_func.c index b3841e7b924..c7a9611fc69 100644 --- a/src/main/xlat_func.c +++ b/src/main/xlat_func.c @@ -624,7 +624,7 @@ xlat_t *xlat_find(char const *name) * - -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) { @@ -664,8 +664,8 @@ int xlat_register(void *mod_inst, char const *name, 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; @@ -732,7 +732,7 @@ static int _xlat_free(xlat_t *xlat) * - -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) @@ -773,13 +773,13 @@ int xlat_async_register(TALLOC_CTX *ctx, 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); @@ -889,7 +889,7 @@ static ssize_t xlat_redundant(TALLOC_CTX *ctx, char **out, NDEBUG_UNUSED size_t *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; @@ -953,7 +953,7 @@ static ssize_t xlat_load_balance(TALLOC_CTX *ctx, char **out, NDEBUG_UNUSED size } 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; @@ -980,7 +980,7 @@ static ssize_t xlat_load_balance(TALLOC_CTX *ctx, char **out, NDEBUG_UNUSED size } 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); }