diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index ecd9189b39..003be91b17 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -496,6 +496,14 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) private_t *tech_pvt = NULL; ftdm_chan_type_t chantype; uint32_t tokencnt; + char *uuid = NULL; + uint8_t uuid_found = 0; + uint32_t t = 0; + const char *token = NULL; + int span_id = 0; + int chan_id = 0; + const char *name = NULL; + channel = switch_core_session_get_channel(session); assert(channel != NULL); @@ -503,10 +511,42 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) tech_pvt = switch_core_session_get_private(session); assert(tech_pvt != NULL); + /* ignore any further I/O requests, we're hanging up already! */ + switch_clear_flag_locked(tech_pvt, TFLAG_IO); + + if (!tech_pvt->ftdmchan) { goto end; } + name = switch_channel_get_name(channel); + + span_id = tech_pvt->ftdmchan ? ftdm_channel_get_span_id(tech_pvt->ftdmchan) : 0; + chan_id = tech_pvt->ftdmchan ? ftdm_channel_get_id(tech_pvt->ftdmchan) : 0; + + + /* Now verify the device is still attached to this call :-) + * Sometimes the FS core takes too long (more than 3 seconds) in calling + * channel_on_hangup() and the FreeTDM core decides to take the brute + * force approach and hangup and detach themselves from the call. Later + * when FS finally comes around, we might end up hanging up the device + * attached to another call, this verification avoids that. */ + uuid = switch_core_session_get_uuid(session); + tokencnt = ftdm_channel_get_token_count(tech_pvt->ftdmchan); + for (t = 0; t < tokencnt; t++) { + token = ftdm_channel_get_token(tech_pvt->ftdmchan, t); + if (!zstr(token) && !strcasecmp(uuid, token)) { + uuid_found = 1; + break; + } + } + + if (!uuid_found) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Device [%d:%d] is no longer attached to %s. Nothing to do.\n", span_id, chan_id, name); + goto end; + } + + ftdm_channel_clear_token(tech_pvt->ftdmchan, switch_core_session_get_uuid(session)); chantype = ftdm_channel_get_type(tech_pvt->ftdmchan); @@ -2459,7 +2499,6 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal) switch_set_flag_locked(tech_pvt, TFLAG_DEAD); channel = switch_core_session_get_channel(session); switch_channel_hangup(channel, caller_data->hangup_cause); - ftdm_channel_clear_token(sigmsg->channel, switch_core_session_get_uuid(session)); switch_core_session_rwunlock(session); } }