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

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@4993 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2007-04-20 23:45:14 +00:00
parent b1d3ae83ab
commit b5a10d5a14
8 changed files with 182 additions and 30 deletions

View File

@ -565,6 +565,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_flush_message(switch_core_se
*/
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

View File

@ -999,7 +999,7 @@ typedef struct switch_media_bug switch_media_bug_t;
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 *);

View File

@ -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 detect_speech_function(switch_core_session_t *session, char *data)
}
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 void ivr_application_function(switch_core_session_t *session, char *data)
}
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 @@ static switch_api_interface_t strepoch_api_interface = {
/*.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 @@ static switch_api_interface_t chat_api_interface = {
/*.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 @@ static switch_api_interface_t dptools_api_interface = {
/*.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 switch_api_interface_t presence_api_interface = {
};
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 @@ static switch_application_interface_t sched_broadcast_application_interface = {
/*.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",

View File

@ -519,10 +519,9 @@ static switch_status_t enum_lookup(char *root, char *in, enum_record_t ** result
}
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 @@ static switch_caller_extension_t *enum_dialplan_hunt(switch_core_session_t *sess
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);

View File

@ -83,9 +83,8 @@ SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_directory_name, globals.directory_n
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 @@ static switch_caller_extension_t *directory_dialplan_hunt(switch_core_session_t
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);

View File

@ -43,17 +43,15 @@ typedef enum {
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 @@ static switch_status_t dialplan_xml_locate(switch_core_session_t *session, switc
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 @@ static switch_caller_extension_t *dialplan_hunt(switch_core_session_t *session,
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;

View File

@ -871,3 +871,121 @@ void switch_core_session_init(switch_memory_pool_t *pool)
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;
}

View File

@ -82,7 +82,7 @@ static void switch_core_standard_on_ring(switch_core_session_t *session)
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;
}