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:
parent
4ede7f7593
commit
741b8329b9
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue