[Asterisk-code-review] pbx: Add variable substitution API for extensions (asterisk[master])

N A asteriskteam at digium.com
Mon Nov 15 15:11:48 CST 2021


N A has uploaded this change for review. ( https://gerrit.asterisk.org/c/asterisk/+/17470 )


Change subject: pbx: Add variable substitution API for extensions
......................................................................

pbx: Add variable substitution API for extensions

Currently, variable substitution involving dialplan
extensions is quite clunky since it entails obtaining
the current dialplan location, backing it up, storing
the desired variables for substitution on the channel,
performing substitution, then restoring the original
location.

In addition to being clunky, things could also go wrong
if an async goto were to occur and change the dialplan
location during a substitution.

Fundamentally, there's no reason it needs to be done this
way, so new API is added to allow for directly passing in
the dialplan location for the purposes of variable
substitution so we don't need to mess with the channel
information anymore. Existing API is not changed.

ASTERISK-29745 #close

Change-Id: I23273bf27fa0efb64a606eebf9aa8e2f41a065e4
---
M include/asterisk/pbx.h
M main/pbx.c
M main/pbx_variables.c
3 files changed, 112 insertions(+), 1 deletion(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/70/17470/1

diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h
index c75e50a..6fe0e2d 100644
--- a/include/asterisk/pbx.h
+++ b/include/asterisk/pbx.h
@@ -1277,6 +1277,22 @@
 const char *ast_get_extension_app(struct ast_exten *e);
 const char *ast_get_extension_label(struct ast_exten *e);
 void *ast_get_extension_app_data(struct ast_exten *e);
+
+/*!
+ * \brief Fill a string buffer with the data at a dialplan extension
+ *
+ * \param buf String buffer
+ * \param bufsize Size of buf
+ * \param c Channel
+ * \param context Dialplan context
+ * \param exten Dialplan extension
+ * \param priority Dialplan priority
+ *
+ * \retval -1 Failed to obtain extension data
+ * \retval 0 Successfully obtained extension data
+ */
+int ast_get_extension_data(char *buf, int bufsize, struct ast_channel *c,
+	const char *context, const char *exten, int priority);
 /*! @} */
 
 /*! @name Registrar info functions ... */
@@ -1400,6 +1416,11 @@
 void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count);
 void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count);
 void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used);
+
+/*!
+ * \brief Substitutes variables, similar to pbx_substitute_variables_helper_full, but allows passing the context, extension, and priority in.
+ */
+void pbx_substitute_variables_helper_full_location(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used, char *context, char *exten, int pri);
 /*! @} */
 /*! @} */
 
@@ -1485,6 +1506,25 @@
  */
 int ast_async_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority);
 
+/*!
+ * \brief Parses a dialplan location into context, extension, priority
+ *
+ * \param chan Channel to execute on
+ * \param context Pointer to initial value for context.
+ * \param exten Pointer to initial value for exten.
+ * \param pri Pointer to initial value for pri
+ * \param ipri Pointer to integer value of priority
+ * \param mode Pointer to mode (or NULL if mode is not used)
+ * \param rest Pointer to buffer to capture rest of parsing (or NULL if not used)
+ *
+ * strsep should be used to initially populate context, exten, and pri prior
+ * to calling this function. All arguments are modified in place.
+ *
+ * \retval 0 success
+ * \retval non-zero failure
+ */
+int pbx_parse_location(struct ast_channel *chan, char *context, char *exten, char *pri, int *ipri, int *mode, char *rest);
+
 struct ast_custom_function* ast_custom_function_find(const char *name);
 
 /*!
diff --git a/main/pbx.c b/main/pbx.c
index 0cae9b8..09f6804 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -8610,6 +8610,26 @@
 	return e ? e->data : NULL;
 }
 
+int ast_get_extension_data(char *buf, int bufsize, struct ast_channel *c,
+	const char *context, const char *exten, int priority)
+{
+	struct ast_exten *e;
+	struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
+	ast_rdlock_contexts();
+	e = pbx_find_extension(c, NULL, &q, context, exten, priority, NULL, "", E_MATCH);
+	ast_unlock_contexts();
+	if (e) {
+		if (buf) {
+			const char *tmp = ast_get_extension_app_data(e);
+			if (tmp) {
+				ast_copy_string(buf, tmp, bufsize);
+			}
+		}
+		return 0;
+	}
+	return -1;
+}
+
 /*
  * Walking functions ...
  */
@@ -8807,6 +8827,43 @@
 	return __ast_goto_if_exists(chan, context, exten, priority, 1);
 }
 
+int pbx_parse_location(struct ast_channel *chan, char *context, char *exten, char *pri, int *ipri, int *mode, char *rest)
+{
+	/* do the strsep before here, so we don't have to alloc and free */
+	if (!exten) {
+		/* Only a priority in this one */
+		pri = context;
+		exten = NULL;
+		context = NULL;
+	} else if (!pri) {
+		/* Only an extension and priority in this one */
+		pri = exten;
+		exten = context;
+		context = NULL;
+	}
+	if (mode) {
+		if (*pri == '+') {
+			*mode = 1;
+			pri++;
+		} else if (*pri == '-') {
+			*mode = -1;
+			pri++;
+		}
+	}
+	if ((rest && sscanf(pri, "%30d%1s", ipri, rest) != 1) || sscanf(pri, "%30d", ipri) != 1) {
+		*ipri = ast_findlabel_extension(chan, context ? context : ast_channel_context(chan),
+			exten ? exten : ast_channel_exten(chan), pri,
+			S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL));
+		if (*ipri < 1) {
+			ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
+			return -1;
+		} else if (mode) {
+			*mode = 0;
+		}
+	}
+	return 0;
+}
+
 static int pbx_parseable_goto(struct ast_channel *chan, const char *goto_string, int async)
 {
 	char *exten, *pri, *context;
diff --git a/main/pbx_variables.c b/main/pbx_variables.c
index 91b5bbb..bd3cbcb 100644
--- a/main/pbx_variables.c
+++ b/main/pbx_variables.c
@@ -625,6 +625,11 @@
 
 void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
 {
+	pbx_substitute_variables_helper_full_location(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used, NULL, NULL, 0)
+}
+
+void pbx_substitute_variables_helper_full_location(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used, char *context, char *exten, int pri)
+{
 	/* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
 	const char *whereweare;
 	const char *orig_cp2 = cp2;
@@ -759,7 +764,16 @@
 				ast_debug(2, "Function %s result is '%s'\n", vars, cp4 ? cp4 : "(null)");
 			} else {
 				/* Retrieve variable value */
-				pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
+				/* For dialplan location, if we were told what to substitute explicitly, use that instead */
+				if (exten && !strcmp(vars, "EXTEN")) {
+					ast_copy_string(workspace, context, VAR_BUF_SIZE);
+				} else if (context && !strcmp(vars, "CONTEXT")) {
+					ast_copy_string(workspace, context, VAR_BUF_SIZE);
+				} else if (pri && !strcmp(vars, "PRIORITY")) {
+					snprintf(workspace, VAR_BUF_SIZE, "%d", pri);
+				} else {
+					pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
+				}
 			}
 			if (cp4) {
 				cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);

-- 
To view, visit https://gerrit.asterisk.org/c/asterisk/+/17470
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Change-Id: I23273bf27fa0efb64a606eebf9aa8e2f41a065e4
Gerrit-Change-Number: 17470
Gerrit-PatchSet: 1
Gerrit-Owner: N A <mail at interlinked.x10host.com>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20211115/a8173682/attachment.html>


More information about the asterisk-code-review mailing list