提交 741b8329 authored 作者: Anthony Minessale's avatar Anthony Minessale

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
上级 4ede7f75
......@@ -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);
......
......@@ -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);
......
......@@ -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");
......
......@@ -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;
}
......@@ -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;
}
......
......@@ -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;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论