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:
parent
b1d3ae83ab
commit
b5a10d5a14
|
@ -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
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue