Modifying the behaviour of the dialplan engine

the 'data' field in action tags may now refer to variables and api functions
to be expanded at runtime.

Syntax:

$varname
${varname}
&func_name(func args)


Exception:
variables that are numeric are still expanded at dialplan compile time based on the regex eg $1 $2 etc

Example:

<extension name="1000">
  <condition field="destination_number" expression="^(1000)$">
    <action appplication="my_route_app" data="$1"/>
    <action appplication="bridge" data="$destination"/>
  </condition>
</extension>

Here the $1 is ecaluated before the call begins setting it to 1000 based on the regex ^(1000)$
$destination is evaluated on the fly in execution once the my_route_app has run and has had a 
chance to set the variable 'destination' to the correct value.



git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2994 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2006-10-07 19:54:04 +00:00
parent 4ede7f7593
commit 741b8329b9
6 changed files with 150 additions and 8 deletions

View File

@ -400,6 +400,14 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_name_state(char *name);
*/
SWITCH_DECLARE(void) switch_channel_event_set_data(switch_channel_t *channel, switch_event_t *event);
/*!
\brief Expand varaibles in a string based on the variables in a paticular channel
\param channel channel to expand the variables from
\param in the original string
\return the original string if no expansion takes place otherwise a new string that must be freed
\note it's necessary to test if the return val is the same as the input and free the string if it is not.
*/
SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel, char *in);
// These may go away
SWITCH_DECLARE(switch_status_t) switch_channel_set_raw_mode (switch_channel_t *channel, int freq, int bits, int channels, int ms, int kbps);

View File

@ -174,17 +174,16 @@ static int parse_exten(switch_core_session_t *session, switch_xml_t xexten, swit
char *cmd = switch_core_session_strdup(session, field + 1);
char *arg;
SWITCH_STANDARD_STREAM(stream);
if (cmd) {
if ((arg = strchr(cmd, ' '))) {
*arg++ = '\0';
}
stream.data = retbuf;
stream.end = stream.data;
stream.data_size = sizeof(retbuf);
stream.write_function = switch_console_stream_write;
if (switch_api_execute(cmd, arg, session, &stream) == SWITCH_STATUS_SUCCESS) {
field_data = retbuf;
}
free(stream.data);
}
} else {
field_data = switch_caller_get_field_by_name(caller_profile, field);

View File

@ -128,7 +128,7 @@ static switch_status_t switch_console_logger(const switch_log_node_t *node, swit
}
if (!log_hash || (((all_level > - 1) || lookup) && level >= node->level)) {
fprintf(handle, node->data);
fprintf(handle, "%s", node->data);
}
} else {
fprintf(stderr, "HELP I HAVE NO CONSOLE TO LOG TO!\n");

View File

@ -999,3 +999,125 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_answer(switch_channel_t *
return SWITCH_STATUS_FALSE;
}
SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel, char *in)
{
char *p, *c;
char *data, *indup;
int sp = 0, len = 0, olen = 0, vtype = 0, br = 0, vnamepos, vvalpos, cpos, ppos, block = 128;
char *sub_val = NULL, *func_val = NULL;
if (!strchr(in, '$') && !strchr(in, '&')) {
return in;
}
olen = strlen(in);
indup = strdup(in);
if ((data = malloc(olen))) {
memset(data, 0, olen);
c = data;
for(p = indup; *p; p++) {
vtype = 0;
if (*p == '$') {
vtype = 1;
}
if (*p == '&') {
vtype = 2;
}
if (vtype) {
char *s = p, *e, *vname, *vval = NULL;
int nlen;
s++;
if (*s == '{') {
br = 1;
s++;
}
e = s;
vname = s;
while (*e) {
if (!br && *e == ' ') {
*e++ = '\0';
sp++;
break;
}
if (br == 1 && *e == '}') {
br = 0;
*e++ = '\0';
break;
}
if (vtype == 2) {
if (*e == '(') {
*e++ = '\0';
vval = e;
br = 2;
}
if (br == 2 && *e == ')') {
*e++ = '\0';
br = 0;
break;
}
}
e++;
}
p = e;
if (vtype == 1) {
sub_val = switch_channel_get_variable(channel, vname);
} else {
switch_stream_handle_t stream = {0};
SWITCH_STANDARD_STREAM(stream);
if (stream.data) {
if (switch_api_execute(vname, vval, channel->session, &stream) == SWITCH_STATUS_SUCCESS) {
func_val = stream.data;
sub_val = func_val;
} else {
free(stream.data);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
free(data);
free(indup);
return in;
}
}
nlen = strlen(sub_val);
if (len + nlen >= olen) {
olen += block;
cpos = c - data;
ppos = p - data;
vnamepos = vname - data;
vvalpos = vval - data;
data = realloc(data, olen);
c = data + cpos;
p = data + ppos;
vname = data + vnamepos;
vname = data + vvalpos;
}
len += nlen;
strcat(c, sub_val);
c += nlen;
if (func_val) {
free(func_val);
func_val = NULL;
}
}
if (sp) {
*c++ = ' ';
sp = 0;
}
*c++ = *p;
len++;
}
}
free(indup);
return data;
}

View File

@ -2435,6 +2435,7 @@ static void switch_core_standard_on_execute(switch_core_session_t *session)
}
while (switch_channel_get_state(session->channel) == CS_EXECUTE && extension->current_application) {
char *expanded;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Execute %s(%s)\n",
extension->current_application->application_name,
extension->current_application->application_data);
@ -2454,13 +2455,25 @@ static void switch_core_standard_on_execute(switch_core_session_t *session)
return;
}
if ((expanded = switch_channel_expand_variables(session->channel, extension->current_application->application_data)) !=
extension->current_application->application_data) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Expanded String %s(%s)\n",
extension->current_application->application_name,
expanded);
}
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(session->channel, event);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application", "%s", extension->current_application->application_name);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application-Data", "%s", extension->current_application->application_data);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application-Data-Orig", "%s", extension->current_application->application_data);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application-Data", "%s", expanded);
switch_event_fire(&event);
}
application_interface->application_function(session, extension->current_application->application_data);
application_interface->application_function(session, expanded);
if (expanded != extension->current_application->application_data) {
free(expanded);
}
extension->current_application = extension->current_application->next;
}

View File

@ -223,7 +223,7 @@ SWITCH_DECLARE(void) switch_log_printf(switch_text_channel_t channel, char *file
}
} else {
if (level == SWITCH_LOG_CONSOLE || !LOG_QUEUE || !THREAD_RUNNING) {
fprintf(handle, data);
fprintf(handle, "%s", data);
free(data);
} else if (level <= MAX_LEVEL) {
switch_log_node_t *node;