diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 57e11718bb..e9fbba34d4 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -566,7 +566,7 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) } 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); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Device [%d:%d] is no longer attached to %s\n", span_id, chan_id, name); goto end; } @@ -3827,6 +3827,7 @@ static switch_status_t load_config(void) const char *tonegroup = NULL; char *digit_timeout = NULL; char *dial_timeout = NULL; + char *release_guard_time_ms = NULL; char *max_digits = NULL; char *dial_regex = NULL; char *hold_music = NULL; @@ -3836,7 +3837,7 @@ static switch_status_t load_config(void) char *answer_supervision = str_false; char *immediate_ringback = str_false; char *ringback_file = str_empty; - uint32_t span_id = 0, to = 0, max = 0, dial_timeout_int = 0; + uint32_t span_id = 0, to = 0, max = 0, dial_timeout_int = 0, release_guard_time_ms_int = 0; ftdm_span_t *span = NULL; analog_option_t analog_options = ANALOG_OPTION_NONE; @@ -3850,6 +3851,8 @@ static switch_status_t load_config(void) digit_timeout = val; } else if (!strcasecmp(var, "dial-timeout")) { dial_timeout = val; + } else if (!strcasecmp(var, "release-guard-time-ms")) { + release_guard_time_ms = val; } else if (!strcasecmp(var, "context")) { context = val; } else if (!strcasecmp(var, "dialplan")) { @@ -3890,6 +3893,10 @@ static switch_status_t load_config(void) dial_timeout_int = atoi(dial_timeout); } + if (release_guard_time_ms) { + release_guard_time_ms_int = atoi(release_guard_time_ms); + } + if (max_digits) { max = atoi(max_digits); } @@ -3925,6 +3932,7 @@ static switch_status_t load_config(void) "ringback_file", ringback_file, "digit_timeout", &to, "dial_timeout", &dial_timeout_int, + "release_guard_time_ms", &release_guard_time_ms_int, "max_dialstr", &max, FTDM_TAG_END) != FTDM_SUCCESS) { LOAD_ERROR("Error starting FreeTDM span %d\n", span_id); diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 57d5af1b85..ec6c2fb757 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -1490,6 +1490,15 @@ static __inline__ int chan_is_avail(ftdm_channel_t *check) return 0; } } + /* release guard time check */ + if (check->span->sig_release_guard_time_ms && check->last_release_time) { + ftdm_time_t time_diff = (check->last_release_time - ftdm_current_time_in_ms()); + if (time_diff < check->span->sig_release_guard_time_ms) { + return 0; + } + /* circuit now available for outbound dialing */ + check->last_release_time = 0; + } return 1; } @@ -2982,6 +2991,11 @@ static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan) ftdmchan->packet_len = ftdmchan->native_interval * (ftdmchan->effective_codec == FTDM_CODEC_SLIN ? 16 : 8); ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE); } + + if (ftdmchan->span->sig_release_guard_time_ms) { + ftdmchan->last_release_time = ftdm_current_time_in_ms(); + } + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "channel done\n"); return FTDM_SUCCESS; } 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 146885f271..98fde2a514 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 @@ -378,6 +378,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_em_configure_span) uint32_t digit_timeout = 2000; uint32_t max_dialstr = 11; uint32_t dial_timeout = 0; + uint32_t release_guard_time_ms = 500; ftdm_bool_t answer_supervision = FTDM_FALSE; const char *var, *val; int *intval; @@ -429,6 +430,11 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_em_configure_span) break; } max_dialstr = *intval; + } else if (!strcasecmp(var, "release_guard_time_ms")) { + if (!(intval = va_arg(ap, int *))) { + break; + } + release_guard_time_ms = *intval; } else { ftdm_log(FTDM_LOG_ERROR, "Invalid parameter for analog em span: '%s'\n", var); return FTDM_FAIL; @@ -460,6 +466,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_em_configure_span) span->get_span_sig_status = analog_em_get_span_sig_status; span->set_channel_sig_status = analog_em_set_channel_sig_status; span->set_span_sig_status = analog_em_set_span_sig_status; + span->sig_release_guard_time_ms = release_guard_time_ms; ftdm_span_load_tones(span, tonemap); if (immediate_ringback || !ftdm_strlen_zero(ringback_file)) { analog_data->immediate_ringback = FTDM_TRUE; diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 728390dd54..15d8ff248b 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -477,6 +477,7 @@ struct ftdm_channel { int32_t rxdrops; ftdm_usrmsg_t *usrmsg; ftdm_time_t last_state_change_time; + ftdm_time_t last_release_time; }; struct ftdm_span { @@ -514,6 +515,7 @@ struct ftdm_span { ftdm_channel_sig_read_t sig_read; ftdm_channel_sig_write_t sig_write; ftdm_channel_sig_dtmf_t sig_dtmf; + uint32_t sig_release_guard_time_ms; ftdm_channel_state_processor_t state_processor; /*!< This guy is called whenever state processing is required */ void *io_data; /*!< Private I/O data per span. Do not touch unless you are an I/O module */ char *type;