diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 9ec92e95b3..9c38755754 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -1091,10 +1091,43 @@ FT_DECLARE(ftdm_status_t) ftdm_span_poll_event(ftdm_span_t *span, uint32_t ms, s return FTDM_NOTIMPL; } +/* handle oob events and send the proper SIGEVENT signal to user, when applicable */ +static __inline__ ftdm_status_t ftdm_event_handle_oob(ftdm_event_t *event) +{ + ftdm_sigmsg_t sigmsg; + ftdm_status_t status = FTDM_SUCCESS; + ftdm_channel_t *fchan = event->channel; + ftdm_span_t *span = fchan->span; + + memset(&sigmsg, 0, sizeof(sigmsg)); + sigmsg.span_id = span->span_id; + sigmsg.chan_id = fchan->chan_id; + sigmsg.channel = fchan; + switch (event->enum_id) { + case FTDM_OOB_ALARM_CLEAR: + { + sigmsg.event_id = FTDM_SIGEVENT_ALARM_CLEAR; + ftdm_clear_flag_locked(fchan, FTDM_CHANNEL_IN_ALARM); + status = ftdm_span_send_signal(span, &sigmsg); + } + break; + case FTDM_OOB_ALARM_TRAP: + { + sigmsg.event_id = FTDM_SIGEVENT_ALARM_TRAP; + ftdm_set_flag_locked(fchan, FTDM_CHANNEL_IN_ALARM); + status = ftdm_span_send_signal(span, &sigmsg); + } + break; + default: + /* NOOP */ + break; + } + return status; +} + FT_DECLARE(ftdm_status_t) ftdm_span_next_event(ftdm_span_t *span, ftdm_event_t **event) { ftdm_status_t status = FTDM_FAIL; - ftdm_sigmsg_t sigmsg; ftdm_assert_return(span->fio != NULL, FTDM_FAIL, "No I/O module attached to this span!\n"); if (!span->fio->next_event) { @@ -1107,38 +1140,16 @@ FT_DECLARE(ftdm_status_t) ftdm_span_next_event(ftdm_span_t *span, ftdm_event_t * 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; + status = ftdm_event_handle_oob(*event); + if (status != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_ERROR, "failed to handle event %d\n", **event); } - 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"); @@ -1155,29 +1166,9 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_read_event(ftdm_channel_t *ftdmchan, ftdm goto done; } - /* 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; + status = ftdm_event_handle_oob(*event); + if (status != FTDM_SUCCESS) { + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "failed to handle event %d\n", **event); } done: diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index 5e9318f7e5..2a203faf8d 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -1234,6 +1234,131 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms) return FTDM_SUCCESS; } +/** + * \brief Process an event in a channel and set it's OOB event id. The channel must be locked. + * \param fchan Channel in which event occured + * \param event_id Pointer where we save the OOB event id + * \param tdm_api Wanpipe tdm struct that contain the event + * \return FTDM_SUCCESS or FTDM_FAIL + */ +static __inline__ ftdm_status_t wanpipe_channel_process_event(ftdm_channel_t *fchan, ftdm_oob_event_t *event_id, wanpipe_tdm_api_t *tdm_api) +{ + switch(tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_type) { + case WP_API_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_API_EVENT_RXHOOK: + { + if (fchan->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(fchan, FTDM_CHANNEL_FLASH)) { + ftdm_clear_flag(fchan, FTDM_CHANNEL_FLASH); + ftdm_clear_flag(fchan, FTDM_CHANNEL_WINK); + *event_id = FTDM_OOB_FLASH; + goto event; + } else { + ftdm_set_flag(fchan, FTDM_CHANNEL_WINK); + } + } else { + if (ftdm_test_flag(fchan, FTDM_CHANNEL_WINK)) { + ftdm_clear_flag(fchan, FTDM_CHANNEL_WINK); + ftdm_clear_flag(fchan, FTDM_CHANNEL_FLASH); + *event_id = FTDM_OOB_WINK; + goto event; + } else { + ftdm_set_flag(fchan, FTDM_CHANNEL_FLASH); + } + } + break; + } else { + ftdm_status_t status; + wanpipe_tdm_api_t onhook_tdm_api; + memset(&onhook_tdm_api, 0, sizeof(onhook_tdm_api)); + status = sangoma_tdm_txsig_onhook(fchan->sockfd, &onhook_tdm_api); + if (status) { + snprintf(fchan->last_error, sizeof(fchan->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_API_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_API_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_API_EVENT_RBS: + { + *event_id = FTDM_OOB_CAS_BITS_CHANGE; + fchan->rx_cas_bits = wanpipe_swap_bits(tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_rbs_bits); + } + break; + case WP_API_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(fchan, 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(fchan, FTDM_CHANNEL_MUTE); + } + + if (tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_STOP) { + ftdm_clear_flag(fchan, FTDM_CHANNEL_MUTE); + if (ftdm_test_flag(fchan, FTDM_CHANNEL_INUSE)) { + ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Queuing wanpipe DTMF: %c\n", tmp_dtmf[0]); + ftdm_channel_queue_dtmf(fchan, tmp_dtmf); + } + } + } + break; + case WP_API_EVENT_ALARM: + { + ftdm_log_chan(fchan, 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; + case WP_API_EVENT_POLARITY_REVERSE: + { + ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Got polarity reverse\n"); + *event_id = FTDM_OOB_POLARITY_REVERSE; + } + break; + default: + { + ftdm_log_chan(fchan, 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: + return FTDM_SUCCESS; +} + /** * \brief Retrieves an event from a wanpipe channel * \param channel Channel to retrieve event from @@ -1260,121 +1385,11 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event) } 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_API_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_API_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_API_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_API_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_API_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_API_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_API_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; - case WP_API_EVENT_POLARITY_REVERSE: - { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Got polarity reverse\n"); - event_id = FTDM_OOB_POLARITY_REVERSE; - } - 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; + if ((wanpipe_channel_process_event(ftdmchan, &event_id, &tdm_api)) != FTDM_SUCCESS) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failed to process event from channel\n"); + return FTDM_FAIL; } -event: - ftdmchan->last_event_time = 0; span->event_header.e_type = FTDM_EVENT_OOB; span->event_header.enum_id = event_id; @@ -1436,120 +1451,15 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event) snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno)); return FTDM_FAIL; } - ftdm_log_chan(span->channels[i], 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_API_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_API_EVENT_RXHOOK: - { - if (span->channels[i]->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(span->channels[i], FTDM_CHANNEL_FLASH)) { - ftdm_clear_flag_locked(span->channels[i], FTDM_CHANNEL_FLASH); - ftdm_clear_flag_locked(span->channels[i], FTDM_CHANNEL_WINK); - event_id = FTDM_OOB_FLASH; - goto event; - } else { - ftdm_set_flag_locked(span->channels[i], FTDM_CHANNEL_WINK); - } - } else { - if (ftdm_test_flag(span->channels[i], FTDM_CHANNEL_WINK)) { - ftdm_clear_flag_locked(span->channels[i], FTDM_CHANNEL_WINK); - ftdm_clear_flag_locked(span->channels[i], FTDM_CHANNEL_FLASH); - event_id = FTDM_OOB_WINK; - goto event; - } else { - ftdm_set_flag_locked(span->channels[i], FTDM_CHANNEL_FLASH); - } - } - continue; - } else { - int err; - ftdm_channel_t *ftdmchan = span->channels[i]; - err=sangoma_tdm_txsig_onhook(ftdmchan->sockfd,&tdm_api); - if (err) { - snprintf(span->channels[i]->last_error, sizeof(span->channels[i]->last_error), "ONHOOK Failed"); - return FTDM_FAIL; - } - event_id = 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_API_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_API_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_API_EVENT_RBS: - { - event_id = FTDM_OOB_CAS_BITS_CHANGE; - span->channels[i]->rx_cas_bits = wanpipe_swap_bits(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_rbs_bits); - } - break; - case WP_API_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_API_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; - case WP_API_EVENT_POLARITY_REVERSE: - { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Got polarity reverse\n"); - event_id = FTDM_OOB_POLARITY_REVERSE; - } - 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; + ftdm_channel_lock(ftdmchan); + if ((wanpipe_channel_process_event(ftdmchan, &event_id, &tdm_api)) != FTDM_SUCCESS) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failed to process events from channel\n"); + ftdm_channel_unlock(ftdmchan); + return FTDM_FAIL; } + ftdm_channel_unlock(ftdmchan); event: @@ -1561,9 +1471,7 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event) return FTDM_SUCCESS; } } - return FTDM_FAIL; - } /** diff --git a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c index fe0ed7c756..5b507bd0b9 100644 --- a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c +++ b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c @@ -993,27 +993,14 @@ FIO_SPAN_POLL_EVENT_FUNCTION(zt_poll_event) } /** - * \brief Retrieves an event from a ftdm channel - * \param ftdmchan Channel to retrieve event from - * \param event FreeTDM event to return - * \return Success or failure + * \brief Process an event from a ftdmchan and set the proper OOB event_id. The channel must be locked. + * \param fchan Channel to retrieve event from + * \param event_id Pointer to OOB event id + * \param zt_event_id Zaptel event id + * \return FTDM_SUCCESS or FTDM_FAIL */ -FIO_CHANNEL_NEXT_EVENT_FUNCTION(zt_channel_next_event) +static __inline__ ftdm_status_t zt_channel_process_event(ftdm_channel_t *fchan, ftdm_oob_event_t *event_id, zt_event_t zt_event_id) { - ftdm_oob_event_t event_id = FTDM_OOB_INVALID; - zt_event_t zt_event_id = 0; - ftdm_span_t *span = ftdmchan->span; - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT)) { - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_EVENT); - } - - if (ioctl(ftdmchan->sockfd, codes.GETEVENT, &zt_event_id) == -1) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed retrieving event from channel: %s\n", - strerror(errno)); - return FTDM_FAIL; - } - switch(zt_event_id) { case ZT_EVENT_RINGEROFF: { @@ -1027,63 +1014,93 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(zt_channel_next_event) break; case ZT_EVENT_RINGBEGIN: { - event_id = FTDM_OOB_RING_START; + *event_id = FTDM_OOB_RING_START; } break; case ZT_EVENT_ONHOOK: { - event_id = FTDM_OOB_ONHOOK; + *event_id = FTDM_OOB_ONHOOK; } break; case ZT_EVENT_WINKFLASH: { - if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN || ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) { - event_id = FTDM_OOB_WINK; + if (fchan->state == FTDM_CHANNEL_STATE_DOWN || fchan->state == FTDM_CHANNEL_STATE_DIALING) { + *event_id = FTDM_OOB_WINK; } else { - event_id = FTDM_OOB_FLASH; + *event_id = FTDM_OOB_FLASH; } } break; case ZT_EVENT_RINGOFFHOOK: { - if (ftdmchan->type == FTDM_CHAN_TYPE_FXS || (ftdmchan->type == FTDM_CHAN_TYPE_EM && ftdmchan->state != FTDM_CHANNEL_STATE_UP)) { - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK); - event_id = FTDM_OOB_OFFHOOK; - } else if (ftdmchan->type == FTDM_CHAN_TYPE_FXO) { - event_id = FTDM_OOB_RING_START; + if (fchan->type == FTDM_CHAN_TYPE_FXS || (fchan->type == FTDM_CHAN_TYPE_EM && fchan->state != FTDM_CHANNEL_STATE_UP)) { + ftdm_set_flag_locked(fchan, FTDM_CHANNEL_OFFHOOK); + *event_id = FTDM_OOB_OFFHOOK; + } else if (fchan->type == FTDM_CHAN_TYPE_FXO) { + *event_id = FTDM_OOB_RING_START; } else { - event_id = FTDM_OOB_NOOP; + *event_id = FTDM_OOB_NOOP; } } break; case ZT_EVENT_ALARM: { - event_id = FTDM_OOB_ALARM_TRAP; + *event_id = FTDM_OOB_ALARM_TRAP; } break; case ZT_EVENT_NOALARM: { - event_id = FTDM_OOB_ALARM_CLEAR; + *event_id = FTDM_OOB_ALARM_CLEAR; } break; case ZT_EVENT_BITSCHANGED: { - event_id = FTDM_OOB_CAS_BITS_CHANGE; + *event_id = FTDM_OOB_CAS_BITS_CHANGE; int bits = 0; - int err = ioctl(ftdmchan->sockfd, codes.GETRXBITS, &bits); + int err = ioctl(fchan->sockfd, codes.GETRXBITS, &bits); if (err) { return FTDM_FAIL; } - ftdmchan->rx_cas_bits = bits; + fchan->rx_cas_bits = bits; } break; default: { - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unhandled event %d\n", zt_event_id); - event_id = FTDM_OOB_INVALID; + ftdm_log_chan(fchan, FTDM_LOG_WARNING, "Unhandled event %d\n", zt_event_id); + *event_id = FTDM_OOB_INVALID; } break; } + return FTDM_SUCCESS; +} + +/** + * \brief Retrieves an event from a ftdm channel + * \param ftdmchan Channel to retrieve event from + * \param event FreeTDM event to return + * \return Success or failure + */ +FIO_CHANNEL_NEXT_EVENT_FUNCTION(zt_channel_next_event) +{ + uint32_t event_id = FTDM_OOB_INVALID; + zt_event_t zt_event_id = 0; + ftdm_span_t *span = ftdmchan->span; + + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT)) { + ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_EVENT); + } + + if (ioctl(ftdmchan->sockfd, codes.GETEVENT, &zt_event_id) == -1) { + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed retrieving event from channel: %s\n", + strerror(errno)); + return FTDM_FAIL; + } + + /* the core already locked the channel for us, so it's safe to call zt_channel_process_event() here */ + if ((zt_channel_process_event(ftdmchan, &event_id, zt_event_id)) != FTDM_SUCCESS) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failed to process event from channel\n"); + return FTDM_FAIL; + } ftdmchan->last_event_time = 0; span->event_header.e_type = FTDM_EVENT_OOB; @@ -1105,91 +1122,29 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event) zt_event_t zt_event_id = 0; for(i = 1; i <= span->chan_count; i++) { - if (ftdm_test_flag(span->channels[i], FTDM_CHANNEL_EVENT)) { - ftdm_clear_flag(span->channels[i], FTDM_CHANNEL_EVENT); - if (ioctl(span->channels[i]->sockfd, codes.GETEVENT, &zt_event_id) == -1) { - snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno)); - return FTDM_FAIL; - } - - switch(zt_event_id) { - case ZT_EVENT_RINGEROFF: - { - return FTDM_FAIL; - } - break; - case ZT_EVENT_RINGERON: - { - return FTDM_FAIL; - } - break; - case ZT_EVENT_RINGBEGIN: - { - event_id = FTDM_OOB_RING_START; - } - break; - case ZT_EVENT_ONHOOK: - { - event_id = FTDM_OOB_ONHOOK; - } - break; - case ZT_EVENT_WINKFLASH: - { - if (span->channels[i]->state == FTDM_CHANNEL_STATE_DOWN || span->channels[i]->state == FTDM_CHANNEL_STATE_DIALING) { - event_id = FTDM_OOB_WINK; - } else { - event_id = FTDM_OOB_FLASH; - } - } - break; - case ZT_EVENT_RINGOFFHOOK: - { - if (span->channels[i]->type == FTDM_CHAN_TYPE_FXS || (span->channels[i]->type == FTDM_CHAN_TYPE_EM && span->channels[i]->state != FTDM_CHANNEL_STATE_UP)) { - ftdm_set_flag_locked(span->channels[i], FTDM_CHANNEL_OFFHOOK); - event_id = FTDM_OOB_OFFHOOK; - } else if (span->channels[i]->type == FTDM_CHAN_TYPE_FXO) { - event_id = FTDM_OOB_RING_START; - } else { - event_id = FTDM_OOB_NOOP; - } - } - break; - case ZT_EVENT_ALARM: - { - event_id = FTDM_OOB_ALARM_TRAP; - } - break; - case ZT_EVENT_NOALARM: - { - event_id = FTDM_OOB_ALARM_CLEAR; - } - break; - case ZT_EVENT_BITSCHANGED: - { - event_id = FTDM_OOB_CAS_BITS_CHANGE; - int bits = 0; - int err = ioctl(span->channels[i]->sockfd, codes.GETRXBITS, &bits); - if (err) { - return FTDM_FAIL; - } - span->channels[i]->rx_cas_bits = bits; - } - break; - default: - { - ftdm_log(FTDM_LOG_WARNING, "Unhandled event %d for %d:%d\n", zt_event_id, span->span_id, i); - event_id = FTDM_OOB_INVALID; - } - break; - } - - span->channels[i]->last_event_time = 0; - span->event_header.e_type = FTDM_EVENT_OOB; - span->event_header.enum_id = event_id; - span->event_header.channel = span->channels[i]; - *event = &span->event_header; - return FTDM_SUCCESS; + ftdm_channel_t *fchan = span->channels[i]; + if (ftdm_test_flag(fchan, FTDM_CHANNEL_EVENT)) { + ftdm_clear_flag(fchan, FTDM_CHANNEL_EVENT); } + if (ioctl(fchan->sockfd, codes.GETEVENT, &zt_event_id) == -1) { + snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno)); + return FTDM_FAIL; + } + + ftdm_channel_lock(fchan); + if ((zt_channel_process_event(fchan, &event_id, zt_event_id)) != FTDM_SUCCESS) { + ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Failed to process event from channel\n"); + ftdm_channel_unlock(fchan); + return FTDM_FAIL; + } + ftdm_channel_unlock(fchan); + + fchan->last_event_time = 0; + span->event_header.e_type = FTDM_EVENT_OOB; + span->event_header.enum_id = event_id; + span->event_header.channel = fchan; + *event = &span->event_header; + return FTDM_SUCCESS; } return FTDM_FAIL;