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);
|
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
|
// 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);
|
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 *cmd = switch_core_session_strdup(session, field + 1);
|
||||||
char *arg;
|
char *arg;
|
||||||
|
|
||||||
|
SWITCH_STANDARD_STREAM(stream);
|
||||||
|
|
||||||
if (cmd) {
|
if (cmd) {
|
||||||
if ((arg = strchr(cmd, ' '))) {
|
if ((arg = strchr(cmd, ' '))) {
|
||||||
*arg++ = '\0';
|
*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) {
|
if (switch_api_execute(cmd, arg, session, &stream) == SWITCH_STATUS_SUCCESS) {
|
||||||
field_data = retbuf;
|
field_data = retbuf;
|
||||||
}
|
}
|
||||||
|
free(stream.data);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
field_data = switch_caller_get_field_by_name(caller_profile, field);
|
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)) {
|
if (!log_hash || (((all_level > - 1) || lookup) && level >= node->level)) {
|
||||||
fprintf(handle, node->data);
|
fprintf(handle, "%s", node->data);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "HELP I HAVE NO CONSOLE TO LOG TO!\n");
|
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;
|
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) {
|
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",
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Execute %s(%s)\n",
|
||||||
extension->current_application->application_name,
|
extension->current_application->application_name,
|
||||||
extension->current_application->application_data);
|
extension->current_application->application_data);
|
||||||
|
@ -2454,13 +2455,25 @@ static void switch_core_standard_on_execute(switch_core_session_t *session)
|
||||||
return;
|
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) {
|
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE) == SWITCH_STATUS_SUCCESS) {
|
||||||
switch_channel_event_set_data(session->channel, event);
|
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", "%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);
|
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;
|
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 {
|
} else {
|
||||||
if (level == SWITCH_LOG_CONSOLE || !LOG_QUEUE || !THREAD_RUNNING) {
|
if (level == SWITCH_LOG_CONSOLE || !LOG_QUEUE || !THREAD_RUNNING) {
|
||||||
fprintf(handle, data);
|
fprintf(handle, "%s", data);
|
||||||
free(data);
|
free(data);
|
||||||
} else if (level <= MAX_LEVEL) {
|
} else if (level <= MAX_LEVEL) {
|
||||||
switch_log_node_t *node;
|
switch_log_node_t *node;
|
||||||
|
|
Loading…
Reference in New Issue