]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Fresh updates (Beware... all coded today)
authorAnthony Minessale <anthony.minessale@gmail.com>
Tue, 7 Feb 2006 20:47:15 +0000 (20:47 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Tue, 7 Feb 2006 20:47:15 +0000 (20:47 +0000)
*) Rename *event_handler* to state_handler to avoid confusion with newer eventing engine.
*) Allow application level of state_handler to be layered/stacked (up to 30)
*) Add new core global state_handler stack (also up to 30.. seems reasonable, constant in switch_types.h)

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@554 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/include/switch_channel.h
src/include/switch_core.h
src/include/switch_module_interfaces.h
src/include/switch_types.h
src/mod/applications/mod_bridgecall/mod_bridgecall.c
src/mod/applications/mod_ivrtest/mod_ivrtest.c
src/switch_channel.c
src/switch_core.c

index cea017691a0b3782faf63adc15b8e8224486a9b6..7de22e8c7c428804a49a6410aff4c01f7e79f541 100644 (file)
@@ -192,18 +192,20 @@ SWITCH_DECLARE(switch_status) switch_channel_clear_flag(switch_channel *channel,
 SWITCH_DECLARE(switch_status) switch_channel_answer(switch_channel *channel);
 
 /*!
-  \brief Assign an event handler table to a given channel
-  \param channel channel on which to assign the event handler table
-  \param event_handlers table of event handler functions
+  \brief add an event handler table to a given channel
+  \param channel channel on which to add the event handler table
+  \param state_handler table of event handler functions
+  \return the index number/priority of the table negative value indicates failure
 */
-SWITCH_DECLARE(void) switch_channel_set_event_handlers(switch_channel *channel, const struct switch_event_handler_table *event_handlers);
+SWITCH_DECLARE(int) switch_channel_add_state_handler(switch_channel *channel, const switch_state_handler_table *state_handler);
 
 /*!
-  \brief Retrieve an event handler tablefrom a given channel
+  \brief Retrieve an event handler tablefrom a given channel at given index level
   \param channel channel from which to retrieve the event handler table
-  \return given channel's event handler table
+  \param index the index of the event handler table (start from 0)
+  \return given channel's event handler table at given index or NULL if requested index does not exist.
 */
-SWITCH_DECLARE(const struct switch_event_handler_table *) switch_channel_get_event_handlers(switch_channel *channel);
+SWITCH_DECLARE(const switch_state_handler_table *) switch_channel_get_state_handler(switch_channel *channel, int index);
 
 /*!
   \brief Set private data on channel
index 91a50152ba37dba0a53131058eb1a6f43e0126df..e6fa2240ee1ebc640d5dbc80816a095c6df18a34 100644 (file)
@@ -115,6 +115,26 @@ SWITCH_DECLARE(switch_status) switch_core_destroy(void);
 ///\}
 
 
+
+///\defgroup sh State Handlers
+///\ingroup core1
+///\{
+/*! 
+  \brief Add a global state handler
+  \param state_handler a state handler to add
+  \return the current index/priority of this handler
+*/
+SWITCH_DECLARE(int) switch_core_add_state_handler(const switch_state_handler_table *state_handler);
+
+/*! 
+  \brief Access a state handler
+  \param index the desired index to access
+  \return the desired state handler table or NULL when it does not exist.
+*/
+SWITCH_DECLARE(const switch_state_handler_table *) switch_core_get_state_handler(int index);
+///\}
+
+
 ///\defgroup memp Memory Pooling/Allocation
 ///\ingroup core1
 ///\{
index b0fd603c34143942d53c8b9c50bbd679511b9b4e..30dd8a9f43143e23668287845ee4ba415075de88 100644 (file)
@@ -47,19 +47,19 @@ extern "C" {
 
 /*! \brief A table of functions to execute at various states 
 */
-struct switch_event_handler_table {
+struct switch_state_handler_table {
        /*! executed when the state changes to init */
-       switch_event_handler on_init;
+       switch_state_handler on_init;
        /*! executed when the state changes to ring */
-       switch_event_handler on_ring;
+       switch_state_handler on_ring;
        /*! executed when the state changes to execute */
-       switch_event_handler on_execute;
+       switch_state_handler on_execute;
        /*! executed when the state changes to hangup */
-       switch_event_handler on_hangup;
+       switch_state_handler on_hangup;
        /*! executed when the state changes to loopback*/
-       switch_event_handler on_loopback;
+       switch_state_handler on_loopback;
        /*! executed when the state changes to transmit*/
-       switch_event_handler on_transmit;
+       switch_state_handler on_transmit;
 };
 
 /*! \brief Node in which to store custom outgoing channel callback hooks */
@@ -183,7 +183,7 @@ struct switch_endpoint_interface {
        const switch_io_routines *io_routines;
 
        /*! state machine methods */
-       const switch_event_handler_table *event_handlers;
+       const switch_state_handler_table *state_handler;
 
        /*! private information */
        void *private;
index aff3a6f4a86c3eb5db708ed41df3d1d3c5029f97..7b549c39c595a72e5901cdd0506f37c215e15d9b 100644 (file)
@@ -43,7 +43,7 @@ extern "C" {
 
 #define SWITCH_RECCOMMENDED_BUFFER_SIZE 131072
 #define SWITCH_MAX_CODECS 30
-
+#define SWITCH_MAX_STATE_HANDLERS 30
 
 /*!
   \enum switch_ivr_option_t
@@ -359,7 +359,7 @@ typedef struct switch_caller_profile switch_caller_profile;
 typedef struct switch_caller_step switch_caller_step;
 typedef struct switch_caller_extension switch_caller_extension;
 typedef struct switch_caller_application switch_caller_application;
-typedef struct switch_event_handler_table switch_event_handler_table;
+typedef struct switch_state_handler_table switch_state_handler_table;
 typedef struct switch_timer switch_timer;
 typedef struct switch_codec switch_codec;
 typedef struct switch_core_thread_session switch_core_thread_session;
@@ -383,7 +383,7 @@ typedef struct switch_speech_interface switch_speech_interface;
 typedef void (*switch_application_function)(switch_core_session *, char *);
 typedef void (*switch_event_callback_t)(switch_event *);
 typedef switch_caller_extension *(*switch_dialplan_hunt_function)(switch_core_session *);
-typedef switch_status (*switch_event_handler)(switch_core_session *);
+typedef switch_status (*switch_state_handler)(switch_core_session *);
 typedef switch_status (*switch_outgoing_channel_hook)(switch_core_session *, switch_caller_profile *, switch_core_session *);
 typedef switch_status (*switch_answer_channel_hook)(switch_core_session *);
 typedef switch_status (*switch_receive_message_hook)(switch_core_session *, switch_core_session_message *);
index e533f8e516702fba7672595b008b0bad00e05a86..6a34e4fb67d7779aff13999c4ad653f2fe45cb32 100644 (file)
@@ -144,7 +144,7 @@ static switch_status audio_bridge_on_ring(switch_core_session *session)
        return SWITCH_STATUS_SUCCESS;
 }
 
-static const switch_event_handler_table audio_bridge_peer_event_handlers = {
+static const switch_state_handler_table audio_bridge_peer_state_handlers = {
        /*.on_init */ NULL,
        /*.on_ring */ audio_bridge_on_ring,
        /*.on_execute */ NULL,
@@ -153,7 +153,7 @@ static const switch_event_handler_table audio_bridge_peer_event_handlers = {
        /*.on_transmit */ NULL
 };
 
-static const switch_event_handler_table audio_bridge_caller_event_handlers = {
+static const switch_state_handler_table audio_bridge_caller_state_handlers = {
        /*.on_init */ NULL,
        /*.on_ring */ NULL,
        /*.on_execute */ NULL,
@@ -215,8 +215,8 @@ static void audio_bridge_function(switch_core_session *session, char *data)
 
                switch_channel_set_private(caller_channel, peer_session);
                switch_channel_set_private(peer_channel, session);
-               switch_channel_set_event_handlers(caller_channel, &audio_bridge_caller_event_handlers);
-               switch_channel_set_event_handlers(peer_channel, &audio_bridge_peer_event_handlers);
+               switch_channel_add_state_handler(caller_channel, &audio_bridge_caller_state_handlers);
+               switch_channel_add_state_handler(peer_channel, &audio_bridge_peer_state_handlers);
                switch_core_session_thread_launch(peer_session);
 
                for (;;) {
index 3c3d6273571471316909feef50abb57ad6037c3b..a5803a7333381370296e6604f871283f9145e5bf 100644 (file)
@@ -92,6 +92,26 @@ static void ivrtest_function(switch_core_session *session, char *data)
 }
 
 
+static switch_status my_on_hangup(switch_core_session *session)
+{
+       switch_channel *channel;
+
+       channel = switch_core_session_get_channel(session);
+    assert(channel != NULL);
+
+       switch_console_printf(SWITCH_CHANNEL_CONSOLE, "I globally hooked to [%s] on the hangup event\n", switch_channel_get_name(channel));
+
+}
+
+static const switch_state_handler_table state_handlers = {
+       /*.on_init */ NULL,
+       /*.on_ring */ NULL,
+       /*.on_execute */ NULL,
+       /*.on_hangup */ my_on_hangup,
+       /*.on_loopback */ NULL,
+       /*.on_transmit */ NULL
+};
+
 static const switch_application_interface ivrtest_application_interface = {
        /*.interface_name */ "ivrtest",
        /*.application_function */ ivrtest_function
@@ -112,6 +132,8 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_modul
        /* connect my internal structure to the blank pointer passed to me */
        *interface = &mod_ivrtest_module_interface;
 
+       /* test global state handlers */
+       switch_core_add_state_handler(&state_handlers);
 
        /* indicate that the module should continue to be loaded */
        return SWITCH_STATUS_SUCCESS;
index d60dca668d4d074091bf5fbd02d4e8024c15be12..919ba1173f857bf75b9cf4ac4e2a088ed3004c58 100644 (file)
@@ -43,7 +43,8 @@ struct switch_channel {
        switch_caller_profile *originator_caller_profile;
        switch_caller_profile *originatee_caller_profile;
        switch_caller_extension *caller_extension;
-       const struct switch_event_handler_table *event_handlers;
+       const struct switch_state_handler_table *state_handlers[SWITCH_MAX_STATE_HANDLERS];
+       int state_handler_index;
        switch_hash *variables;
        void *private;
        int freq;
@@ -484,17 +485,29 @@ SWITCH_DECLARE(switch_caller_profile *) switch_channel_get_originatee_caller_pro
        return channel->originatee_caller_profile;
 }
 
-SWITCH_DECLARE(void) switch_channel_set_event_handlers(switch_channel *channel,
-                                                                                                          const struct switch_event_handler_table *event_handlers)
+SWITCH_DECLARE(int) switch_channel_add_state_handler(switch_channel *channel,
+                                                                                                        const switch_state_handler_table *state_handler)
 {
        assert(channel != NULL);
-       channel->event_handlers = event_handlers;
+       int index = channel->state_handler_index++;
+
+       if (channel->state_handler_index >= SWITCH_MAX_STATE_HANDLERS) {
+               return -1;
+       }
+
+       channel->state_handlers[index] = state_handler;
+       return index;
 }
 
-SWITCH_DECLARE(const struct switch_event_handler_table *) switch_channel_get_event_handlers(switch_channel *channel)
+SWITCH_DECLARE(const switch_state_handler_table *) switch_channel_get_state_handler(switch_channel *channel, int index)
 {
        assert(channel != NULL);
-       return channel->event_handlers;
+
+       if (index > SWITCH_MAX_STATE_HANDLERS || index > channel->state_handler_index) {
+               return NULL;
+       }
+
+       return channel->state_handlers[index];
 }
 
 SWITCH_DECLARE(void) switch_channel_set_caller_extension(switch_channel *channel,
index 425cbfe5c0f7e32bc94c18d0f2f9551cb8eb658c..911d261b0aa5cb45ba1f9dbc7b81bf36cc0053cb 100644 (file)
@@ -91,6 +91,8 @@ struct switch_core_runtime {
        apr_pool_t *memory_pool;
        switch_hash *session_table;
        switch_core_db *db;
+       const struct switch_state_handler_table *state_handlers[SWITCH_MAX_STATE_HANDLERS];
+    int state_handler_index;
 #ifdef EMBED_PERL
        PerlInterpreter *my_perl;
 #endif
@@ -186,6 +188,29 @@ SWITCH_DECLARE(switch_status) switch_core_do_perl(char *txt)
 }
 #endif
 
+
+SWITCH_DECLARE(int) switch_core_add_state_handler(const switch_state_handler_table *state_handler)
+{
+       int index = runtime.state_handler_index++;
+
+       if (runtime.state_handler_index >= SWITCH_MAX_STATE_HANDLERS) {
+               return -1;
+       }
+
+       runtime.state_handlers[index] = state_handler;
+       return index;
+}
+
+SWITCH_DECLARE(const switch_state_handler_table *) switch_core_get_state_handler(int index)
+{
+
+       if (index > SWITCH_MAX_STATE_HANDLERS || index > runtime.state_handler_index) {
+               return NULL;
+       }
+
+       return runtime.state_handlers[index];
+}
+
 SWITCH_DECLARE(switch_status) switch_core_session_message_send(char *uuid_str, switch_core_session_message *message)
 {
        switch_core_session *session = NULL;
@@ -1604,8 +1629,8 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session *session)
 {
        switch_channel_state state = CS_NEW, laststate = CS_HANGUP, midstate = CS_DONE;
        const switch_endpoint_interface *endpoint_interface;
-       const switch_event_handler_table *driver_event_handlers = NULL;
-       const switch_event_handler_table *application_event_handlers = NULL;
+       const switch_state_handler_table *driver_state_handler = NULL;
+       const switch_state_handler_table *application_state_handler = NULL;
 
        /*
           Life of the channel. you have channel and pool in your session
@@ -1623,13 +1648,13 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session *session)
 
         */
        assert(session != NULL);
-       application_event_handlers = switch_channel_get_event_handlers(session->channel);
+
 
        endpoint_interface = session->endpoint_interface;
        assert(endpoint_interface != NULL);
 
-       driver_event_handlers = endpoint_interface->event_handlers;
-       assert(driver_event_handlers != NULL);
+       driver_state_handler = endpoint_interface->state_handler;
+       assert(driver_state_handler != NULL);
 
        switch_mutex_lock(session->mutex);
 
@@ -1637,6 +1662,8 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session *session)
                switch_event *event;
 
                if (state != laststate) {
+                       int index = 0;
+                       int proceed = 1;
                        midstate = state;
 
                        if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_STATE) == SWITCH_STATUS_SUCCESS) {
@@ -1653,14 +1680,37 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session *session)
                                break;
                        case CS_HANGUP: /* Deactivate and end the thread */
                                switch_console_printf(SWITCH_CHANNEL_CONSOLE, "State HANGUP\n");
-                               if (!driver_event_handlers->on_hangup ||
-                                       (driver_event_handlers->on_hangup &&
-                                        driver_event_handlers->on_hangup(session) == SWITCH_STATUS_SUCCESS &&
+                               if (!driver_state_handler->on_hangup ||
+                                       (driver_state_handler->on_hangup &&
+                                        driver_state_handler->on_hangup(session) == SWITCH_STATUS_SUCCESS &&
                                         midstate == switch_channel_get_state(session->channel))) {
-                                       if (!application_event_handlers || !application_event_handlers->on_hangup ||
-                                               (application_event_handlers->on_hangup &&
-                                                application_event_handlers->on_hangup(session) == SWITCH_STATUS_SUCCESS &&
-                                                midstate == switch_channel_get_state(session->channel))) {
+                                       while((application_state_handler = switch_channel_get_state_handler(session->channel, index++))) {
+                                               if (!application_state_handler || !application_state_handler->on_hangup ||
+                                                       (application_state_handler->on_hangup &&
+                                                        application_state_handler->on_hangup(session) == SWITCH_STATUS_SUCCESS &&
+                                                        midstate == switch_channel_get_state(session->channel))) {
+                                                       proceed++;
+                                                       continue;
+                                               } else {
+                                                       proceed = 0;
+                                                       break;
+                                               }
+                                       }
+                                       index = 0;
+                                       while(proceed && (application_state_handler = switch_core_get_state_handler(index++))) {
+                                               if (!application_state_handler || !application_state_handler->on_hangup ||
+                                                       (application_state_handler->on_hangup &&
+                                                        application_state_handler->on_hangup(session) == SWITCH_STATUS_SUCCESS &&
+                                                        midstate == switch_channel_get_state(session->channel))) {
+                                                       proceed++;
+                                                       continue;
+                                               } else {
+                                                       proceed = 0;
+                                                       break;
+                                               }
+                                       }
+
+                                       if (proceed) {
                                                switch_core_standard_on_hangup(session);
                                        }
                                }
@@ -1668,70 +1718,181 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session *session)
                                break;
                        case CS_INIT:           /* Basic setup tasks */
                                switch_console_printf(SWITCH_CHANNEL_CONSOLE, "State INIT\n");
-                               if (!driver_event_handlers->on_init ||
-                                       (driver_event_handlers->on_init &&
-                                        driver_event_handlers->on_init(session) == SWITCH_STATUS_SUCCESS &&
+                               if (!driver_state_handler->on_init ||
+                                       (driver_state_handler->on_init &&
+                                        driver_state_handler->on_init(session) == SWITCH_STATUS_SUCCESS &&
                                         midstate == switch_channel_get_state(session->channel))) {
-                                       if (!application_event_handlers || !application_event_handlers->on_init ||
-                                               (application_event_handlers->on_init &&
-                                                application_event_handlers->on_init(session) == SWITCH_STATUS_SUCCESS &&
-                                                midstate == switch_channel_get_state(session->channel))) {
+                                       while((application_state_handler = switch_channel_get_state_handler(session->channel, index++))) {
+                                               if (!application_state_handler || !application_state_handler->on_init ||
+                                                       (application_state_handler->on_init &&
+                                                        application_state_handler->on_init(session) == SWITCH_STATUS_SUCCESS &&
+                                                        midstate == switch_channel_get_state(session->channel))) {
+                                                       proceed++;
+                                                       continue;
+                                               } else {
+                                                       proceed = 0;
+                                                       break;
+                                               }
+                                       }
+                                       index = 0;
+                                       while(proceed && (application_state_handler = switch_core_get_state_handler(index++))) {
+                                               if (!application_state_handler || !application_state_handler->on_init ||
+                                                       (application_state_handler->on_init &&
+                                                        application_state_handler->on_init(session) == SWITCH_STATUS_SUCCESS &&
+                                                        midstate == switch_channel_get_state(session->channel))) {
+                                                       proceed++;
+                                                       continue;
+                                               } else {
+                                                       proceed = 0;
+                                                       break;
+                                               }
+                                       }
+                                       if (proceed) {
                                                switch_core_standard_on_init(session);
                                        }
                                }
                                break;
                        case CS_RING:           /* Look for a dialplan and find something to do */
                                switch_console_printf(SWITCH_CHANNEL_CONSOLE, "State RING\n");
-                               if (!driver_event_handlers->on_ring ||
-                                       (driver_event_handlers->on_ring &&
-                                        driver_event_handlers->on_ring(session) == SWITCH_STATUS_SUCCESS &&
+                               if (!driver_state_handler->on_ring ||
+                                       (driver_state_handler->on_ring &&
+                                        driver_state_handler->on_ring(session) == SWITCH_STATUS_SUCCESS &&
                                         midstate == switch_channel_get_state(session->channel))) {
-                                       if (!application_event_handlers || !application_event_handlers->on_ring ||
-                                               (application_event_handlers->on_ring &&
-                                                application_event_handlers->on_ring(session) == SWITCH_STATUS_SUCCESS &&
-                                                midstate == switch_channel_get_state(session->channel))) {
+                                       while((application_state_handler = switch_channel_get_state_handler(session->channel, index++))) {
+                                               if (!application_state_handler || !application_state_handler->on_ring ||
+                                                       (application_state_handler->on_ring &&
+                                                        application_state_handler->on_ring(session) == SWITCH_STATUS_SUCCESS &&
+                                                        midstate == switch_channel_get_state(session->channel))) {
+                                                       proceed++;
+                                                       continue;
+                                               } else {
+                                                       proceed = 0;
+                                                       break;
+                                               }
+                                       }
+                                       index = 0;
+                                       while(proceed && (application_state_handler = switch_core_get_state_handler(index++))) {
+                                               if (!application_state_handler || !application_state_handler->on_ring ||
+                                                       (application_state_handler->on_ring &&
+                                                        application_state_handler->on_ring(session) == SWITCH_STATUS_SUCCESS &&
+                                                        midstate == switch_channel_get_state(session->channel))) {
+                                                       proceed++;
+                                                       continue;
+                                               } else {
+                                                       proceed = 0;
+                                                       break;
+                                               }
+                                       }
+                                       if (proceed) {
                                                switch_core_standard_on_ring(session);
                                        }
                                }
                                break;
                        case CS_EXECUTE:        /* Execute an Operation */
                                switch_console_printf(SWITCH_CHANNEL_CONSOLE, "State EXECUTE\n");
-                               if (!driver_event_handlers->on_execute ||
-                                       (driver_event_handlers->on_execute &&
-                                        driver_event_handlers->on_execute(session) == SWITCH_STATUS_SUCCESS &&
+                               if (!driver_state_handler->on_execute ||
+                                       (driver_state_handler->on_execute &&
+                                        driver_state_handler->on_execute(session) == SWITCH_STATUS_SUCCESS &&
                                         midstate == switch_channel_get_state(session->channel))) {
-                                       if (!application_event_handlers || !application_event_handlers->on_execute ||
-                                               (application_event_handlers->on_execute &&
-                                                application_event_handlers->on_execute(session) == SWITCH_STATUS_SUCCESS &&
-                                                midstate == switch_channel_get_state(session->channel))) {
+                                       while((application_state_handler = switch_channel_get_state_handler(session->channel, index++))) {
+                                               if (!application_state_handler || !application_state_handler->on_execute ||
+                                                       (application_state_handler->on_execute &&
+                                                        application_state_handler->on_execute(session) == SWITCH_STATUS_SUCCESS &&
+                                                        midstate == switch_channel_get_state(session->channel))) {
+                                                       proceed++;
+                                                       continue;
+                                               } else {
+                                                       proceed = 0;
+                                                       break;
+                                               }
+                                       }
+                                       index = 0;
+                                       while(proceed && (application_state_handler = switch_core_get_state_handler(index++))) {
+                                               if (!application_state_handler || !application_state_handler->on_execute ||
+                                                       (application_state_handler->on_execute &&
+                                                        application_state_handler->on_execute(session) == SWITCH_STATUS_SUCCESS &&
+                                                        midstate == switch_channel_get_state(session->channel))) {
+                                                       proceed++;
+                                                       continue;
+                                               } else {
+                                                       proceed = 0;
+                                                       break;
+                                               }
+                                       }
+                                       if (proceed) {
                                                switch_core_standard_on_execute(session);
                                        }
                                }
                                break;
                        case CS_LOOPBACK:       /* loop all data back to source */
                                switch_console_printf(SWITCH_CHANNEL_CONSOLE, "State LOOPBACK\n");
-                               if (!driver_event_handlers->on_loopback ||
-                                       (driver_event_handlers->on_loopback &&
-                                        driver_event_handlers->on_loopback(session) == SWITCH_STATUS_SUCCESS &&
+                               if (!driver_state_handler->on_loopback ||
+                                       (driver_state_handler->on_loopback &&
+                                        driver_state_handler->on_loopback(session) == SWITCH_STATUS_SUCCESS &&
                                         midstate == switch_channel_get_state(session->channel))) {
-                                       if (!application_event_handlers || !application_event_handlers->on_loopback ||
-                                               (application_event_handlers->on_loopback &&
-                                                application_event_handlers->on_loopback(session) == SWITCH_STATUS_SUCCESS &&
-                                                midstate == switch_channel_get_state(session->channel))) {
+                                       while((application_state_handler = switch_channel_get_state_handler(session->channel, index++))) {
+                                               if (!application_state_handler || !application_state_handler->on_loopback ||
+                                                       (application_state_handler->on_loopback &&
+                                                        application_state_handler->on_loopback(session) == SWITCH_STATUS_SUCCESS &&
+                                                        midstate == switch_channel_get_state(session->channel))) {
+                                                       proceed++;
+                                                       continue;
+                                               } else {
+                                                       proceed = 0;
+                                                       break;
+                                               }
+                                       }
+                                       index = 0;
+                                       while(proceed && (application_state_handler = switch_core_get_state_handler(index++))) {
+                                               if (!application_state_handler || !application_state_handler->on_loopback ||
+                                                       (application_state_handler->on_loopback &&
+                                                        application_state_handler->on_loopback(session) == SWITCH_STATUS_SUCCESS &&
+                                                        midstate == switch_channel_get_state(session->channel))) {
+                                                       proceed++;
+                                                       continue;
+                                               } else {
+                                                       proceed = 0;
+                                                       break;
+                                               }
+                                       }
+                                       if (proceed) {
                                                switch_core_standard_on_loopback(session);
                                        }
                                }
                                break;
                        case CS_TRANSMIT:       /* send/recieve data to/from another channel */
                                switch_console_printf(SWITCH_CHANNEL_CONSOLE, "State TRANSMIT\n");
-                               if (!driver_event_handlers->on_transmit ||
-                                       (driver_event_handlers->on_transmit &&
-                                        driver_event_handlers->on_transmit(session) == SWITCH_STATUS_SUCCESS &&
+                               if (!driver_state_handler->on_transmit ||
+                                       (driver_state_handler->on_transmit &&
+                                        driver_state_handler->on_transmit(session) == SWITCH_STATUS_SUCCESS &&
                                         midstate == switch_channel_get_state(session->channel))) {
-                                       if (!application_event_handlers || !application_event_handlers->on_transmit ||
-                                               (application_event_handlers->on_transmit &&
-                                                application_event_handlers->on_transmit(session) == SWITCH_STATUS_SUCCESS &&
-                                                midstate == switch_channel_get_state(session->channel))) {
+
+                                       while((application_state_handler = switch_channel_get_state_handler(session->channel, index++))) {
+                                               if (!application_state_handler || !application_state_handler->on_transmit ||
+                                                       (application_state_handler->on_transmit &&
+                                                        application_state_handler->on_transmit(session) == SWITCH_STATUS_SUCCESS &&
+                                                        midstate == switch_channel_get_state(session->channel))) {
+                                                       proceed++;
+                                                       continue;
+                                               } else {
+                                                       proceed = 0;
+                                                       break;
+                                               }
+                                       }
+                                       index = 0;
+                                       while(proceed && (application_state_handler = switch_core_get_state_handler(index++))) {
+                                               if (!application_state_handler || !application_state_handler->on_transmit ||
+                                                       (application_state_handler->on_transmit &&
+                                                        application_state_handler->on_transmit(session) == SWITCH_STATUS_SUCCESS &&
+                                                        midstate == switch_channel_get_state(session->channel))) {
+                                                       proceed++;
+                                                       continue;
+                                               } else {
+                                                       proceed = 0;
+                                                       break;
+                                               }
+                                       }
+                                       if (proceed) {
                                                switch_core_standard_on_transmit(session);
                                        }
                                }