From a6e868f588572034dbf41866432138aa54a10aa4 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Thu, 16 Feb 2012 14:49:18 -0500 Subject: [PATCH] freetdm: Fix spirou certification native bridge issue - The outgoing tdm leg should not move to UP until after the IAM is sent at the end of the function - The UP state should be processed immediately otherwise the state processor is not run due to the way the main ss7 processing loop currently works --- libs/freetdm/src/ftdm_state.c | 10 +++++++-- .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c | 21 ++++++++++++++++--- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/libs/freetdm/src/ftdm_state.c b/libs/freetdm/src/ftdm_state.c index 30ef3ce478..03f2cd8e18 100644 --- a/libs/freetdm/src/ftdm_state.c +++ b/libs/freetdm/src/ftdm_state.c @@ -48,9 +48,15 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_complete_state(const char *file, const c ftdm_time_t diff = 0; ftdm_channel_state_t state = fchan->state; + if (fchan->state_status == FTDM_STATE_STATUS_NEW) { + ftdm_log_chan_ex(fchan, file, func, line, FTDM_LOG_LEVEL_CRIT, + "Asking to complete state change from %s to %s in %llums, but the state is still unprocessed (this might be a bug!)\n", + ftdm_channel_state2str(fchan->last_state), ftdm_channel_state2str(state), diff); + /* We should probably return here with FTDM_FAIL if we don't see this message in production environments for a while (2012-02-16) */ + } + if (fchan->state_status == FTDM_STATE_STATUS_COMPLETED) { - ftdm_assert_return(!ftdm_test_flag(fchan, FTDM_CHANNEL_STATE_CHANGE), FTDM_FAIL, - "State change flag set but state is not completed\n"); + ftdm_assert_return(!ftdm_test_flag(fchan, FTDM_CHANNEL_STATE_CHANGE), FTDM_FAIL, "State change flag set but state is already completed\n"); return FTDM_SUCCESS; } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c index 00d06905dd..7ad510079f 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c @@ -46,6 +46,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan) { const char *var = NULL; SiConEvnt iam; + ftdm_bool_t native_going_up = FTDM_FALSE; sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;; SS7_FUNC_TRACE_ENTER (__FUNCTION__); @@ -81,9 +82,11 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan) /* flush our own queue */ sngss7_flush_queue(sngss7_info->event_queue); - /* go up until release comes, note that state processing is done different and much simpler when there is a peer */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); - ftdm_channel_advance_states(ftdmchan); + /* Go to up until release comes, note that state processing is done different and much simpler when there is a peer, + We can't go to UP state right away yet though, so do not set the state to UP here, wait until the end of this function + because moving from one state to another causes the ftdmchan->usrmsg structure to be wiped + and we still need those variables for further IAM processing */ + native_going_up = FTDM_TRUE; } } } @@ -211,6 +214,18 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan) &iam, 0); + if (native_going_up) { + /* + Note that this function (ft_to_sngss7_iam) is run within the main SS7 processing loop in + response to the DIALING state handler, we can set the state to UP here and that will + implicitly complete the DIALING state, but we *MUST* also advance the state handler + right away for a native bridge, otherwise, the processing state function (ftdm_sangoma_ss7_process_state_change) + will complete the state without having executed the handler for FTDM_CHANNEL_STATE_UP, and we won't notify + the user sending FTDM_SIGEVENT_UP which can cause the application to misbehave (ie, no audio) */ + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); + ftdm_channel_advance_states(ftdmchan); + } + SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; }