[Freeswitch-svn] [commit] r2994 - in freeswitch/trunk/src: . include mod/dialplans/mod_dialplan_xml mod/loggers/mod_console

Freeswitch SVN anthm at freeswitch.org
Sat Oct 7 15:54:04 EDT 2006


Author: anthm
Date: Sat Oct  7 15:54:04 2006
New Revision: 2994

Modified:
   freeswitch/trunk/src/include/switch_channel.h
   freeswitch/trunk/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c
   freeswitch/trunk/src/mod/loggers/mod_console/mod_console.c
   freeswitch/trunk/src/switch_channel.c
   freeswitch/trunk/src/switch_core.c
   freeswitch/trunk/src/switch_log.c

Log:
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.



Modified: freeswitch/trunk/src/include/switch_channel.h
==============================================================================
--- freeswitch/trunk/src/include/switch_channel.h	(original)
+++ freeswitch/trunk/src/include/switch_channel.h	Sat Oct  7 15:54:04 2006
@@ -400,6 +400,14 @@
 */
 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);

Modified: freeswitch/trunk/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c
==============================================================================
--- freeswitch/trunk/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c	(original)
+++ freeswitch/trunk/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c	Sat Oct  7 15:54:04 2006
@@ -174,17 +174,16 @@
 				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);

Modified: freeswitch/trunk/src/mod/loggers/mod_console/mod_console.c
==============================================================================
--- freeswitch/trunk/src/mod/loggers/mod_console/mod_console.c	(original)
+++ freeswitch/trunk/src/mod/loggers/mod_console/mod_console.c	Sat Oct  7 15:54:04 2006
@@ -128,7 +128,7 @@
 		} 
 
 		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");

Modified: freeswitch/trunk/src/switch_channel.c
==============================================================================
--- freeswitch/trunk/src/switch_channel.c	(original)
+++ freeswitch/trunk/src/switch_channel.c	Sat Oct  7 15:54:04 2006
@@ -999,3 +999,125 @@
 	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;
+}

Modified: freeswitch/trunk/src/switch_core.c
==============================================================================
--- freeswitch/trunk/src/switch_core.c	(original)
+++ freeswitch/trunk/src/switch_core.c	Sat Oct  7 15:54:04 2006
@@ -2435,6 +2435,7 @@
 	}
 
 	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 @@
 			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;
 	}
 	

Modified: freeswitch/trunk/src/switch_log.c
==============================================================================
--- freeswitch/trunk/src/switch_log.c	(original)
+++ freeswitch/trunk/src/switch_log.c	Sat Oct  7 15:54:04 2006
@@ -223,7 +223,7 @@
 				}
 		} 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;



More information about the Freeswitch-svn mailing list