]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Wire in async xlat functions
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Tue, 21 Nov 2017 21:33:36 +0000 (21:33 +0000)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Tue, 21 Nov 2017 21:33:43 +0000 (21:33 +0000)
src/include/xlat.h
src/main/xlat.h
src/main/xlat_eval.c
src/main/xlat_func.c

index 21315c79b6ea7360c4a8ee3b9081a456b3edd4d4..c86640165e74a059c0281cd8e1f0e609c021dff8 100644 (file)
@@ -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);
index 583e29a1b406c0d3df62f3ad73e326f25140ae31..e5f90164291b7ddee4a57dc6dc40f70a6a01ec86 100644 (file)
  *
  */
 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.
index 5c4edf565677539f6df6ef4d0c55050307b812e5..16c293ab9c4fe770cd85bd5dd989299e014263ad 100644 (file)
@@ -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);
index b3841e7b924db280a68914218f89fd8d12c30857..c7a9611fc69662fbe84b8f63bcdc431673df0bd9 100644 (file)
@@ -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);
                }