if (call) {
pri_hangup(isdn_data->spri.pri, call, ftdmchan->caller_data.hangup_cause);
pri_destroycall(isdn_data->spri.pri, call);
- ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
- } else {
- ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
- }
+ ftdmchan->call_data = NULL;
+ }
+ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
}
break;
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
{
sig.event_id = FTDM_SIGEVENT_STOP;
status = ftdm_span_send_signal(ftdmchan->span, &sig);
- ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
-
+ /* user moves us to HANGUP and from there we go to DOWN */
}
default:
break;
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_channel_lock(span->channels[j]);
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);
+ ftdm_channel_unlock(span->channels[j]);
}
}
}
q931_call *call = NULL;
ftdmchan = span->channels[pevent->hangup.channel];
- if (ftdmchan) {
- call = (q931_call *) ftdmchan->call_data;
- ftdm_log(FTDM_LOG_DEBUG, "-- Hangup on channel %d:%d\n", spri->span->span_id, pevent->hangup.channel);
- ftdmchan->caller_data.hangup_cause = pevent->hangup.cause;
- pri_release(spri->pri, call, 0);
- pri_destroycall(spri->pri, call);
- ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
- } else {
- ftdm_log(FTDM_LOG_DEBUG, "-- Hangup on channel %d:%d %s but it's not in use?\n", spri->span->span_id,
- pevent->hangup.channel, ftdmchan->chan_id);
+ if (!ftdmchan) {
+ ftdm_log(FTDM_LOG_CRIT, "-- Hangup on channel %d:%d %s but it's not in use?\n", spri->span->span_id, pevent->hangup.channel);
+ return 0;
}
+ ftdm_channel_lock(ftdmchan);
+
+ if (ftdmchan->state >= FTDM_CHANNEL_STATE_TERMINATING) {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Ignoring remote hangup in state %s\n", ftdm_channel_state2str(ftdmchan->state));
+ goto done;
+ }
+
+ if (!ftdmchan->call_data) {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Ignoring remote hangup in state %s with no call data\n", ftdm_channel_state2str(ftdmchan->state));
+ goto done;
+ }
+
+ call = (q931_call *) ftdmchan->call_data;
+ ftdm_log(FTDM_LOG_DEBUG, "-- Hangup on channel %d:%d\n", spri->span->span_id, pevent->hangup.channel);
+ ftdmchan->caller_data.hangup_cause = pevent->hangup.cause;
+ pri_release(spri->pri, call, 0);
+ pri_destroycall(spri->pri, call);
+ ftdmchan->call_data = NULL;
+ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+
+done:
+
+ ftdm_channel_unlock(ftdmchan);
+
return 0;
}