From a65ba2429833eda44fbd286806a14cc5350d0391 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Sun, 20 Jul 2014 21:45:24 -0400 Subject: [PATCH 1/6] mod_freetdm: Added 'ftdm cas' command to read/write raw CAS bits --- libs/freetdm/mod_freetdm/mod_freetdm.c | 93 ++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 227d5a698f..57e11718bb 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -5243,6 +5243,98 @@ end: return SWITCH_STATUS_SUCCESS; } +#define CASINTS(cas) ((cas) & (1 << 3)) ? 1 : 0, \ + ((cas) & (1 << 2)) ? 1 : 0, \ + ((cas) & (1 << 1)) ? 1 : 0, \ + ((cas) & (1 << 0)) ? 1 : 0 +FTDM_CLI_DECLARE(ftdm_cmd_cas) +{ + uint32_t chan_id = 0; + switch_bool_t do_read = SWITCH_FALSE; + ftdm_channel_t *chan; + ftdm_iterator_t *iter = NULL; + ftdm_iterator_t *curr = NULL; + ftdm_span_t *span = NULL; + const char *write_bits_str = ""; + int32_t abcd_bits = 0; + + if (argc < 3) { + print_usage(stream, cli); + goto end; + } + + if (!strcasecmp(argv[1], "read")) { + do_read = SWITCH_TRUE; + chan_id = argc > 3 ? atoi(argv[3]) : 0; + } else if (!strcasecmp(argv[1], "write") && argc >= 4) { + const char *str = NULL; + int mask = 0x08; + do_read = SWITCH_FALSE; + if (argc == 4) { + chan_id = 0; + write_bits_str = argv[3]; + } else { + chan_id = atoi(argv[3]); + write_bits_str = argv[4]; + } + if (strlen(write_bits_str) != 4) { + stream->write_function(stream, "-ERR Invalid CAS bits '%s'. CAS ABCD string must be composed of only four 1's and 0's (e.g. 1101)\n", write_bits_str); + goto end; + } + str = write_bits_str; + while (*str) { + if (*str == '1') { + abcd_bits |= mask; + } else if (*str != '0') { + stream->write_function(stream, "-ERR Invalid CAS bits '%s'. CAS ABCD string must be composed of only four 1's and 0's (e.g. 1101)\n", write_bits_str); + goto end; + } + str++; + mask = (mask >> 1); + } + } else { + print_usage(stream, cli); + goto end; + } + + ftdm_span_find_by_name(argv[2], &span); + if (!span) { + stream->write_function(stream, "-ERR failed to find span %s\n", argv[2]); + goto end; + } + + if (chan_id) { + if (chan_id > ftdm_span_get_chan_count(span)) { + stream->write_function(stream, "-ERR invalid channel\n"); + goto end; + } + chan = ftdm_span_get_channel(span, chan_id); + if (do_read) { + ftdm_channel_command(chan, FTDM_COMMAND_GET_CAS_BITS, &abcd_bits); + stream->write_function(stream, "Read CAS bits from channel %d: %d%d%d%d (0x0%X)\n", chan_id, CASINTS(abcd_bits), abcd_bits); + } else { + stream->write_function(stream, "Writing 0x0%X to channel %d\n", abcd_bits, chan_id); + } + } else { + iter = ftdm_span_get_chan_iterator(span, NULL); + for (curr = iter; curr; curr = ftdm_iterator_next(curr)) { + chan = ftdm_iterator_current(curr); + //ftdm_channel_command(); + chan_id = ftdm_channel_get_id(chan); + if (do_read) { + ftdm_channel_command(chan, FTDM_COMMAND_GET_CAS_BITS, &abcd_bits); + stream->write_function(stream, "Read CAS bits from channel %d: %d%d%d%d (0x0%X)\n", chan_id, CASINTS(abcd_bits), abcd_bits); + } else { + stream->write_function(stream, "Writing 0x0%X to channel %d\n", abcd_bits, chan_id); + } + } + ftdm_iterator_free(iter); + } + stream->write_function(stream, "+OK\n"); +end: + return SWITCH_STATUS_SUCCESS; +} + SWITCH_STANDARD_API(ftdm_api_exec_usage) { char *mycmd = NULL, *argv[10] = { 0 }; @@ -5323,6 +5415,7 @@ static ftdm_cli_entry_t ftdm_cli_options[] = { "queuesize", " []", "", NULL, ftdm_cmd_queuesize, NULL }, { "iostats", "enable|disable|flush|print ", "::[enable:disable:flush:print", NULL, ftdm_cmd_iostats, NULL }, { "ioread", " [num_times] [interval]", "", NULL, ftdm_cmd_ioread, NULL }, + { "cas", "read|write [] []", "::[read:write", NULL, ftdm_cmd_cas, NULL }, /* Stand-alone commands (not part of the generic ftdm API */ { "ftdm_usage", " ", "", "Return channel call count", NULL, ftdm_api_exec_usage }, From 61101e325f93259da0369e60f6857cfb64c3ca38 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Sun, 20 Jul 2014 21:51:32 -0400 Subject: [PATCH 2/6] freetdm: ftmod_analog_em: Added support for suspending channels that are offhook --- .../ftmod/ftmod_analog_em/ftdm_analog_em.h | 6 +- .../ftmod/ftmod_analog_em/ftmod_analog_em.c | 60 ++++++++++++++----- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ftdm_analog_em.h b/libs/freetdm/src/ftmod/ftmod_analog_em/ftdm_analog_em.h index 121381d522..e52a319155 100644 --- a/libs/freetdm/src/ftmod/ftmod_analog_em/ftdm_analog_em.h +++ b/libs/freetdm/src/ftmod/ftmod_analog_em/ftdm_analog_em.h @@ -44,10 +44,12 @@ #define MAX_DIALSTRING 256 typedef enum { - FTDM_ANALOG_EM_RUNNING = (1 << 0) + FTDM_ANALOG_EM_RUNNING = (1 << 0), + FTDM_ANALOG_EM_LOCAL_WRITE = (1 << 2), + FTDM_ANALOG_EM_LOCAL_SUSPEND = (1 << 3), + FTDM_ANALOG_EM_REMOTE_SUSPEND = (1 << 4), } ftdm_analog_em_flag_t; - struct ftdm_analog_data { uint32_t flags; uint32_t max_dialstr; 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 8a537bb5e6..146885f271 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 @@ -178,8 +178,7 @@ static ftdm_status_t ftdm_analog_em_sig_write(ftdm_channel_t *ftdmchan, void *da ftdm_analog_em_data_t *analog_data = ftdmchan->span->signal_data; if (ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA && analog_data->immediate_ringback - && ftdmchan->call_data) { - /* DO NOT USE ftdmchan->call_data, as is a dummy non-null pointer */ + && ftdm_test_sflag(ftdmchan, FTDM_ANALOG_EM_LOCAL_WRITE)) { /* ringback is being played in the analog thread, ignore user data for now */ return FTDM_BREAK; } @@ -283,7 +282,7 @@ static FIO_SPAN_GET_SIG_STATUS_FUNCTION(analog_em_get_span_sig_status) return FTDM_SUCCESS; } -static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(analog_em_set_channel_sig_status) +static ftdm_status_t analog_em_set_channel_sig_status_ex(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status, ftdm_bool_t remote) { switch (status) { case FTDM_SIG_STATE_DOWN: @@ -299,17 +298,30 @@ static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(analog_em_set_channel_sig_status) } ftdm_analog_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_SUSPENDED); } + if (remote) { + ftdm_set_sflag(ftdmchan, FTDM_ANALOG_EM_REMOTE_SUSPEND); + } else { + ftdm_set_sflag(ftdmchan, FTDM_ANALOG_EM_LOCAL_SUSPEND); + } break; case FTDM_SIG_STATE_UP: if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) { - int cas_bits = 0x00; - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED); - ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_CAS_BITS, &cas_bits); - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK)) { - ftdm_channel_command(ftdmchan, FTDM_COMMAND_ONHOOK, NULL); + if (remote) { + ftdm_clear_sflag(ftdmchan, FTDM_ANALOG_EM_REMOTE_SUSPEND); + } else { + ftdm_clear_sflag(ftdmchan, FTDM_ANALOG_EM_LOCAL_SUSPEND); } - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) { - ftdm_analog_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP); + if (!ftdm_test_sflag(ftdmchan, FTDM_ANALOG_EM_REMOTE_SUSPEND) && + !ftdm_test_sflag(ftdmchan, FTDM_ANALOG_EM_LOCAL_SUSPEND)) { + int cas_bits = 0x00; + ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED); + ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_CAS_BITS, &cas_bits); + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK)) { + ftdm_channel_command(ftdmchan, FTDM_COMMAND_ONHOOK, NULL); + } + if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) { + ftdm_analog_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP); + } } } break; @@ -320,6 +332,11 @@ static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(analog_em_set_channel_sig_status) return FTDM_SUCCESS; } +static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(analog_em_set_channel_sig_status) +{ + return analog_em_set_channel_sig_status_ex(ftdmchan, status, FTDM_FALSE); +} + static FIO_SPAN_SET_SIG_STATUS_FUNCTION(analog_em_set_span_sig_status) { ftdm_iterator_t *chaniter = NULL; @@ -335,7 +352,7 @@ static FIO_SPAN_SET_SIG_STATUS_FUNCTION(analog_em_set_span_sig_status) ftdm_channel_t *fchan = ftdm_iterator_current(citer); /* we set channel's state through analog_em_set_channel_sig_status(), since it already takes care of notifying the user when appropriate */ ftdm_channel_lock(fchan); - if ((analog_em_set_channel_sig_status(fchan, status)) != FTDM_SUCCESS) { + if ((analog_em_set_channel_sig_status_ex(fchan, status, FTDM_FALSE)) != FTDM_SUCCESS) { ftdm_log_chan(fchan, FTDM_LOG_ERROR, "Failed to set signaling status to %s\n", ftdm_signaling_status2str(status)); } ftdm_channel_unlock(fchan); @@ -496,6 +513,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj) uint32_t cas_hangup = 0; int cas_answer_ms = 500; int cas_hangup_ms = 500; + ftdm_bool_t busy_timeout = FTDM_FALSE; FILE *ringback_f = NULL; ftdm_bool_t digits_sent = FTDM_FALSE; @@ -762,6 +780,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj) indicate = 1; } else { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + busy_timeout = FTDM_TRUE; } } break; @@ -925,17 +944,25 @@ read_try: } } - /* we must lock the channel and make sure we let our own generated audio thru (ftdmchan->call_data is tested in the ftdm_analog_em_sig_write handler)*/ + /* we must lock the channel and make sure we let our own generated audio thru (FTDM_ANALOG_EM_LOCAL_WRITE is tested in the ftdm_analog_em_sig_write handler)*/ ftdm_channel_lock(ftdmchan); - ftdmchan->call_data = (void *)0xFF; /* ugh! */ + ftdm_set_sflag(ftdmchan, FTDM_ANALOG_EM_LOCAL_WRITE); ftdm_channel_write(ftdmchan, frame, sizeof(frame), &rlen); - ftdmchan->call_data = NULL; + ftdm_clear_sflag(ftdmchan, FTDM_ANALOG_EM_LOCAL_WRITE); ftdm_channel_unlock(ftdmchan); } done: ftdm_channel_command(ftdmchan, FTDM_COMMAND_ONHOOK, NULL); + if (busy_timeout) { + ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_CAS_BITS, &cas_bits); + if (cas_bits == 0XF) { + /* the remote end never sent any digits, neither moved to onhook, let's stay suspended */ + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Moving channel to suspended after timeout, remote end still offhook\n"); + analog_em_set_channel_sig_status_ex(ftdmchan, FTDM_SIG_STATE_SUSPENDED, FTDM_TRUE); + } + } closed_chan = ftdmchan; ftdm_channel_close(&ftdmchan); @@ -984,6 +1011,11 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e ftdm_mutex_lock(event->channel->mutex); locked++; + if (event->enum_id == FTDM_OOB_ONHOOK && ftdm_test_sflag(event->channel, FTDM_ANALOG_EM_REMOTE_SUSPEND)) { + /* We've got remote suspend, now we're back on hook, lift the remote suspend status */ + analog_em_set_channel_sig_status_ex(event->channel, FTDM_SIG_STATE_UP, FTDM_TRUE); + } + if (ftdm_test_flag(event->channel, FTDM_CHANNEL_SUSPENDED)) { ftdm_log(FTDM_LOG_WARNING, "Ignoring event %s on channel %d:%d in state %s, channel is suspended\n", ftdm_oob_event2str(event->enum_id), event->channel->span_id, event->channel->chan_id, ftdm_channel_state2str(event->channel->state)); From 09198ee3572f4c99d07eed5512dec2ebfd6f2104 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 22 Jul 2014 23:44:17 -0400 Subject: [PATCH 3/6] freetdm: Raise some buffer limits --- libs/freetdm/src/ftmod/ftmod_analog/ftdm_analog.h | 2 +- libs/freetdm/src/include/freetdm.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftdm_analog.h b/libs/freetdm/src/ftmod/ftmod_analog/ftdm_analog.h index 9a4046bf3d..b42d72bcfd 100644 --- a/libs/freetdm/src/ftmod/ftmod_analog/ftdm_analog.h +++ b/libs/freetdm/src/ftmod/ftmod_analog/ftdm_analog.h @@ -43,7 +43,7 @@ typedef enum { FTDM_ANALOG_POLARITY_CALLERID = (1 << 4) } ftdm_analog_flag_t; -#define FTDM_MAX_HOTLINE_STR 20 +#define FTDM_MAX_HOTLINE_STR 32 #define MAX_DTMF 256 struct ftdm_analog_data { diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 1aa337b943..2b29d4f396 100755 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -74,10 +74,10 @@ extern "C" { #endif /*! \brief Limit to span names */ -#define FTDM_MAX_NAME_STR_SZ 80 +#define FTDM_MAX_NAME_STR_SZ 128 /*! \brief Limit to channel number strings */ -#define FTDM_MAX_NUMBER_STR_SZ 20 +#define FTDM_MAX_NUMBER_STR_SZ 32 /*! \brief Hangup cause codes */ typedef enum { @@ -343,7 +343,7 @@ typedef enum { FTDM_STR2ENUM_P(ftdm_str2ftdm_transfer_response, ftdm_transfer_response2str, ftdm_transfer_response_t) /*! \brief Digit limit used in DNIS/ANI */ -#define FTDM_DIGITS_LIMIT 25 +#define FTDM_DIGITS_LIMIT 64 #define FTDM_SILENCE_VALUE(fchan) (fchan)->native_codec == FTDM_CODEC_ULAW ? 255 : (fchan)->native_codec == FTDM_CODEC_ALAW ? 0xD5 : 0x00 From b80cdd45d5e3a255871074e4b1acff8f61a13262 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Wed, 23 Jul 2014 00:40:27 -0400 Subject: [PATCH 4/6] freetdm: Added release guard time configuration Currently only enabled in the analog e&m module but any signaling module can easily take advantage of it with a small modification to the signaling module to set span->sig_release_guard_time_ms --- libs/freetdm/mod_freetdm/mod_freetdm.c | 12 ++++++++++-- libs/freetdm/src/ftdm_io.c | 14 ++++++++++++++ .../src/ftmod/ftmod_analog_em/ftmod_analog_em.c | 7 +++++++ libs/freetdm/src/include/private/ftdm_core.h | 2 ++ 4 files changed, 33 insertions(+), 2 deletions(-) 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; From d65716d83ad3546bde2b459d75a7f23a8dba4025 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Sun, 27 Jul 2014 13:29:58 -0400 Subject: [PATCH 5/6] freetdm: Added dtmf_time_on and dtmf_time_off parameters to tweak DTMF duration in milliseconds --- libs/freetdm/src/ftdm_io.c | 18 ++++++++++++++++-- libs/freetdm/src/include/freetdm.h | 2 ++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index ec6c2fb757..099035409f 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -3457,7 +3457,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co ftdmchan->dtmf_on = val; GOTO_STATUS(done, FTDM_SUCCESS); } else { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "invalid value %d range 10-1000", val); + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "invalid value %d range 10-1000", val); GOTO_STATUS(done, FTDM_FAIL); } } @@ -3471,7 +3471,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co ftdmchan->dtmf_off = val; GOTO_STATUS(done, FTDM_SUCCESS); } else { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "invalid value %d range 10-1000", val); + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "invalid value %d range 10-1000", val); GOTO_STATUS(done, FTDM_FAIL); } } @@ -5108,6 +5108,12 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span_channels(ftdm_span_t *span, const if (chan_config->dtmf_on_start) { span->channels[chan_index]->dtmfdetect.trigger_on_start = 1; } + if (chan_config->dtmf_time_on) { + ftdm_channel_command(span->channels[chan_index], FTDM_COMMAND_SET_DTMF_ON_PERIOD, &chan_config->dtmf_time_on); + } + if (chan_config->dtmf_time_off) { + ftdm_channel_command(span->channels[chan_index], FTDM_COMMAND_SET_DTMF_OFF_PERIOD, &chan_config->dtmf_time_off); + } } return FTDM_SUCCESS; @@ -5347,6 +5353,14 @@ static ftdm_status_t load_config(void) chan_config.dtmf_on_start = FTDM_FALSE; } } + } else if (!strcasecmp(var, "dtmf_time_on")) { + if (sscanf(val, "%u", &(chan_config.dtmf_time_on)) != 1) { + ftdm_log(FTDM_LOG_ERROR, "invalid dtmf_time_on: '%s'\n", val); + } + } else if (!strcasecmp(var, "dtmf_time_off")) { + if (sscanf(val, "%u", &(chan_config.dtmf_time_off)) != 1) { + ftdm_log(FTDM_LOG_ERROR, "invalid dtmf_time_off: '%s'\n", val); + } } else if (!strncasecmp(var, "iostats", sizeof("iostats")-1)) { if (ftdm_true(val)) { chan_config.iostats = FTDM_TRUE; diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 2b29d4f396..443afc7fd0 100755 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -521,6 +521,8 @@ typedef struct ftdm_channel_config { uint8_t debugdtmf; uint8_t dtmf_on_start; uint32_t dtmfdetect_ms; + uint32_t dtmf_time_on; + uint32_t dtmf_time_off; uint8_t iostats; } ftdm_channel_config_t; From 6b8d5b2b100946e2a23eacacbd88ae595097697d Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Sun, 9 Nov 2014 00:41:59 -0800 Subject: [PATCH 6/6] freetdm: Fix release guard timer check --- libs/freetdm/src/ftdm_io.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 099035409f..cbc04eb894 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -1492,12 +1492,13 @@ static __inline__ int chan_is_avail(ftdm_channel_t *check) } /* 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()); + ftdm_time_t time_diff = (ftdm_current_time_in_ms() - check->last_release_time); if (time_diff < check->span->sig_release_guard_time_ms) { return 0; } /* circuit now available for outbound dialing */ check->last_release_time = 0; + ftdm_log_chan(check, FTDM_LOG_DEBUG, "Channel is now available, release guard timer expired %zdms ago\n", (time_diff - check->span->sig_release_guard_time_ms)); } return 1; }