mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-08-13 17:38:59 +00:00
Merge remote-tracking branch 'moystash/em-suspend-support'
Conflicts: libs/freetdm/src/include/private/ftdm_core.h
This commit is contained in:
@@ -1489,6 +1489,16 @@ 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 = (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;
|
||||
}
|
||||
|
||||
@@ -2981,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;
|
||||
}
|
||||
@@ -3442,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);
|
||||
}
|
||||
}
|
||||
@@ -3456,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);
|
||||
}
|
||||
}
|
||||
@@ -5096,6 +5111,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;
|
||||
@@ -5335,6 +5356,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;
|
||||
|
@@ -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 {
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
@@ -361,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;
|
||||
@@ -412,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;
|
||||
@@ -443,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;
|
||||
@@ -496,6 +520,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 +787,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 +951,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 +1018,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));
|
||||
|
@@ -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 {
|
||||
@@ -355,7 +355,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
|
||||
|
||||
@@ -533,6 +533,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;
|
||||
|
||||
|
@@ -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 {
|
||||
@@ -515,6 +516,7 @@ struct ftdm_span {
|
||||
ftdm_channel_sig_write_t sig_write;
|
||||
ftdm_channel_sig_dtmf_t sig_queue_dtmf;
|
||||
ftdm_channel_sig_dtmf_t sig_send_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;
|
||||
|
Reference in New Issue
Block a user