[Freeswitch-svn] [commit] r4993 - in freeswitch/trunk/src: . include mod/applications/mod_dptools mod/applications/mod_enum mod/dialplans/mod_dialplan_directory mod/dialplans/mod_dialplan_xml

Freeswitch SVN anthm at freeswitch.org
Fri Apr 20 19:45:14 EDT 2007


Author: anthm
Date: Fri Apr 20 19:45:14 2007
New Revision: 4993

Modified:
   freeswitch/trunk/src/include/switch_core.h
   freeswitch/trunk/src/include/switch_types.h
   freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c
   freeswitch/trunk/src/mod/applications/mod_enum/mod_enum.c
   freeswitch/trunk/src/mod/dialplans/mod_dialplan_directory/mod_dialplan_directory.c
   freeswitch/trunk/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c
   freeswitch/trunk/src/switch_core_session.c
   freeswitch/trunk/src/switch_core_state_machine.c

Log:
add new execute_extension application to execute another extension in the current scope

Modified: freeswitch/trunk/src/include/switch_core.h
==============================================================================
--- freeswitch/trunk/src/include/switch_core.h	(original)
+++ freeswitch/trunk/src/include/switch_core.h	Fri Apr 20 19:45:14 2007
@@ -565,6 +565,8 @@
 */
 SWITCH_DECLARE(switch_status_t) switch_core_session_event_send(char *uuid_str, switch_event_t **event);
 
+SWITCH_DECLARE(switch_status_t) switch_core_session_execute_exten(switch_core_session_t *session, char *exten, char *dialplan, char *context);
+
 /*! 
   \brief Send an event to a session translating it to it's native message format
   \param session the session to receive the event

Modified: freeswitch/trunk/src/include/switch_types.h
==============================================================================
--- freeswitch/trunk/src/include/switch_types.h	(original)
+++ freeswitch/trunk/src/include/switch_types.h	Fri Apr 20 19:45:14 2007
@@ -999,7 +999,7 @@
 typedef switch_bool_t (*switch_media_bug_callback_t) (switch_media_bug_t *, void *, switch_abc_type_t);
 typedef void (*switch_application_function_t) (switch_core_session_t *, char *);
 typedef void (*switch_event_callback_t) (switch_event_t *);
-typedef switch_caller_extension_t *(*switch_dialplan_hunt_function_t) (switch_core_session_t *, void *);
+typedef switch_caller_extension_t *(*switch_dialplan_hunt_function_t) (switch_core_session_t *, void *, switch_caller_profile_t *);
 typedef struct switch_scheduler_task switch_scheduler_task_t;
 typedef void (*switch_scheduler_func_t) (switch_scheduler_task_t *task);
 typedef switch_status_t (*switch_state_handler_t) (switch_core_session_t *);

Modified: freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c	(original)
+++ freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c	Fri Apr 20 19:45:14 2007
@@ -36,6 +36,7 @@
 static const char modname[] = "mod_dptools";
 
 static const switch_application_interface_t detect_speech_application_interface;
+static const switch_application_interface_t exe_application_interface;
 
 static void detect_speech_function(switch_core_session_t *session, char *data)
 {
@@ -64,6 +65,26 @@
 
 }
 
+static void exe_function(switch_core_session_t *session, char *data)
+{
+	char *argv[4];
+	int argc;
+	char *lbuf = NULL;
+	char *extension;
+	char *context;
+	char *dialplan;
+	
+	if (data && (lbuf = switch_core_session_strdup(session, data))
+		&& (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
+		extension = argv[0];
+		dialplan = argv[1];
+		context = argv[2];
+		switch_core_session_execute_exten(session, extension, dialplan, context);
+	} else {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", exe_application_interface.syntax);
+	}
+}
+
 static void ring_ready_function(switch_core_session_t *session, char *data)
 {
 	switch_channel_t *channel;
@@ -606,7 +627,7 @@
 }
 
 
-static switch_api_interface_t strepoch_api_interface = {
+static const switch_api_interface_t strepoch_api_interface = {
 	/*.interface_name */ "strepoch",
 	/*.desc */ "Convert a date string into epoch time",
 	/*.function */ strepoch_api_function,
@@ -614,7 +635,7 @@
 	/*.next */ NULL
 };
 
-static switch_api_interface_t chat_api_interface = {
+static const switch_api_interface_t chat_api_interface = {
 	/*.interface_name */ "chat",
 	/*.desc */ "chat",
 	/*.function */ chat_api_function,
@@ -622,7 +643,7 @@
 	/*.next */ &strepoch_api_interface
 };
 
-static switch_api_interface_t dptools_api_interface = {
+static const switch_api_interface_t dptools_api_interface = {
 	/*.interface_name */ "strftime",
 	/*.desc */ "strftime",
 	/*.function */ strftime_api_function,
@@ -630,7 +651,7 @@
 	/*.next */ &chat_api_interface
 };
 
-static switch_api_interface_t presence_api_interface = {
+static const switch_api_interface_t presence_api_interface = {
 	/*.interface_name */ "presence",
 	/*.desc */ "presence",
 	/*.function */ presence_api_function,
@@ -639,18 +660,27 @@
 };
 
 
+static const switch_application_interface_t exe_application_interface = {
+	/*.interface_name */ "execute_extension",
+	/*.application_function */ exe_function,
+	/*.long_desc */ "Execute an extension",
+	/*.short_desc */ "Execute an extension",
+	/*.syntax */ "<extension> <dialplan> <context>",
+	/* flags */ SAF_SUPPORT_NOMEDIA,
+	/*.next */
+};
 
-static switch_application_interface_t sched_transfer_application_interface = {
+static const switch_application_interface_t sched_transfer_application_interface = {
 	/*.interface_name */ "sched_transfer",
 	/*.application_function */ sched_transfer_function,
 	/*.long_desc */ "Schedule a transfer in the future",
 	/*.short_desc */ "Schedule a transfer in the future",
 	/*.syntax */ "[+]<time> <extension> <dialplan> <context>",
 	/* flags */ SAF_SUPPORT_NOMEDIA,
-	/*.next */ NULL
+	/*.next */ &exe_application_interface
 };
 
-static switch_application_interface_t sched_broadcast_application_interface = {
+static const switch_application_interface_t sched_broadcast_application_interface = {
 	/*.interface_name */ "sched_broadcast",
 	/*.application_function */ sched_broadcast_function,
 	/*.long_desc */ "Schedule a broadcast in the future",
@@ -660,7 +690,7 @@
 	/*.next */ &sched_transfer_application_interface
 };
 
-static switch_application_interface_t sched_hangup_application_interface = {
+static const switch_application_interface_t sched_hangup_application_interface = {
 	/*.interface_name */ "sched_hangup",
 	/*.application_function */ sched_hangup_function,
 	/*.long_desc */ "Schedule a hangup in the future",

Modified: freeswitch/trunk/src/mod/applications/mod_enum/mod_enum.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_enum/mod_enum.c	(original)
+++ freeswitch/trunk/src/mod/applications/mod_enum/mod_enum.c	Fri Apr 20 19:45:14 2007
@@ -519,10 +519,9 @@
 }
 
 
-static switch_caller_extension_t *enum_dialplan_hunt(switch_core_session_t *session, void *arg)
+static switch_caller_extension_t *enum_dialplan_hunt(switch_core_session_t *session, void *arg, switch_caller_profile_t *caller_profile)
 {
 	switch_caller_extension_t *extension = NULL;
-	switch_caller_profile_t *caller_profile;
 	enum_record_t *results, *rp;
 	switch_channel_t *channel = switch_core_session_get_channel(session);
 	enum_route_t *rtp;
@@ -530,7 +529,9 @@
 
 	assert(channel != NULL);
 
-	caller_profile = switch_channel_get_caller_profile(channel);
+	if (!caller_profile) {
+		caller_profile = switch_channel_get_caller_profile(channel);
+	}
 
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "ENUM Lookup on %s\n", caller_profile->destination_number);
 

Modified: freeswitch/trunk/src/mod/dialplans/mod_dialplan_directory/mod_dialplan_directory.c
==============================================================================
--- freeswitch/trunk/src/mod/dialplans/mod_dialplan_directory/mod_dialplan_directory.c	(original)
+++ freeswitch/trunk/src/mod/dialplans/mod_dialplan_directory/mod_dialplan_directory.c	Fri Apr 20 19:45:14 2007
@@ -83,9 +83,8 @@
 	switch_xml_free(xml);
 }
 
-static switch_caller_extension_t *directory_dialplan_hunt(switch_core_session_t *session, void *arg)
+static switch_caller_extension_t *directory_dialplan_hunt(switch_core_session_t *session, void *arg, switch_caller_profile_t *caller_profile)
 {
-	switch_caller_profile_t *caller_profile;
 	switch_caller_extension_t *extension = NULL;
 	switch_channel_t *channel;
 	char *var, *val;
@@ -97,8 +96,10 @@
 	channel = switch_core_session_get_channel(session);
 	assert(channel != NULL);
 
-	caller_profile = switch_channel_get_caller_profile(channel);
-
+	if (!caller_profile) {
+		caller_profile = switch_channel_get_caller_profile(channel);
+	}
+	
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Hello %s You Dialed %s!\n", caller_profile->caller_id_name,
 					  caller_profile->destination_number);
 

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	Fri Apr 20 19:45:14 2007
@@ -43,17 +43,15 @@
 	BREAK_NEVER
 } break_t;
 
-static int parse_exten(switch_core_session_t *session, switch_xml_t xexten, switch_caller_extension_t **extension)
+static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *caller_profile, switch_xml_t xexten, switch_caller_extension_t **extension)
 {
 	switch_xml_t xcond, xaction;
-	switch_caller_profile_t *caller_profile;
 	switch_channel_t *channel;
 	char *exten_name = (char *) switch_xml_attr_soft(xexten, "name");
 	int proceed = 0;
 	switch_stream_handle_t stream = { 0 };
 
 	channel = switch_core_session_get_channel(session);
-	caller_profile = switch_channel_get_caller_profile(channel);
 
 	for (xcond = switch_xml_child(xexten, "condition"); xcond; xcond = xcond->next) {
 		char *field = NULL;
@@ -291,24 +289,26 @@
 	return status;
 }
 
-static switch_caller_extension_t *dialplan_hunt(switch_core_session_t *session, void *arg)
+static switch_caller_extension_t *dialplan_hunt(switch_core_session_t *session, void *arg, switch_caller_profile_t *caller_profile)
 {
-	switch_caller_profile_t *caller_profile;
 	switch_caller_extension_t *extension = NULL;
 	switch_channel_t *channel;
 	switch_xml_t alt_root = NULL, cfg, xml = NULL, xcontext, xexten;
 	char *alt_path = (char *) arg;
-
+	
 	channel = switch_core_session_get_channel(session);
 
-	if ((caller_profile = switch_channel_get_caller_profile(channel))) {
-		if (!caller_profile->context) {
-			caller_profile->context = "default";
+	if (!caller_profile) {
+		if (!(caller_profile = switch_channel_get_caller_profile(channel))) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Obtaining Profile!\n");
+			goto done;
 		}
-	} else {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Obtaining Profile!\n");
-		goto done;
 	}
+	
+	if (!caller_profile->context) {
+		caller_profile->context = "default";
+	}
+	
 
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Processing %s->%s!\n", caller_profile->caller_id_name, caller_profile->destination_number);
 
@@ -352,7 +352,7 @@
 		int proceed = 0;
 		char *cont = (char *) switch_xml_attr_soft(xexten, "continue");
 
-		proceed = parse_exten(session, xexten, &extension);
+		proceed = parse_exten(session, caller_profile, xexten, &extension);
 
 		if (proceed && !switch_true(cont)) {
 			break;

Modified: freeswitch/trunk/src/switch_core_session.c
==============================================================================
--- freeswitch/trunk/src/switch_core_session.c	(original)
+++ freeswitch/trunk/src/switch_core_session.c	Fri Apr 20 19:45:14 2007
@@ -871,3 +871,121 @@
 	switch_core_hash_init(&runtime.session_table, runtime.memory_pool);
 	switch_mutex_init(&runtime.session_table_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);
 }
+
+
+SWITCH_DECLARE(switch_status_t) switch_core_session_execute_exten(switch_core_session_t *session, char *exten, char *dialplan, char *context)
+{
+	char *dp[25];
+	char *dpstr;
+	int argc, x, count = 0;
+	char *expanded = NULL;
+	switch_caller_profile_t *profile, *new_profile;
+	switch_channel_t *channel;
+	switch_dialplan_interface_t *dialplan_interface = NULL;
+	switch_caller_extension_t *extension = NULL;
+	const switch_application_interface_t *application_interface;
+	switch_event_t *event;
+
+	channel = switch_core_session_get_channel(session);
+	
+	if (!(profile = switch_channel_get_caller_profile(channel))) {
+		return SWITCH_STATUS_SUCCESS;
+	}
+
+	new_profile = switch_caller_profile_clone(session, profile);
+	new_profile->destination_number = switch_core_session_strdup(session, exten);
+		
+	if (!switch_strlen_zero(dialplan)) {
+		new_profile->dialplan = switch_core_session_strdup(session, dialplan);
+	}
+	
+	if (!switch_strlen_zero(context)) {
+		new_profile->context = switch_core_session_strdup(session, context);
+	}
+
+	if (!(dpstr = switch_core_session_strdup(session, new_profile->dialplan))) {
+		abort();
+	}
+
+	argc = switch_separate_string(dpstr, ',', dp, (sizeof(dp) / sizeof(dp[0])));
+	for (x = 0; x < argc; x++) {
+		char *dpname = dp[x];
+		char *dparg = NULL;
+			
+		if (dpname) {
+			if ((dparg = strchr(dpname, ':'))) {
+				*dparg++ = '\0';
+			}
+		}
+		if (!(dialplan_interface = switch_loadable_module_get_dialplan_interface(dpname))) {
+			continue;
+		}
+			
+		count++;
+			
+		if ((extension = dialplan_interface->hunt_function(session, dparg, new_profile)) != 0) {
+			break;
+		}
+	}
+	
+	if (!extension) {
+		return SWITCH_STATUS_FALSE;
+	}
+
+	while (switch_channel_ready(channel) && extension->current_application) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Execute %s(%s)\n",
+						  extension->current_application->application_name, switch_str_nil(extension->current_application->application_data));
+		if ((application_interface = switch_loadable_module_get_application_interface(extension->current_application->application_name)) == 0) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Application %s\n", extension->current_application->application_name);
+			return SWITCH_STATUS_FALSE;
+		}
+
+		if (switch_channel_test_flag(session->channel, CF_NOMEDIA) && !switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA)) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Application %s Cannot be used with NO_MEDIA mode!\n",
+							  extension->current_application->application_name);
+			return SWITCH_STATUS_FALSE;
+		}
+	
+		if (!application_interface->application_function) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Function for %s\n", extension->current_application->application_name);
+			return SWITCH_STATUS_FALSE;
+		}
+
+		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-Orig", "%s", extension->current_application->application_data);
+			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application-Data", "%s", expanded);
+			switch_event_fire(&event);
+		}
+
+
+		if (switch_channel_get_variable(session->channel, "presence_id")) {
+			char *arg = switch_mprintf("%s(%s)", extension->current_application->application_name, expanded);
+			if (arg) {
+				switch_channel_presence(session->channel, "unknown", arg);
+				switch_safe_free(arg);
+			}
+		}
+
+		application_interface->application_function(session, expanded);
+
+		if (expanded != extension->current_application->application_data) {
+			switch_safe_free(expanded);
+		}
+
+		extension->current_application = extension->current_application->next;		
+	}
+
+	return SWITCH_STATUS_SUCCESS;
+	
+}
+
+

Modified: freeswitch/trunk/src/switch_core_state_machine.c
==============================================================================
--- freeswitch/trunk/src/switch_core_state_machine.c	(original)
+++ freeswitch/trunk/src/switch_core_state_machine.c	Fri Apr 20 19:45:14 2007
@@ -82,7 +82,7 @@
 
 					count++;
 
-					if ((extension = dialplan_interface->hunt_function(session, dparg)) != 0) {
+					if ((extension = dialplan_interface->hunt_function(session, dparg, NULL)) != 0) {
 						switch_channel_set_caller_extension(session->channel, extension);
 						return;
 					}



More information about the Freeswitch-svn mailing list