Merge branch 'arnaldo.ftdm_channel_read_event'

This commit is contained in:
Arnaldo Pereira
2010-12-02 20:53:18 -02:00
6 changed files with 653 additions and 358 deletions

View File

@@ -1004,6 +1004,51 @@ FT_DECLARE(ftdm_status_t) ftdm_span_next_event(ftdm_span_t *span, ftdm_event_t *
return status;
}
FT_DECLARE(ftdm_status_t) ftdm_channel_read_event(ftdm_channel_t *ftdmchan, ftdm_event_t **event)
{
ftdm_status_t status = FTDM_FAIL;
ftdm_sigmsg_t sigmsg;
ftdm_span_t *span = ftdmchan->span;
ftdm_assert_return(span->fio != NULL, FTDM_FAIL, "No I/O module attached to this span!\n");
if (!span->fio->channel_next_event) {
ftdm_log(FTDM_LOG_ERROR, "channel_next_event method not implemented in module %s!", span->fio->name);
return FTDM_NOTIMPL;
}
status = span->fio->channel_next_event(ftdmchan, event);
if (status != FTDM_SUCCESS) {
return status;
}
/* before returning the event to the user we do some core operations with certain OOB events */
memset(&sigmsg, 0, sizeof(sigmsg));
sigmsg.span_id = span->span_id;
sigmsg.chan_id = (*event)->channel->chan_id;
sigmsg.channel = (*event)->channel;
switch ((*event)->enum_id) {
case FTDM_OOB_ALARM_CLEAR:
{
sigmsg.event_id = FTDM_SIGEVENT_ALARM_CLEAR;
ftdm_clear_flag_locked((*event)->channel, FTDM_CHANNEL_IN_ALARM);
ftdm_span_send_signal(span, &sigmsg);
}
break;
case FTDM_OOB_ALARM_TRAP:
{
sigmsg.event_id = FTDM_SIGEVENT_ALARM_TRAP;
ftdm_set_flag_locked((*event)->channel, FTDM_CHANNEL_IN_ALARM);
ftdm_span_send_signal(span, &sigmsg);
}
break;
default:
/* NOOP */
break;
}
return status;
}
static ftdm_status_t ftdmchan_fsk_write_sample(int16_t *buf, ftdm_size_t buflen, void *user_data)
{
ftdm_channel_t *ftdmchan = (ftdm_channel_t *) user_data;

File diff suppressed because it is too large Load Diff

View File

@@ -35,6 +35,7 @@
* Moises Silva <moy@sangoma.com>
* David Yat Sin <davidy@sangoma.com>
* Nenad Corbic <ncorbic@sangoma.com>
* Arnaldo Pereira <arnaldo@sangoma.com>
*
*/
@@ -99,7 +100,8 @@ static struct {
/* a bunch of this stuff should go into the wanpipe_tdm_api_iface.h */
FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event);
FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event);
FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event);
FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event);
/**
* \brief Poll for event on a wanpipe socket
@@ -794,7 +796,7 @@ static void wanpipe_write_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_tx_hdr_t *t
/* we don't test for 80% full in tx since is typically full for voice channels, should we test tx 80% full for D-channels? */
if (ftdmchan->iostats.tx.queue_len >= ftdmchan->iostats.tx.queue_size) {
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Tx Queue Full (%d/%d)\n",
ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.tx.queue_size);
ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size);
ftdm_set_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL);
} else if (ftdm_test_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL)){
ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Tx Queue no longer full (%d/%d)\n",
@@ -861,7 +863,6 @@ static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx
ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES);
} else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){
/* any reason we have wanpipe_tdm_api_iface.h in ftmod_wanpipe/ dir? */
ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Rx Queue length reduced 80% threshold (%d/%d)\n",
ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES);
@@ -1181,13 +1182,155 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms)
return FTDM_SUCCESS;
}
/**
* \brief Retrieves an event from a wanpipe channel
* \param channel Channel to retrieve event from
* \param event FreeTDM event to return
* \return Success or failure
*/
FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event)
{
ftdm_status_t status;
ftdm_oob_event_t event_id;
wanpipe_tdm_api_t tdm_api;
ftdm_span_t *span = ftdmchan->span;
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT))
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_EVENT);
memset(&tdm_api, 0, sizeof(tdm_api));
status = sangoma_tdm_read_event(ftdmchan->sockfd, &tdm_api);
if (status != FTDM_SUCCESS) {
snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno));
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to read event from channel: %s\n", strerror(errno));
return FTDM_FAIL;
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "read wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type);
switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type) {
case WP_TDMAPI_EVENT_LINK_STATUS:
{
switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_link_status) {
case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED:
event_id = FTDM_OOB_ALARM_CLEAR;
break;
default:
event_id = FTDM_OOB_ALARM_TRAP;
break;
};
}
break;
case WP_TDMAPI_EVENT_RXHOOK:
{
if (ftdmchan->type == FTDM_CHAN_TYPE_FXS) {
event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_OFFHOOK : FTDM_OOB_ONHOOK;
if (event_id == FTDM_OOB_OFFHOOK) {
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_FLASH)) {
ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH);
ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_WINK);
event_id = FTDM_OOB_FLASH;
goto event;
} else {
ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_WINK);
}
} else {
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_WINK)) {
ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_WINK);
ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH);
event_id = FTDM_OOB_WINK;
goto event;
} else {
ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH);
}
}
break;
} else {
wanpipe_tdm_api_t onhook_tdm_api;
memset(&onhook_tdm_api, 0, sizeof(onhook_tdm_api));
status = sangoma_tdm_txsig_onhook(ftdmchan->sockfd, &onhook_tdm_api);
if (status) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "ONHOOK Failed");
return FTDM_FAIL;
}
event_id = onhook_tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_ONHOOK : FTDM_OOB_NOOP;
}
}
break;
case WP_TDMAPI_EVENT_RING_DETECT:
{
event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_RING_START : FTDM_OOB_RING_STOP;
}
break;
/*
disabled this ones when configuring, we don't need them, do we?
case WP_TDMAPI_EVENT_RING_TRIP_DETECT:
{
event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_ONHOOK : FTDM_OOB_OFFHOOK;
}
break;
*/
case WP_TDMAPI_EVENT_RBS:
{
event_id = FTDM_OOB_CAS_BITS_CHANGE;
ftdmchan->rx_cas_bits = wanpipe_swap_bits(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_rbs_bits);
}
break;
case WP_TDMAPI_EVENT_DTMF:
{
char tmp_dtmf[2] = { tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_digit, 0 };
event_id = FTDM_OOB_NOOP;
if (tmp_dtmf[0] == 'f') {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Ignoring wanpipe DTMF: %c, fax tones will be passed through!\n", tmp_dtmf[0]);
break;
}
if (tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_PRESENT) {
ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_MUTE);
}
if (tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_STOP) {
ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_MUTE);
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Queuing wanpipe DTMF: %c\n", tmp_dtmf[0]);
ftdm_channel_queue_dtmf(ftdmchan, tmp_dtmf);
}
}
}
break;
case WP_TDMAPI_EVENT_ALARM:
{
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Got wanpipe alarms %d\n", tdm_api.wp_tdm_cmd.event.wp_api_event_alarm);
event_id = FTDM_OOB_ALARM_TRAP;
}
break;
default:
{
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unhandled wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type);
event_id = FTDM_OOB_INVALID;
}
break;
}
event:
ftdmchan->last_event_time = 0;
span->event_header.e_type = FTDM_EVENT_OOB;
span->event_header.enum_id = event_id;
span->event_header.channel = ftdmchan;
*event = &span->event_header;
return FTDM_SUCCESS;
}
/**
* \brief Retrieves an event from a wanpipe span
* \param span Span to retrieve event from
* \param event FreeTDM event to return
* \return Success or failure
*/
FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event)
FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event)
{
uint32_t i,err;
ftdm_oob_event_t event_id;
@@ -1419,7 +1562,8 @@ static FIO_IO_LOAD_FUNCTION(wanpipe_init)
wanpipe_interface.read = wanpipe_read;
wanpipe_interface.write = wanpipe_write;
wanpipe_interface.poll_event = wanpipe_poll_event;
wanpipe_interface.next_event = wanpipe_next_event;
wanpipe_interface.next_event = wanpipe_span_next_event;
wanpipe_interface.channel_next_event = wanpipe_channel_next_event;
wanpipe_interface.channel_destroy = wanpipe_channel_destroy;
wanpipe_interface.get_alarms = wanpipe_get_alarms;
*fio = &wanpipe_interface;

View File

@@ -483,6 +483,7 @@ struct ftdm_memory_handler {
#define FIO_SPAN_GET_SIG_STATUS_ARGS (ftdm_span_t *span, ftdm_signaling_status_t *status)
#define FIO_SPAN_POLL_EVENT_ARGS (ftdm_span_t *span, uint32_t ms, short *poll_events)
#define FIO_SPAN_NEXT_EVENT_ARGS (ftdm_span_t *span, ftdm_event_t **event)
#define FIO_CHANNEL_NEXT_EVENT_ARGS (ftdm_channel_t *ftdmchan, ftdm_event_t **event)
#define FIO_SIGNAL_CB_ARGS (ftdm_sigmsg_t *sigmsg)
#define FIO_EVENT_CB_ARGS (ftdm_channel_t *ftdmchan, ftdm_event_t *event)
#define FIO_CONFIGURE_SPAN_ARGS (ftdm_span_t *span, const char *str, ftdm_chan_type_t type, char *name, char *number)
@@ -514,6 +515,7 @@ typedef ftdm_status_t (*fio_span_set_sig_status_t) FIO_SPAN_SET_SIG_STATUS_ARGS;
typedef ftdm_status_t (*fio_span_get_sig_status_t) FIO_SPAN_GET_SIG_STATUS_ARGS;
typedef ftdm_status_t (*fio_span_poll_event_t) FIO_SPAN_POLL_EVENT_ARGS ;
typedef ftdm_status_t (*fio_span_next_event_t) FIO_SPAN_NEXT_EVENT_ARGS ;
typedef ftdm_status_t (*fio_channel_next_event_t) FIO_CHANNEL_NEXT_EVENT_ARGS ;
typedef ftdm_status_t (*fio_signal_cb_t) FIO_SIGNAL_CB_ARGS ;
typedef ftdm_status_t (*fio_event_cb_t) FIO_EVENT_CB_ARGS ;
typedef ftdm_status_t (*fio_configure_span_t) FIO_CONFIGURE_SPAN_ARGS ;
@@ -546,6 +548,7 @@ typedef ftdm_status_t (*fio_api_t) FIO_API_ARGS ;
#define FIO_SPAN_GET_SIG_STATUS_FUNCTION(name) ftdm_status_t name FIO_SPAN_GET_SIG_STATUS_ARGS
#define FIO_SPAN_POLL_EVENT_FUNCTION(name) ftdm_status_t name FIO_SPAN_POLL_EVENT_ARGS
#define FIO_SPAN_NEXT_EVENT_FUNCTION(name) ftdm_status_t name FIO_SPAN_NEXT_EVENT_ARGS
#define FIO_CHANNEL_NEXT_EVENT_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_NEXT_EVENT_ARGS
#define FIO_SIGNAL_CB_FUNCTION(name) ftdm_status_t name FIO_SIGNAL_CB_ARGS
#define FIO_EVENT_CB_FUNCTION(name) ftdm_status_t name FIO_EVENT_CB_ARGS
#define FIO_CONFIGURE_SPAN_FUNCTION(name) ftdm_status_t name FIO_CONFIGURE_SPAN_ARGS
@@ -584,6 +587,7 @@ struct ftdm_io_interface {
fio_write_t write; /*!< Write data to the channel */
fio_span_poll_event_t poll_event; /*!< Poll for events on the whole span */
fio_span_next_event_t next_event; /*!< Retrieve an event from the span */
fio_channel_next_event_t channel_next_event; /*!< Retrieve an event from channel */
fio_api_t api; /*!< Execute a text command */
};
@@ -902,6 +906,23 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_add_to_group(const char* name, ftdm_chann
/*! \brief Remove the channel from a hunt group */
FT_DECLARE(ftdm_status_t) ftdm_channel_remove_from_group(ftdm_group_t* group, ftdm_channel_t* ftdmchan);
/*!
* \brief Retrieves an event from the span
*
* \note
* This function is non-reentrant and not thread-safe.
* The event returned may be modified if the function is called again
* from a different thread or even the same. It is recommended to
* handle events from the same span in a single thread.
*
* \param ftdmchan The channel to retrieve the event from
* \param event Pointer to store the pointer to the event
*
* \retval FTDM_SUCCESS success (at least one event available)
* \retval FTDM_FAIL failure
*/
FT_DECLARE(ftdm_status_t) ftdm_channel_read_event(ftdm_channel_t *ftdmchan, ftdm_event_t **event);
/*! \brief Find a hunt group by id */
FT_DECLARE(ftdm_status_t) ftdm_group_find(uint32_t id, ftdm_group_t **group);