Fresh updates (Beware... all coded today)

*) 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
This commit is contained in:
Anthony Minessale 2006-02-07 20:47:15 +00:00
parent 7ddaffbcd4
commit 9e85723e3f
8 changed files with 293 additions and 75 deletions

View 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

View 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
///\{

View 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;

View 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 *);

View 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 (;;) {

View 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;

View 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,

View 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);
}
}