diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index 949ea154e3..ec7fe39c7d 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -562,14 +562,18 @@ static ftdm_status_t 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: { ftdm_channel_t *chtmp = chan; - chan->call_data = NULL; + + if (call) { + pri_destroycall(isdn_data->spri.pri, call); + chan->call_data = NULL; + } if (ftdm_channel_close(&chtmp) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_WARNING, "-- Failed to close channel %d:%d\n", @@ -776,8 +780,7 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan) pri_hangup(isdn_data->spri.pri, call, caller_data->hangup_cause); // pri_destroycall(isdn_data->spri.pri, call); - - chan->call_data = NULL; +// chan->call_data = NULL; } ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); } @@ -785,10 +788,10 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan) case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: { - if (call) { - pri_destroycall(isdn_data->spri.pri, call); - chan->call_data = NULL; - } +// if (call) { +// pri_destroycall(isdn_data->spri.pri, call); +// chan->call_data = NULL; +// } ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_DOWN); } break; @@ -862,18 +865,61 @@ static int on_hangup(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_even ftdm_channel_lock(chan); - if (ftdm_channel_get_state(chan) >= FTDM_CHANNEL_STATE_TERMINATING) { - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Ignoring remote hangup in state %s\n", ftdm_channel_get_state_str(chan)); - goto done; + switch (event_type) { + case LPWRAP_PRI_EVENT_HANGUP_REQ: /* DISCONNECT */ + if (ftdm_channel_get_state(chan) >= FTDM_CHANNEL_STATE_TERMINATING) { + ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Ignoring remote hangup in state %s\n", + ftdm_channel_get_state_str(chan)); + goto done; + } + ftdm_log(FTDM_LOG_DEBUG, "-- Hangup REQ on channel %d:%d\n", + ftdm_span_get_id(spri->span), pevent->hangup.channel); + + pri_hangup(spri->pri, pevent->hangup.call, pevent->hangup.cause); + + chan->caller_data.hangup_cause = pevent->hangup.cause; + ftdm_set_state(chan, FTDM_CHANNEL_STATE_TERMINATING); + break; + + case LPWRAP_PRI_EVENT_HANGUP_ACK: /* */ + ftdm_log(FTDM_LOG_DEBUG, "-- Hangup ACK on channel %d:%d\n", + ftdm_span_get_id(spri->span), pevent->hangup.channel); + + pri_hangup(spri->pri, pevent->hangup.call, pevent->hangup.cause); + + ftdm_set_state(chan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); + break; + + case LPWRAP_PRI_EVENT_HANGUP: /* "RELEASE/RELEASE_COMPLETE/other" */ + ftdm_log(FTDM_LOG_DEBUG, "-- Hangup on channel %d:%d\n", + ftdm_span_get_id(spri->span), pevent->hangup.channel); + + switch (ftdm_channel_get_state(chan)) { + case FTDM_CHANNEL_STATE_DIALING: + case FTDM_CHANNEL_STATE_RINGING: + case FTDM_CHANNEL_STATE_PROGRESS: + case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: + case FTDM_CHANNEL_STATE_PROCEED: + case FTDM_CHANNEL_STATE_UP: + chan->caller_data.hangup_cause = pevent->hangup.cause; + ftdm_set_state(chan, FTDM_CHANNEL_STATE_TERMINATING); + break; + case FTDM_CHANNEL_STATE_HANGUP: + chan->caller_data.hangup_cause = pevent->hangup.cause; + ftdm_set_state(chan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); + break; +// case FTDM_CHANNEL_STATE_TERMINATING: +// ftdm_set_state(chan, FTDM_CHANNEL_STATE_HANGUP); +// break; +// case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: +// ftdm_set_state(chan, FTDM_CHANNEL_STATE_DOWN); +// break; + } + break; + default: + break; } - ftdm_log(FTDM_LOG_DEBUG, "-- Hangup on channel %d:%d\n", ftdm_span_get_id(spri->span), pevent->hangup.channel); - - pri_hangup(spri->pri, pevent->hangup.call, -1); - - chan->caller_data.hangup_cause = pevent->hangup.cause; - chan->call_data = NULL; - ftdm_set_state(chan, FTDM_CHANNEL_STATE_TERMINATING); done: ftdm_channel_unlock(chan); return 0; @@ -1644,6 +1690,7 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj) LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_DCHAN_UP, on_dchan_up); LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_DCHAN_DOWN, on_dchan_down); LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_HANGUP_REQ, on_hangup); + LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_HANGUP_ACK, on_hangup); LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_HANGUP, on_hangup); LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_INFO_RECEIVED, on_info); LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RESTART, on_restart);