From fe0d8d1ec508d96d6edc08ec610f142633e896bf Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 31 Dec 2010 13:44:20 -0500 Subject: [PATCH] freetdm: - updated all signaling modules (except for ftmod_isdn and ftmod_sangoma_ss7) to adapt to new core state processing - fixed bug in configure.ac to detect ftmod_pritap compilation - ignore FTDM_SIGEVENT_RELEASED and FTDM_SIGEVENT_INDICATION_COMPLETED in mod_freetdm - Destroy the state completed interrupt on channel destroy - Fix analog polarity reversal bug when using 3-way calling or call-swap --- libs/freetdm/configure.ac | 2 +- libs/freetdm/mod_freetdm/mod_freetdm.c | 14 ++++---- libs/freetdm/src/ftdm_io.c | 3 ++ libs/freetdm/src/ftdm_state.c | 18 +++++++--- .../src/ftmod/ftmod_analog/ftmod_analog.c | 14 ++++---- .../ftmod/ftmod_analog_em/ftmod_analog_em.c | 1 - .../src/ftmod/ftmod_libpri/ftmod_libpri.c | 15 ++++----- .../src/ftmod/ftmod_pritap/ftmod_pritap.c | 29 ++++++++-------- .../ftmod_sangoma_boost/ftmod_sangoma_boost.c | 33 ++++++------------- libs/freetdm/src/include/freetdm.h | 2 +- libs/freetdm/src/include/private/ftdm_core.h | 2 +- 11 files changed, 65 insertions(+), 68 deletions(-) diff --git a/libs/freetdm/configure.ac b/libs/freetdm/configure.ac index e26f10b0b2..a070e994a3 100644 --- a/libs/freetdm/configure.ac +++ b/libs/freetdm/configure.ac @@ -160,7 +160,7 @@ AC_ARG_WITH([pritap], [AS_HELP_STRING([--with-pritap], [Install ftmod_pritap])], [case "${withval}" in no) enable_pritap="no" ;; - *) enable_pritab="yes" ;; + *) enable_pritap="yes" ;; esac], [enable_pritap="no"] ) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index e08d4c1f3b..7bbdef6dae 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -1642,6 +1642,14 @@ static FIO_SIGNAL_CB_FUNCTION(on_common_signal) } return FTDM_SUCCESS; } + + case FTDM_SIGEVENT_RELEASED: + case FTDM_SIGEVENT_INDICATION_COMPLETED: + { + /* Swallow these events */ + return FTDM_BREAK; + } + break; default: return FTDM_SUCCESS; break; @@ -1732,7 +1740,6 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxo_signal) } } break; - case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break; case FTDM_SIGEVENT_SIGSTATUS_CHANGED: { /* twiddle */ } break; default: @@ -1788,7 +1795,6 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxs_signal) } } break; - case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break; case FTDM_SIGEVENT_STOP: { @@ -2015,8 +2021,6 @@ static FIO_SIGNAL_CB_FUNCTION(on_r2_signal) } break; - case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break; - /* on DNIS received from the R2 forward side, return status == FTDM_BREAK to stop requesting DNIS */ case FTDM_SIGEVENT_COLLECTED_DIGIT: { @@ -2135,8 +2139,6 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal) } break; - case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break; - case FTDM_SIGEVENT_STOP: case FTDM_SIGEVENT_RESTART: { diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 5c900b91dd..a1c5ceea88 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -615,6 +615,9 @@ static ftdm_status_t ftdm_channel_destroy(ftdm_channel_t *ftdmchan) ftdm_mutex_destroy(&ftdmchan->mutex); ftdm_mutex_destroy(&ftdmchan->pre_buffer_mutex); + if (ftdmchan->state_completed_interrupt) { + ftdm_interrupt_destroy(&ftdmchan->state_completed_interrupt); + } } return FTDM_SUCCESS; diff --git a/libs/freetdm/src/ftdm_state.c b/libs/freetdm/src/ftdm_state.c index 2f42282756..0221fa2a1e 100644 --- a/libs/freetdm/src/ftdm_state.c +++ b/libs/freetdm/src/ftdm_state.c @@ -103,7 +103,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_complete_state(const char *file, const c if (ftdm_test_flag(fchan, FTDM_CHANNEL_BLOCKING)) { ftdm_clear_flag(fchan, FTDM_CHANNEL_BLOCKING); - ftdm_interrupt_signal(fchan->state_change_notify); + ftdm_interrupt_signal(fchan->state_completed_interrupt); } return FTDM_SUCCESS; @@ -194,8 +194,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_set_state(const char *file, const char *f return FTDM_FAIL; } - if (!ftdmchan->state_change_notify) { - status = ftdm_interrupt_create(&ftdmchan->state_change_notify, FTDM_INVALID_SOCKET); + if (!ftdmchan->state_completed_interrupt) { + status = ftdm_interrupt_create(&ftdmchan->state_completed_interrupt, FTDM_INVALID_SOCKET); if (status != FTDM_SUCCESS) { ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_CRIT, "Failed to create state change interrupt when moving from %s to %s\n", ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state)); @@ -323,17 +323,23 @@ end: goto done; } + if (!waitrq) { + /* no waiting was requested */ + goto done; + } + + /* let's wait for the state change to be completed by the signaling stack */ ftdm_set_flag(ftdmchan, FTDM_CHANNEL_BLOCKING); ftdm_mutex_unlock(ftdmchan->mutex); - status = ftdm_interrupt_wait(ftdmchan->state_change_notify, waitms); + status = ftdm_interrupt_wait(ftdmchan->state_completed_interrupt, waitms); ftdm_mutex_lock(ftdmchan->mutex); if (status != FTDM_SUCCESS) { ftdm_log_chan_ex(ftdmchan, file, func, line, - FTDM_LOG_LEVEL_WARNING, "state change from %s to %s was most likely not processed after aprox %dms\n", + FTDM_LOG_LEVEL_WARNING, "state change from %s to %s was most likely not completed after aprox %dms\n", ftdm_channel_state2str(ftdmchan->last_state), ftdm_channel_state2str(state), DEFAULT_WAIT_TIME); ok = 0; goto done; @@ -437,6 +443,8 @@ FT_DECLARE(char *) ftdm_channel_get_history_str(const ftdm_channel_t *fchan) FT_DECLARE(ftdm_status_t) ftdm_channel_advance_states(ftdm_channel_t *fchan) { ftdm_channel_state_t state; + + ftdm_assert_return(fchan->span->state_processor, FTDM_FAIL, "Cannot process states without a state processor!\n"); while (fchan->state_status == FTDM_STATE_STATUS_NEW) { state = fchan->state; diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c index 981df5dcc9..818f1c5754 100644 --- a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c +++ b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c @@ -585,8 +585,8 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) if (done) { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_STATE_CHANGE); ftdm_clear_flag_locked(ftdmchan->span, FTDM_SPAN_STATE_CHANGE); + ftdm_channel_complete_state(ftdmchan); ftdmchan->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK] = 0; } } @@ -628,7 +628,6 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) break; } } else { - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_STATE_CHANGE); ftdm_clear_flag_locked(ftdmchan->span, FTDM_SPAN_STATE_CHANGE); ftdm_channel_complete_state(ftdmchan); indicate = 0; @@ -672,11 +671,12 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) && ftdm_test_flag(analog_data, FTDM_ANALOG_ANSWER_POLARITY_REVERSE)) { ftdm_polarity_t polarity = FTDM_POLARITY_REVERSE; - if (ftdmchan->polarity != FTDM_POLARITY_FORWARD) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Polarity is already reversed on answer??\n"); - } else { + if (ftdmchan->polarity == FTDM_POLARITY_FORWARD) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Reversing polarity on answer\n"); ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_POLARITY, &polarity); + } else { + /* the polarity may be already reversed if this is the second time we + * answer (ie, due to 2 calls being on the same line) */ } } @@ -1036,8 +1036,8 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e if (event->channel->state != FTDM_CHANNEL_STATE_DOWN) { if (event->channel->state == FTDM_CHANNEL_STATE_HANGUP && ftdm_test_flag(event->channel, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_clear_flag(event->channel, FTDM_CHANNEL_STATE_CHANGE); /* we do not need to process HANGUP since the device also hangup already */ + ftdm_channel_complete_state(event->channel); } ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_DOWN); } @@ -1052,8 +1052,8 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e { if (event->channel->state == FTDM_CHANNEL_STATE_CALLWAITING) { ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_UP); - ftdm_clear_flag(event->channel, FTDM_CHANNEL_STATE_CHANGE); ftdm_clear_flag(event->channel->span, FTDM_SPAN_STATE_CHANGE); + ftdm_channel_complete_state(event->channel); event->channel->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK] = 0; } diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c index 843ac484a5..31c2421b9b 100644 --- a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c +++ b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c @@ -355,7 +355,6 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj) break; } } else { - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_STATE_CHANGE); ftdm_clear_flag_locked(ftdmchan->span, FTDM_SPAN_STATE_CHANGE); ftdm_channel_complete_state(ftdmchan); indicate = 0; diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index 1d3c76d2e2..8be6d579e1 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -497,7 +497,7 @@ static ftdm_state_map_t isdn_state_map = { * \param ftdmchan Channel to handle * \note This function MUST be called with the channel locked */ -static __inline__ void state_advance(ftdm_channel_t *chan) +static ftdm_status_t state_advance(ftdm_channel_t *chan) { ftdm_libpri_data_t *isdn_data = chan->span->signal_data; q931_call *call = (q931_call *)chan->call_data; @@ -511,6 +511,8 @@ static __inline__ void state_advance(ftdm_channel_t *chan) sig.chan_id = ftdm_channel_get_id(chan); sig.span_id = ftdm_channel_get_span_id(chan); sig.channel = chan; + + ftdm_channel_complete_state(chan); switch (ftdm_channel_get_state(chan)) { case FTDM_CHANNEL_STATE_DOWN: @@ -625,7 +627,7 @@ static __inline__ void state_advance(ftdm_channel_t *chan) ftdm_channel_get_span_id(chan), ftdm_channel_get_id(chan)); /* TODO: set hangup cause? */ ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART); - return; + return FTDM_SUCCESS; } ton = caller_data->dnis.type; @@ -708,6 +710,7 @@ static __inline__ void state_advance(ftdm_channel_t *chan) default: break; } + return FTDM_SUCCESS; } /** @@ -723,13 +726,8 @@ static __inline__ void check_state(ftdm_span_t *span) for (j = 1; j <= ftdm_span_get_chan_count(span); j++) { ftdm_channel_t *chan = ftdm_span_get_channel(span, j); - ftdm_channel_lock(chan); - while (ftdm_test_flag(chan, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_clear_flag(chan, FTDM_CHANNEL_STATE_CHANGE); - state_advance(chan); - ftdm_channel_complete_state(chan); - } + ftdm_channel_advance_states(chan); ftdm_channel_unlock(chan); } } @@ -1910,6 +1908,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span) span->outgoing_call = isdn_outgoing_call; span->state_map = &isdn_state_map; + span->state_processor = state_advance; span->get_channel_sig_status = isdn_get_channel_sig_status; span->get_span_sig_status = isdn_get_span_sig_status; diff --git a/libs/freetdm/src/ftmod/ftmod_pritap/ftmod_pritap.c b/libs/freetdm/src/ftmod/ftmod_pritap/ftmod_pritap.c index 27fbe2139f..48a2f012eb 100644 --- a/libs/freetdm/src/ftmod/ftmod_pritap/ftmod_pritap.c +++ b/libs/freetdm/src/ftmod/ftmod_pritap/ftmod_pritap.c @@ -265,7 +265,7 @@ static ftdm_state_map_t pritap_state_map = { } }; -static __inline__ void state_advance(ftdm_channel_t *ftdmchan) +static ftdm_status_t state_advance(ftdm_channel_t *ftdmchan) { ftdm_status_t status; ftdm_sigmsg_t sig; @@ -278,6 +278,8 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) sig.span_id = ftdmchan->span_id; sig.channel = ftdmchan; + ftdm_channel_complete_state(ftdmchan); + switch (ftdmchan->state) { case FTDM_CHANNEL_STATE_DOWN: { @@ -321,24 +323,20 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) break; } - return; + return FTDM_SUCCESS; } static __inline__ void pritap_check_state(ftdm_span_t *span) { - if (ftdm_test_flag(span, FTDM_SPAN_STATE_CHANGE)) { - uint32_t j; - ftdm_clear_flag_locked(span, FTDM_SPAN_STATE_CHANGE); - for(j = 1; j <= span->chan_count; j++) { - if (ftdm_test_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_mutex_lock(span->channels[j]->mutex); - ftdm_clear_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE); - state_advance(span->channels[j]); - ftdm_channel_complete_state(span->channels[j]); - ftdm_mutex_unlock(span->channels[j]->mutex); - } - } - } + if (ftdm_test_flag(span, FTDM_SPAN_STATE_CHANGE)) { + uint32_t j; + ftdm_clear_flag_locked(span, FTDM_SPAN_STATE_CHANGE); + for(j = 1; j <= span->chan_count; j++) { + ftdm_mutex_lock(span->channels[j]->mutex); + ftdm_channel_advance_states(span->channels[j]); + ftdm_mutex_unlock(span->channels[j]->mutex); + } + } } static int pri_io_read(struct pri *pri, void *buf, int buflen) @@ -896,6 +894,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_pritap_configure_span) span->get_span_sig_status = pritap_get_span_sig_status; span->state_map = &pritap_state_map; + span->state_processor = state_advance; return FTDM_SUCCESS; } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c index 97e242dacb..d0bc14c8d8 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c @@ -951,7 +951,6 @@ static void handle_call_answer(ftdm_span_t *span, sangomabc_connection_t *mcon, } } -static __inline__ void advance_chan_states(ftdm_channel_t *ftdmchan); static __inline__ void stop_loop(ftdm_channel_t *ftdmchan); /** @@ -1002,7 +1001,7 @@ tryagain: } else if (ftdmchan->state == FTDM_CHANNEL_STATE_IN_LOOP && retry) { retry = 0; stop_loop(ftdmchan); - advance_chan_states(ftdmchan); + ftdm_channel_advance_states(ftdmchan); goto tryagain; } else { ftdm_log(FTDM_LOG_ERROR, "s%dc%d: rejecting incoming call in channel state %s\n", @@ -1267,7 +1266,7 @@ static ftdm_channel_t* event_process_states(ftdm_span_t *span, sangomabc_short_e } ftdm_mutex_lock(ftdmchan->mutex); - advance_chan_states(ftdmchan); + ftdm_channel_advance_states(ftdmchan); return ftdmchan; } @@ -1354,11 +1353,11 @@ static int parse_sangoma_event(ftdm_span_t *span, sangomabc_connection_t *mcon, } if(ftdmchan != NULL) { - advance_chan_states(ftdmchan); + ftdm_channel_advance_states(ftdmchan); ftdm_mutex_unlock(ftdmchan->mutex); } - return 0; + return 0; } @@ -1366,7 +1365,7 @@ static int parse_sangoma_event(ftdm_span_t *span, sangomabc_connection_t *mcon, * \brief Handler for channel state change * \param ftdmchan Channel to handle */ -static __inline__ ftdm_status_t state_advance(ftdm_channel_t *ftdmchan) +static ftdm_status_t state_advance(ftdm_channel_t *ftdmchan) { ftdm_sangoma_boost_data_t *sangoma_boost_data = ftdmchan->span->signal_data; sangomabc_connection_t *mcon = &sangoma_boost_data->mcon; @@ -1374,12 +1373,6 @@ static __inline__ ftdm_status_t state_advance(ftdm_channel_t *ftdmchan) ftdm_status_t status; - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE); - } else { - return FTDM_SUCCESS; - } - ftdm_assert_return(ftdmchan->last_state != ftdmchan->state, FTDM_FAIL, "Channel state already processed\n"); ftdm_log(FTDM_LOG_DEBUG, "%d:%d PROCESSING STATE [%s]\n", ftdmchan->span_id, ftdmchan->chan_id, ftdm_channel_state2str(ftdmchan->state)); @@ -1389,6 +1382,8 @@ static __inline__ ftdm_status_t state_advance(ftdm_channel_t *ftdmchan) sig.span_id = ftdmchan->span_id; sig.channel = ftdmchan; + ftdm_channel_complete_state(ftdmchan); + switch (ftdmchan->state) { case FTDM_CHANNEL_STATE_DOWN: { @@ -1640,24 +1635,15 @@ static __inline__ ftdm_status_t state_advance(ftdm_channel_t *ftdmchan) default: break; } - ftdm_channel_complete_state(ftdmchan); return FTDM_SUCCESS; } -static __inline__ void advance_chan_states(ftdm_channel_t *ftdmchan) -{ - while (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { - state_advance(ftdmchan); - } -} - /** * \brief Initialises outgoing requests array */ static __inline__ void init_outgoing_array(void) { memset(&OUTBOUND_REQUESTS, 0, sizeof(OUTBOUND_REQUESTS)); - } /** @@ -1685,7 +1671,7 @@ static __inline__ void check_state(ftdm_span_t *span) if (susp && span->channels[j]->state != FTDM_CHANNEL_STATE_DOWN) { ftdm_set_state(span->channels[j], FTDM_CHANNEL_STATE_RESTART); } - state_advance(span->channels[j]); + ftdm_channel_advance_states(span->channels[j]); ftdm_mutex_unlock(span->channels[j]->mutex); } } @@ -1695,7 +1681,7 @@ static __inline__ void check_state(ftdm_span_t *span) * but without taking the chan out of the queue, so check th * flag before advancing the state */ ftdm_mutex_lock(ftdmchan->mutex); - state_advance(ftdmchan); + ftdm_channel_advance_states(ftdmchan); ftdm_mutex_unlock(ftdmchan->mutex); } } @@ -2687,6 +2673,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_boost_configure_span) span->get_span_sig_status = sangoma_boost_get_span_sig_status; span->set_span_sig_status = sangoma_boost_set_span_sig_status; span->state_map = &boost_state_map; + span->state_processor = state_advance; sangoma_boost_data->mcon.debuglevel = FTDM_LOG_LEVEL_DEBUG; sangoma_boost_data->pcon.debuglevel = FTDM_LOG_LEVEL_DEBUG; ftdm_clear_flag(span, FTDM_SPAN_SUGGEST_CHAN_ID); diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 3e8ad287bd..38bc61188b 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -583,10 +583,10 @@ typedef enum { FTDM_COMMAND_GET_LINK_STATUS, FTDM_COMMAND_ENABLE_LOOP, FTDM_COMMAND_DISABLE_LOOP, - FTDM_COMMAND_COUNT, FTDM_COMMAND_SET_RX_QUEUE_SIZE, FTDM_COMMAND_SET_TX_QUEUE_SIZE, FTDM_COMMAND_SET_POLARITY, + FTDM_COMMAND_COUNT, } ftdm_command_t; typedef enum { diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 829b4069a1..55fb8ba032 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -462,7 +462,7 @@ struct ftdm_channel { ftdm_dtmf_debug_t dtmfdbg; ftdm_io_dump_t rxdump; ftdm_io_dump_t txdump; - ftdm_interrupt_t *state_change_notify; /*!< Notify when a state change is terminated */ + ftdm_interrupt_t *state_completed_interrupt; /*!< Notify when a state change is completed */ int32_t txdrops; int32_t rxdrops; };