]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
add new execute_extension application to execute another extension in the current...
authorAnthony Minessale <anthony.minessale@gmail.com>
Fri, 20 Apr 2007 23:45:14 +0000 (23:45 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Fri, 20 Apr 2007 23:45:14 +0000 (23:45 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@4993 d0543943-73ff-0310-b7d9-9358b9ac24b2

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

index efb28017a50b1d49b5f38a0e3fb672c52a68e4a9..2c6603568cc53e5bb454552198d32c6bc529bab3 100644 (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
index 7a7f6c02850f09a4a91d6feb568ad9f80bed8cdd..19aa2867bd27cbd65e0b652b0b26b53854c051f1 100644 (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 *);
index 609590579d637a7bb3c120eef730e107a61f979d..6770a933aa117389d2ba284ab48b1fc3462bf766 100644 (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",
index 95d73bfe0260fee534fe742b64a352af094a388b..c9d798dc0eca3a05a64009c07101bde6cdfa01ef 100644 (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);
 
index 7b214d46792758f700f86f713f3c9bd593333116..46bf7225f9fe6241f64c3f6bb18d800c3231c294 100644 (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);
 
index 3ec37baa5dd6ba20327acade6bb28786b3ef051d..aff62974b1bf8083d7795ece398c80ce0ca0cd68 100644 (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;
index 26e290ffdbfc20953f2674de685542d566e250cc..74982016d6e5c7f51b13e533746bc44c7a3e2de7 100644 (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;
+       
+}
+
+
index e50e8f473a9907f562a0e34bb960728b7e981434..5b0850ce8964b4a3fdc1ab9ee8e5ae0a5698fb3c 100644 (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;
                                        }