Merge branch 'v1.2.stable' of ssh://git.freeswitch.org:222/freeswitch into v1.2.stable

This commit is contained in:
Michael S Collins 2012-12-28 16:17:59 -08:00
commit e04eab7902
5 changed files with 112 additions and 18 deletions

View File

@ -3775,11 +3775,14 @@ static switch_status_t load_config(void)
const char *dialplan = "XML";
const char *tonegroup = NULL;
char *digit_timeout = NULL;
char *dial_timeout = NULL;
char *max_digits = NULL;
char *dial_regex = NULL;
char *hold_music = NULL;
char *fail_dial_regex = NULL;
uint32_t span_id = 0, to = 0, max = 0;
char str_false[] = "false";
char *answer_supervision = str_false;
uint32_t span_id = 0, to = 0, max = 0, dial_timeout_int = 0;
ftdm_span_t *span = NULL;
analog_option_t analog_options = ANALOG_OPTION_NONE;
@ -3791,6 +3794,8 @@ static switch_status_t load_config(void)
tonegroup = val;
} else if (!strcasecmp(var, "digit_timeout") || !strcasecmp(var, "digit-timeout")) {
digit_timeout = val;
} else if (!strcasecmp(var, "dial-timeout")) {
dial_timeout = val;
} else if (!strcasecmp(var, "context")) {
context = val;
} else if (!strcasecmp(var, "dialplan")) {
@ -3803,6 +3808,8 @@ static switch_status_t load_config(void)
hold_music = val;
} else if (!strcasecmp(var, "max_digits") || !strcasecmp(var, "max-digits")) {
max_digits = val;
} else if (!strcasecmp(var, "answer-supervision")) {
answer_supervision = val;
} else if (!strcasecmp(var, "enable-analog-option")) {
analog_options = enable_analog_option(val, analog_options);
}
@ -3821,6 +3828,10 @@ static switch_status_t load_config(void)
to = atoi(digit_timeout);
}
if (dial_timeout) {
dial_timeout_int = atoi(dial_timeout);
}
if (max_digits) {
max = atoi(max_digits);
}
@ -3851,7 +3862,9 @@ static switch_status_t load_config(void)
if (ftdm_configure_span(span, "analog_em", on_analog_signal,
"tonemap", tonegroup,
"answer_supervision", answer_supervision,
"digit_timeout", &to,
"dial_timeout", &dial_timeout_int,
"max_dialstr", &max,
FTDM_TAG_END) != FTDM_SUCCESS) {
LOAD_ERROR("Error starting FreeTDM span %d\n", span_id);

View File

@ -51,6 +51,8 @@ struct ftdm_analog_data {
uint32_t flags;
uint32_t max_dialstr;
uint32_t digit_timeout;
uint32_t dial_timeout;
ftdm_bool_t answer_supervision;
};
static void *ftdm_analog_em_run(ftdm_thread_t *me, void *obj);

View File

@ -120,8 +120,10 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_em_configure_span)
{
ftdm_analog_em_data_t *analog_data;
const char *tonemap = "us";
uint32_t digit_timeout = 10;
uint32_t digit_timeout = 2000;
uint32_t max_dialstr = 11;
uint32_t dial_timeout = 0;
ftdm_bool_t answer_supervision = FTDM_FALSE;
const char *var, *val;
int *intval;
@ -137,11 +139,22 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_em_configure_span)
memset(analog_data, 0, sizeof(*analog_data));
while((var = va_arg(ap, char *))) {
ftdm_log(FTDM_LOG_DEBUG, "Parsing analog em parameter '%s'\n", var);
if (!strcasecmp(var, "tonemap")) {
if (!(val = va_arg(ap, char *))) {
break;
}
tonemap = val;
} else if (!strcasecmp(var, "answer_supervision")) {
if (!(val = va_arg(ap, char *))) {
break;
}
answer_supervision = ftdm_true(val);
} else if (!strcasecmp(var, "dial_timeout")) {
if (!(intval = va_arg(ap, int *))) {
break;
}
dial_timeout = *intval;
} else if (!strcasecmp(var, "digit_timeout")) {
if (!(intval = va_arg(ap, int *))) {
break;
@ -153,7 +166,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_em_configure_span)
}
max_dialstr = *intval;
} else {
snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var);
ftdm_log(FTDM_LOG_ERROR, "Invalid parameter for analog em span: '%s'\n", var);
return FTDM_FAIL;
}
}
@ -171,6 +184,8 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_em_configure_span)
span->start = ftdm_analog_em_start;
analog_data->digit_timeout = digit_timeout;
analog_data->max_dialstr = max_dialstr;
analog_data->dial_timeout = dial_timeout;
analog_data->answer_supervision = answer_supervision;
span->signal_cb = sig_cb;
span->signal_type = FTDM_SIGTYPE_ANALOG;
span->signal_data = analog_data;
@ -221,6 +236,10 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
ftdm_channel_t *closed_chan;
uint32_t state_counter = 0, elapsed = 0, collecting = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = 30000;
ftdm_sigmsg_t sig;
int cas_bits = 0;
uint32_t cas_answer = 0;
int cas_answer_ms = 500;
ftdm_bool_t digits_sent = FTDM_FALSE;
ftdm_log(FTDM_LOG_DEBUG, "ANALOG EM CHANNEL thread starting.\n");
@ -259,13 +278,12 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
sig.channel = ftdmchan;
assert(interval != 0);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "IO Interval: %u\n", interval);
while (ftdm_running() && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INTHREAD)) {
ftdm_wait_flag_t flags = FTDM_READ;
ftdm_size_t dlen = 0;
len = sizeof(frame);
elapsed += interval;
state_counter += interval;
@ -274,7 +292,8 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
case FTDM_CHANNEL_STATE_DIALING:
{
if (! ftdmchan->needed_tones[FTDM_TONEMAP_RING]
&& ftdm_test_flag(ftdmchan, FTDM_CHANNEL_WINK)) {
&& ftdm_test_flag(ftdmchan, FTDM_CHANNEL_WINK)
&& !digits_sent) {
if (ftdm_strlen_zero(ftdmchan->caller_data.dnis.digits)) {
ftdm_log(FTDM_LOG_ERROR, "No Digits to send!\n");
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
@ -284,12 +303,18 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
} else {
state_counter = 0;
digits_sent = FTDM_TRUE;
ftdmchan->needed_tones[FTDM_TONEMAP_RING] = 1;
ftdmchan->needed_tones[FTDM_TONEMAP_BUSY] = 1;
ftdmchan->needed_tones[FTDM_TONEMAP_FAIL1] = 1;
ftdmchan->needed_tones[FTDM_TONEMAP_FAIL2] = 1;
ftdmchan->needed_tones[FTDM_TONEMAP_FAIL3] = 1;
dial_timeout = ((ftdmchan->dtmf_on + ftdmchan->dtmf_off) * strlen(ftdmchan->caller_data.dnis.digits)) + 2000;
if (analog_data->dial_timeout) {
dial_timeout += analog_data->dial_timeout;
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Outbound dialing timeout: %dms\n", dial_timeout);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Outbound CAS answer timeout: %dms\n", cas_answer_ms);
}
}
break;
@ -297,10 +322,25 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
if (state_counter > dial_timeout) {
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_WINK)) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
} else {
} else if (!analog_data->answer_supervision) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
}
}
cas_bits = 0;
ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_CAS_BITS, &cas_bits);
if (!(state_counter % 1000)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "CAS bits: 0x%X\n", cas_bits);
}
if (cas_bits == 0xF) {
cas_answer += interval;
if (cas_answer >= cas_answer_ms) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Answering on CAS answer signal persistence!\n");
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
}
} else if (cas_answer) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Resetting cas answer to 0: 0x%X!\n", cas_bits);
cas_answer = 0;
}
}
break;
case FTDM_CHANNEL_STATE_DIALTONE:
@ -488,11 +528,17 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
continue;
}
len = sizeof(frame);
if (ftdm_channel_read(ftdmchan, frame, &len) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "READ ERROR [%s]\n", ftdmchan->last_error);
goto done;
}
if (0 == len) {
ftdm_log(FTDM_LOG_DEBUG, "Nothing read\n");
continue;
}
if (ftdmchan->detected_tones[0]) {
int i;
@ -511,7 +557,11 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
ftdm_log(FTDM_LOG_ERROR, "Failure indication detected!\n");
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
} else if (ftdmchan->detected_tones[FTDM_TONEMAP_RING]) {
if (!analog_data->answer_supervision) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ringing, but not answering since answer supervision is enabled\n");
}
}
ftdm_channel_clear_detected_tones(ftdmchan);
@ -613,7 +663,9 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
case FTDM_OOB_OFFHOOK:
{
if (ftdm_test_flag(event->channel, FTDM_CHANNEL_INTHREAD)) {
if (event->channel->state < FTDM_CHANNEL_STATE_UP) {
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_UP);
}
} else {
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_DIALTONE);
ftdm_mutex_unlock(event->channel->mutex);

View File

@ -1098,6 +1098,7 @@ static __inline__ int handle_dtmf_event(ftdm_channel_t *fchan, zt_event_t zt_eve
*/
static __inline__ ftdm_status_t zt_channel_process_event(ftdm_channel_t *fchan, ftdm_oob_event_t *event_id, zt_event_t zt_event_id)
{
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Processing zap hardware event %d\n", zt_event_id);
switch(zt_event_id) {
case ZT_EVENT_RINGEROFF:
{
@ -1132,16 +1133,30 @@ static __inline__ ftdm_status_t zt_channel_process_event(ftdm_channel_t *fchan,
break;
case ZT_EVENT_RINGOFFHOOK:
{
*event_id = FTDM_OOB_NOOP;
if (fchan->type == FTDM_CHAN_TYPE_FXS || (fchan->type == FTDM_CHAN_TYPE_EM && fchan->state != FTDM_CHANNEL_STATE_UP)) {
if (fchan->type != FTDM_CHAN_TYPE_EM) {
/* In E&M we're supposed to set this flag when the tx side goes offhook, not the rx */
/* In E&M we're supposed to set this flag only when the local side goes offhook, not the remote */
ftdm_set_flag_locked(fchan, FTDM_CHANNEL_OFFHOOK);
}
/* For E&M let's count the ring count (it seems sometimes we receive RINGOFFHOOK once before the other end
* answers, then another RINGOFFHOOK when the other end answers?? anyways, now we count rings before delivering the
* offhook event ... the E&M signaling code in ftmod_analog_em also polls the RBS bits looking for answer, just to
* be safe and not rely on this event, so even if this event does not arrive, when there is answer supervision
* the analog signaling code should detect the cas persistance pattern and answer */
if (fchan->type == FTDM_CHAN_TYPE_EM && ftdm_test_flag(fchan, FTDM_CHANNEL_OUTBOUND)) {
fchan->ring_count++;
/* perhaps some day we'll make this configurable, but since I am not even sure what the hell is going on
* no point in making a configuration option for something that may not be technically correct */
if (fchan->ring_count == 2) {
*event_id = FTDM_OOB_OFFHOOK;
}
} else {
*event_id = FTDM_OOB_OFFHOOK;
}
} else if (fchan->type == FTDM_CHAN_TYPE_FXO) {
*event_id = FTDM_OOB_RING_START;
} else {
*event_id = FTDM_OOB_NOOP;
}
}
break;
@ -1309,8 +1324,20 @@ static FIO_READ_FUNCTION(zt_read)
else {
if (errno == EAGAIN || errno == EINTR)
continue;
if (errno == ELAST)
if (errno == ELAST) {
zt_event_t zt_event_id = 0;
if (ioctl(ftdmchan->sockfd, codes.GETEVENT, &zt_event_id) == -1) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed retrieving event after ELAST on read: %s\n", strerror(errno));
r = -1;
break;
}
if (handle_dtmf_event(ftdmchan, zt_event_id)) {
/* we should enqueue this event somewhere so it can be retrieved by the user, for now, dropping it to see what it is! */
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dropping event %d to be able to read data\n", zt_event_id);
}
continue;
}
ftdm_log(FTDM_LOG_ERROR, "read failed: %s\n", strerror(errno));
}

View File

@ -92,7 +92,7 @@
!strcasecmp(expr, "true") || \
!strcasecmp(expr, "enabled") || \
!strcasecmp(expr, "active") || \
atoi(expr))) ? 1 : 0
atoi(expr))) ? FTDM_TRUE : FTDM_FALSE
#ifdef WIN32_LEAN_AND_MEAN
#include <winsock2.h>