Merge branch 'master' into FS-4558
This commit is contained in:
commit
3e26caf8ff
|
@ -585,6 +585,9 @@ libs/openzap/Makefile:
|
|||
cd libs/openzap && autoconf
|
||||
cd libs/openzap && ./configure
|
||||
|
||||
version:
|
||||
git log -1 | head -3
|
||||
|
||||
reinstall: modwipe uninstall install
|
||||
|
||||
update-clean: clean libs/openzap/Makefile python-reconf
|
||||
|
@ -692,7 +695,7 @@ modclean: $(switch_builddir)/modules.conf
|
|||
@cd src/mod && $(MAKE) $(AM_MAKEFLAGS) clean
|
||||
|
||||
modwipe:
|
||||
rm -f $(modulesdir)/*.${DYNAMIC_LIB_EXTEN}
|
||||
rm -f $(modulesdir)/*.${DYNAMIC_LIB_EXTEN} $(modulesdir)/*.la
|
||||
|
||||
dox:
|
||||
cd docs && doxygen $(PWD)/docs/Doxygen.conf
|
||||
|
|
|
@ -382,6 +382,7 @@
|
|||
<prompt phrase="Please enter the phone number." filename="ivr-please_enter_the_phone_number.wav"/>
|
||||
<prompt phrase="Please state your name and the reason for your call." filename="ivr-please_state_your_name_and_reason_for_calling.wav"/>
|
||||
<prompt phrase="To accept, press 1. To reject, press 2. To send to voicemail, press 3." filename="ivr-accept_reject_voicemail.wav"/>
|
||||
<prompt phrase="To accept, press 1. To reject, press 2." filename="ivr-accept_reject.wav"/>
|
||||
<prompt phrase="To accept, press 1." filename="ivr-to_accept_press_one.wav"/>
|
||||
<prompt phrase="Incoming call." filename="ivr-incoming_call.wav"/>
|
||||
<prompt phrase="Thank you for calling." filename="ivr-thank_you_for_calling.wav"/>
|
||||
|
@ -566,7 +567,6 @@
|
|||
<prompt phrase="...the short greeting." filename="ivr-short_greeting.wav"/>
|
||||
<prompt phrase="...the invalid sound prompt." filename="ivr-ivalid_sound_prompt.wav"/>
|
||||
<prompt phrase="...the exit sound prompt." filename="ivr-exit_sound_prompt.wav"/>
|
||||
<!-- The following phrases still need to be recorded -->
|
||||
<prompt phrase="That person does not accept anonymous calls." filename="ivr-not_accept_anonymous_calls.wav"/>
|
||||
<prompt phrase="To accept, press..." filename="ivr-to_accept_press.wav"/>
|
||||
<prompt phrase="To reject..." filename="ivr-to_reject.wav"/>
|
||||
|
@ -583,18 +583,13 @@
|
|||
<prompt phrase="To send a fax, press..." filename="ivr-send_fax.wav"/>
|
||||
<prompt phrase="Please enter the number to which I should send this fax, then press pound." filename="ivr-enter_number_send_fax.wav"/>
|
||||
<prompt phrase="Send your fax now." filename="ivr-send_fax_now.wav"/>
|
||||
<prompt phrase="To learn more about FreeSWITCH Solutions, press..." filename="misc-learn_more_about_freeswitch_solutions.wav"/>
|
||||
<prompt phrase="For information about FreeSWITCH, press..." filename="misc-information_about_freeswitch.wav"/>
|
||||
<prompt phrase="For other options, press..." filename="ivr-for_other_options.wav"/>
|
||||
<prompt phrase="FreeSWITCH is a state of the art telecommunications platform." filename="misc-freeswitch_is_state_of_the_art.wav"/>
|
||||
<prompt phrase="It is stable, highly scalable, and extensible." filename="misc-it_is_stable_scalable_extensible.wav"/>
|
||||
<prompt phrase="Best of all, it is free for anyone to download and use." filename="misc-free_to_download.wav"/>
|
||||
<prompt phrase="Visit www dot freeswitch dot org to learn more about our project and worldwide community." filename="misc-freeswitch_dot_org_more.wav"/>
|
||||
<prompt phrase="...has been added to the blacklist." filename="ivr-has_been_added_to_the_blacklist.wav"/>
|
||||
<prompt phrase="...has been removed from the blacklist." filename="ivr-has_been_removed_from_blacklist.wav"/>
|
||||
<prompt phrase="Please enter the number to be added to the blacklist." filename="ivr-enter_number_to_add_to_blacklist.wav"/>
|
||||
<prompt phrase="...is not on the blacklist." filename="ivr-is_not_on_the_blacklist.wav"/>
|
||||
<prompt phrase="...is already on the blacklist." filename="ivr-is_already_on_the_blacklist.wav"/>
|
||||
<prompt phrase="For other options, press..." filename="ivr-for_other_options.wav"/>
|
||||
<!-- The following phrases still need to be recorded -->
|
||||
<prompt phrase="" filename=""/>
|
||||
<prompt phrase="" filename=""/>
|
||||
|
||||
|
@ -622,6 +617,12 @@
|
|||
<prompt phrase="Everyone is koo koo for CudaTel!" filename="misc-koo_koo_for_cudatel.wav"/>
|
||||
<prompt phrase="I'm pretty sure CudaTel's patented Automagicatronical configuration takes care of it." filename="misc-cudatel_automagicatronical.wav"/>
|
||||
<prompt phrase="Thank you for calling the CudaTel test system." filename="misc-cudatel_test_system.wav"/>
|
||||
<prompt phrase="To learn more about FreeSWITCH Solutions, press..." filename="misc-learn_more_about_freeswitch_solutions.wav"/>
|
||||
<prompt phrase="For information about FreeSWITCH, press..." filename="misc-information_about_freeswitch.wav"/>
|
||||
<prompt phrase="FreeSWITCH is a state of the art telecommunications platform." filename="misc-freeswitch_is_state_of_the_art.wav"/>
|
||||
<prompt phrase="It is stable, highly scalable, and extensible." filename="misc-it_is_stable_scalable_extensible.wav"/>
|
||||
<prompt phrase="Best of all, it is free for anyone to download and use." filename="misc-free_to_download.wav"/>
|
||||
<prompt phrase="Visit www dot freeswitch dot org to learn more about our project and worldwide community." filename="misc-freeswitch_dot_org_more.wav"/>
|
||||
</misc>
|
||||
<zrtp>
|
||||
<!-- base256 prompts for SAS -->
|
||||
|
|
|
@ -39,6 +39,8 @@ static ftdm_status_t ftdm_libpri_start(ftdm_span_t *span);
|
|||
static ftdm_io_interface_t ftdm_libpri_interface;
|
||||
|
||||
static int on_timeout_t302(struct lpwrap_pri *spri, struct lpwrap_timer *timer);
|
||||
static int on_timeout_t316(struct lpwrap_pri *spri, struct lpwrap_timer *timer);
|
||||
static int on_timeout_t3xx(struct lpwrap_pri *spri, struct lpwrap_timer *timer);
|
||||
|
||||
|
||||
static void _ftdm_channel_set_state_force(ftdm_channel_t *chan, const ftdm_channel_state_t state)
|
||||
|
@ -739,7 +741,7 @@ static ftdm_state_map_t isdn_state_map = {
|
|||
ZSD_OUTBOUND,
|
||||
ZSM_UNACCEPTABLE,
|
||||
{FTDM_CHANNEL_STATE_RESTART, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_DOWN, FTDM_END}
|
||||
{FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END}
|
||||
},
|
||||
{
|
||||
ZSD_OUTBOUND,
|
||||
|
@ -806,6 +808,12 @@ static ftdm_state_map_t isdn_state_map = {
|
|||
{FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_DOWN, FTDM_END},
|
||||
},
|
||||
{
|
||||
ZSD_OUTBOUND,
|
||||
ZSM_UNACCEPTABLE,
|
||||
{FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_DOWN, FTDM_END},
|
||||
},
|
||||
|
||||
/****************************************/
|
||||
{
|
||||
|
@ -818,7 +826,7 @@ static ftdm_state_map_t isdn_state_map = {
|
|||
ZSD_INBOUND,
|
||||
ZSM_UNACCEPTABLE,
|
||||
{FTDM_CHANNEL_STATE_RESTART, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_DOWN, FTDM_END}
|
||||
{FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END}
|
||||
},
|
||||
{
|
||||
ZSD_INBOUND,
|
||||
|
@ -894,6 +902,12 @@ static ftdm_state_map_t isdn_state_map = {
|
|||
{FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_DOWN, FTDM_END},
|
||||
},
|
||||
{
|
||||
ZSD_INBOUND,
|
||||
ZSM_UNACCEPTABLE,
|
||||
{FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_DOWN, FTDM_END},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -935,6 +949,10 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
|
|||
/* Stop T302 */
|
||||
lpwrap_stop_timer(&isdn_data->spri, &chan_priv->t302);
|
||||
|
||||
/* Stop T316 and reset counter */
|
||||
lpwrap_stop_timer(&isdn_data->spri, &chan_priv->t316);
|
||||
chan_priv->t316_timeout_cnt = 0;
|
||||
|
||||
if (ftdm_channel_close(&chtmp) != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_WARNING, "-- Failed to close channel %d:%d\n",
|
||||
ftdm_channel_get_span_id(chan),
|
||||
|
@ -1073,11 +1091,17 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
|
|||
sig.event_id = FTDM_SIGEVENT_RESTART;
|
||||
status = ftdm_span_send_signal(span, &sig);
|
||||
|
||||
if (!(chan_priv->flags & FTDM_LIBPRI_B_REMOTE_RESTART)) {
|
||||
if (ftdm_span_get_trunk_type(span) == FTDM_TRUNK_BRI_PTMP) {
|
||||
/* Just put the channel into DOWN state, libpri won't send RESTART on BRI PTMP */
|
||||
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_DOWN);
|
||||
|
||||
} else if (!(chan_priv->flags & FTDM_LIBPRI_B_REMOTE_RESTART)) {
|
||||
/* Locally triggered restart, send RESTART to remote, wait for ACK */
|
||||
pri_reset(isdn_data->spri.pri, ftdm_channel_get_id(chan));
|
||||
/* Start T316 */
|
||||
lpwrap_start_timer(&isdn_data->spri, &chan_priv->t316, isdn_data->t316_timeout_ms, &on_timeout_t316);
|
||||
} else {
|
||||
/* Remote restart complete, clear flag */
|
||||
/* Remote restart complete, clear flag (RESTART ACK already sent by libpri) */
|
||||
chan_priv->flags &= ~FTDM_LIBPRI_B_REMOTE_RESTART;
|
||||
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_DOWN);
|
||||
}
|
||||
|
@ -1865,11 +1889,67 @@ static int on_timeout_t302(struct lpwrap_pri *spri, struct lpwrap_timer *timer)
|
|||
ftdm_libpri_b_chan_t *chan_priv = ftdm_container_of(timer, ftdm_libpri_b_chan_t, t302);
|
||||
ftdm_channel_t *chan = chan_priv->channel;
|
||||
|
||||
ftdm_log(FTDM_LOG_NOTICE, "-- T302 timed out, going to state RING\n");
|
||||
ftdm_log_chan_msg(chan, FTDM_LOG_INFO, "-- T302 timed out, going to state RING\n");
|
||||
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timeout handler for T316 (RESTART ACK timer)
|
||||
*/
|
||||
static int on_timeout_t316(struct lpwrap_pri *spri, struct lpwrap_timer *timer)
|
||||
{
|
||||
ftdm_libpri_b_chan_t *chan_priv = ftdm_container_of(timer, ftdm_libpri_b_chan_t, t316);
|
||||
ftdm_libpri_data_t *isdn_data = ftdm_container_of(spri, ftdm_libpri_data_t, spri);
|
||||
ftdm_channel_t *chan = chan_priv->channel;
|
||||
|
||||
if (++chan_priv->t316_timeout_cnt > isdn_data->t316_max_attempts) {
|
||||
ftdm_log_chan(chan, FTDM_LOG_ERROR, "-- T316 timed out, channel reached restart attempt limit '%d' and is suspended\n",
|
||||
isdn_data->t316_max_attempts);
|
||||
|
||||
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_SUSPENDED);
|
||||
} else {
|
||||
ftdm_log_chan_msg(chan, FTDM_LOG_WARNING, "-- T316 timed out, resending RESTART request\n");
|
||||
pri_reset(spri->pri, ftdm_channel_get_id(chan));
|
||||
|
||||
/* Restart T316 */
|
||||
lpwrap_start_timer(spri, timer, isdn_data->t316_timeout_ms, &on_timeout_t316);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Timeout handler for T3xx (NT-mode idle restart)
|
||||
*/
|
||||
static int on_timeout_t3xx(struct lpwrap_pri *spri, struct lpwrap_timer *timer)
|
||||
{
|
||||
ftdm_span_t *span = spri->span;
|
||||
ftdm_libpri_data_t *isdn_data = span->signal_data;
|
||||
ftdm_iterator_t *iter = NULL;
|
||||
|
||||
ftdm_log_chan_msg(isdn_data->dchan, FTDM_LOG_INFO, "-- T3xx timed out, restarting idle b-channels\n");
|
||||
ftdm_mutex_lock(span->mutex);
|
||||
|
||||
/* Iterate b-channels */
|
||||
for (iter = ftdm_span_get_chan_iterator(span, NULL); iter; iter = ftdm_iterator_next(iter)) {
|
||||
ftdm_channel_t *cur = ftdm_iterator_current(iter);
|
||||
/* Skip non-b-channels */
|
||||
if (ftdm_channel_get_type(cur) != FTDM_CHAN_TYPE_B)
|
||||
continue;
|
||||
/* Restart idle b-channels */
|
||||
if (ftdm_channel_get_state(cur) == FTDM_CHANNEL_STATE_DOWN) {
|
||||
ftdm_set_state_locked(cur, FTDM_CHANNEL_STATE_RESTART);
|
||||
}
|
||||
}
|
||||
ftdm_iterator_free(iter);
|
||||
ftdm_mutex_unlock(span->mutex);
|
||||
|
||||
/* Start timer again */
|
||||
lpwrap_start_timer(spri, timer, isdn_data->idle_restart_timeout_ms, &on_timeout_t3xx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Processes freetdm event
|
||||
|
@ -2237,6 +2317,7 @@ static int on_dchan_up(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev
|
|||
if (!ftdm_test_flag(spri, LPWRAP_PRI_READY)) {
|
||||
ftdm_signaling_status_t status = FTDM_SIG_STATE_UP;
|
||||
ftdm_span_t *span = spri->span;
|
||||
ftdm_libpri_data_t *isdn_data = span->signal_data;
|
||||
ftdm_sigmsg_t sig;
|
||||
int i;
|
||||
|
||||
|
@ -2257,6 +2338,15 @@ static int on_dchan_up(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev
|
|||
sig.ev_data.sigstatus.status = status;
|
||||
ftdm_span_send_signal(span, &sig);
|
||||
}
|
||||
|
||||
/* NT-mode idle b-channel restart timer */
|
||||
if (ftdm_span_get_trunk_type(span) != FTDM_TRUNK_BRI_PTMP &&
|
||||
isdn_data->mode == PRI_NETWORK && isdn_data->idle_restart_timeout_ms > 0)
|
||||
{
|
||||
ftdm_log_chan(isdn_data->dchan, FTDM_LOG_INFO, "Starting NT-mode idle b-channel restart timer (%d ms)\n",
|
||||
isdn_data->idle_restart_timeout_ms);
|
||||
lpwrap_start_timer(&isdn_data->spri, &isdn_data->t3xx, isdn_data->idle_restart_timeout_ms, &on_timeout_t3xx);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -2273,6 +2363,7 @@ static int on_dchan_down(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_
|
|||
if (ftdm_test_flag(spri, LPWRAP_PRI_READY)) {
|
||||
ftdm_signaling_status_t status = FTDM_SIG_STATE_DOWN;
|
||||
ftdm_span_t *span = spri->span;
|
||||
ftdm_libpri_data_t *isdn_data = span->signal_data;
|
||||
ftdm_sigmsg_t sig;
|
||||
int i;
|
||||
|
||||
|
@ -2293,9 +2384,19 @@ static int on_dchan_down(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_
|
|||
sig.ev_data.sigstatus.status = status;
|
||||
|
||||
ftdm_span_send_signal(span, &sig);
|
||||
}
|
||||
}
|
||||
|
||||
if (ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_B) {
|
||||
ftdm_libpri_b_chan_t *chan_priv = chan->call_data;
|
||||
/* Stop T316 and reset counter */
|
||||
lpwrap_stop_timer(spri, &chan_priv->t316);
|
||||
chan_priv->t316_timeout_cnt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* NT-mode idle b-channel restart timer */
|
||||
ftdm_log_chan_msg(isdn_data->dchan, FTDM_LOG_INFO, "Stopping NT-mode idle b-channel restart timer\n");
|
||||
lpwrap_stop_timer(&isdn_data->spri, &isdn_data->t3xx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2646,6 +2747,53 @@ static uint32_t parse_opts(const char *in)
|
|||
return flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse timeout value with (convenience) modifier suffix
|
||||
* \param[in] in Input string, e.g. '1d' = 1 day, '7w' = 7 weeks, '3s' = 3 seconds
|
||||
* \todo Could be simplified by using strtol() instead of atoi()
|
||||
*/
|
||||
static int parse_timeout(const char *in)
|
||||
{
|
||||
const char *p_end = NULL, *p_start = in;
|
||||
int msec = 0;
|
||||
|
||||
if (ftdm_strlen_zero(in))
|
||||
return 0;
|
||||
|
||||
p_end = in + strlen(in);
|
||||
|
||||
/* skip whitespace at start */
|
||||
while (p_start != p_end && *p_start == ' ')
|
||||
p_start++;
|
||||
|
||||
/* skip whitespace at end */
|
||||
while (p_end != p_start && (*p_end == ' ' || *p_end == '\0'))
|
||||
p_end--;
|
||||
|
||||
msec = atoi(p_start);
|
||||
|
||||
switch (p_end[0]) {
|
||||
case 's': /* seconds */
|
||||
msec *= 1000;
|
||||
break;
|
||||
case 'm': /* minutes */
|
||||
if (p_end[1] != 's') msec *= 60 * 1000;
|
||||
break;
|
||||
case 'h': /* hours */
|
||||
msec *= 3600 * 1000;
|
||||
break;
|
||||
case 'd': /* days */
|
||||
msec *= 86400 * 1000;
|
||||
break;
|
||||
case 'w': /* weeks */
|
||||
msec *= 604800 * 1000;
|
||||
break;
|
||||
default: /* miliseconds */
|
||||
break;
|
||||
}
|
||||
return msec;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Initialises a libpri span from configuration variables
|
||||
* \param span Span to configure
|
||||
|
@ -2699,6 +2847,15 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
|
|||
/* set some default values */
|
||||
isdn_data->ton = PRI_UNKNOWN;
|
||||
isdn_data->overlap_timeout_ms = OVERLAP_TIMEOUT_MS_DEFAULT;
|
||||
isdn_data->idle_restart_timeout_ms = IDLE_RESTART_TIMEOUT_MS_DEFAULT;
|
||||
|
||||
/*
|
||||
* T316 restart ack timeout and retry limit
|
||||
* (ITU-T Q.931 05/98 Paragraph 5.5.1 and Table 9-1)
|
||||
*/
|
||||
isdn_data->t316_timeout_ms = T316_TIMEOUT_MS_DEFAULT;
|
||||
isdn_data->t316_max_attempts = T316_ATTEMPT_LIMIT_DEFAULT;
|
||||
|
||||
|
||||
/* Use span's trunk_mode as a reference for the default libpri mode */
|
||||
if (ftdm_span_get_trunk_mode(span) == FTDM_TRUNK_MODE_NET) {
|
||||
|
@ -2777,16 +2934,51 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
|
|||
}
|
||||
}
|
||||
else if (!strcasecmp(var, "digit_timeout") || !strcasecmp(var, "t302")) {
|
||||
int tmp = atoi(val);
|
||||
int tmp = parse_timeout(val);
|
||||
if (!tmp) {
|
||||
isdn_data->overlap_timeout_ms = 0; /* disabled */
|
||||
}
|
||||
else if ((isdn_data->overlap_timeout_ms = ftdm_clamp(tmp, OVERLAP_TIMEOUT_MS_MIN, OVERLAP_TIMEOUT_MS_MAX)) != tmp) {
|
||||
ftdm_log(FTDM_LOG_WARNING, "'%s' value '%d' outside of range [%d:%d], using '%d' ms instead\n",
|
||||
var, tmp, OVERLAP_TIMEOUT_MS_MIN, OVERLAP_TIMEOUT_MS_MAX,
|
||||
ftdm_log(FTDM_LOG_WARNING, "'%s' value %d ms ('%s') outside of range [%d:%d] ms, using %d ms instead\n",
|
||||
var, tmp, val, OVERLAP_TIMEOUT_MS_MIN, OVERLAP_TIMEOUT_MS_MAX,
|
||||
isdn_data->overlap_timeout_ms);
|
||||
}
|
||||
}
|
||||
else if (!strcasecmp(var, "idle_restart_interval")) {
|
||||
int tmp = parse_timeout(val);
|
||||
if (!tmp) {
|
||||
isdn_data->idle_restart_timeout_ms = 0; /* disabled */
|
||||
}
|
||||
else if ((isdn_data->idle_restart_timeout_ms = ftdm_clamp(tmp, IDLE_RESTART_TIMEOUT_MS_MIN, IDLE_RESTART_TIMEOUT_MS_MAX)) != tmp) {
|
||||
ftdm_log(FTDM_LOG_WARNING, "'%s' value %d ms ('%s') outside of range [%d:%d] ms, using %d ms instead\n",
|
||||
var, tmp, val, IDLE_RESTART_TIMEOUT_MS_MIN, IDLE_RESTART_TIMEOUT_MS_MAX,
|
||||
isdn_data->idle_restart_timeout_ms);
|
||||
}
|
||||
}
|
||||
else if (!strcasecmp(var, "restart_timeout") || !strcasecmp(var, "t316")) {
|
||||
int tmp = parse_timeout(val);
|
||||
if (tmp <= 0) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "'%s' value '%s' is invalid\n", var, val);
|
||||
goto error;
|
||||
}
|
||||
else if ((isdn_data->t316_timeout_ms = ftdm_clamp(tmp, T316_TIMEOUT_MS_MIN, T316_TIMEOUT_MS_MAX)) != tmp) {
|
||||
ftdm_log(FTDM_LOG_WARNING, "'%s' value %d ms ('%s') outside of range [%d:%d] ms, using %d ms instead\n",
|
||||
var, tmp, val, T316_TIMEOUT_MS_MIN, T316_TIMEOUT_MS_MAX,
|
||||
isdn_data->t316_timeout_ms);
|
||||
}
|
||||
}
|
||||
else if (!strcasecmp(var, "restart_attempts") || !strcasecmp(var, "t316_limit")) {
|
||||
int tmp = atoi(val);
|
||||
if (tmp <= 0) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "'%s' value '%s' is invalid\n", var, val);
|
||||
goto error;
|
||||
}
|
||||
else if ((isdn_data->t316_max_attempts = ftdm_clamp(tmp, T316_ATTEMPT_LIMIT_MIN, T316_ATTEMPT_LIMIT_MAX)) != tmp) {
|
||||
ftdm_log(FTDM_LOG_WARNING, "'%s' value %d ('%s') outside of range [%d:%d], using %d instead\n",
|
||||
var, tmp, val, T316_ATTEMPT_LIMIT_MIN, T316_ATTEMPT_LIMIT_MAX,
|
||||
isdn_data->t316_max_attempts);
|
||||
}
|
||||
}
|
||||
else if (!strcasecmp(var, "debug")) {
|
||||
if (parse_debug(val, &isdn_data->debug_mask) == -1) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Invalid debug flag, ignoring parameter\n");
|
||||
|
|
|
@ -35,10 +35,27 @@
|
|||
#include "freetdm.h"
|
||||
#include "lpwrap_pri.h"
|
||||
|
||||
/* T302 Overlap receiving inter-digit timeout */
|
||||
#define OVERLAP_TIMEOUT_MS_DEFAULT 5000 /* 5 sec */
|
||||
#define OVERLAP_TIMEOUT_MS_MIN 3000 /* 3 sec */
|
||||
#define OVERLAP_TIMEOUT_MS_MAX 30000 /* 30 sec */
|
||||
|
||||
/* NT-mode idle b-channel restart timer */
|
||||
#define IDLE_RESTART_TIMEOUT_MS_DEFAULT 900000 /* 15 min */
|
||||
#define IDLE_RESTART_TIMEOUT_MS_MIN 10000 /* 10 sec */
|
||||
#define IDLE_RESTART_TIMEOUT_MS_MAX 86400000 /* 1 day */
|
||||
|
||||
/* T316 RESTART ACK wait timer */
|
||||
#define T316_TIMEOUT_MS_DEFAULT 30000 /* 30 sec */
|
||||
#define T316_TIMEOUT_MS_MIN 10000 /* 10 sec */
|
||||
#define T316_TIMEOUT_MS_MAX 300000 /* 5 min */
|
||||
|
||||
/* T316 restart attempts until channel is suspended */
|
||||
#define T316_ATTEMPT_LIMIT_DEFAULT 3
|
||||
#define T316_ATTEMPT_LIMIT_MIN 1
|
||||
#define T316_ATTEMPT_LIMIT_MAX 10
|
||||
|
||||
|
||||
typedef enum {
|
||||
SERVICE_CHANGE_STATUS_INSERVICE = 0,
|
||||
SERVICE_CHANGE_STATUS_MAINTENANCE,
|
||||
|
@ -76,6 +93,9 @@ struct ftdm_libpri_data {
|
|||
int dialect;
|
||||
int overlap; /*!< Overlap dial flags */
|
||||
int overlap_timeout_ms; /*!< Overlap dial timeout */
|
||||
int idle_restart_timeout_ms; /*!< NT-mode idle b-channel restart */
|
||||
int t316_timeout_ms; /*!< T316 RESTART ACK timeout */
|
||||
int t316_max_attempts; /*!< T316 timeout limit */
|
||||
unsigned int layer1;
|
||||
unsigned int ton;
|
||||
unsigned int service_message_support;
|
||||
|
@ -85,6 +105,9 @@ struct ftdm_libpri_data {
|
|||
/* MSN filter */
|
||||
ftdm_hash_t *msn_hash;
|
||||
ftdm_mutex_t *msn_mutex;
|
||||
|
||||
/* NT-mode idle restart timer */
|
||||
struct lpwrap_timer t3xx;
|
||||
};
|
||||
|
||||
typedef struct ftdm_libpri_data ftdm_libpri_data_t;
|
||||
|
@ -103,9 +126,11 @@ enum {
|
|||
*/
|
||||
struct ftdm_libpri_b_chan {
|
||||
struct lpwrap_timer t302; /*!< T302 overlap receive timer */
|
||||
struct lpwrap_timer t316; /*!< T316 restart ack timer */
|
||||
ftdm_channel_t *channel; /*!< back-pointer to b-channel */
|
||||
q931_call *call; /*!< libpri opaque call handle */
|
||||
uint32_t flags; /*!< channel flags */
|
||||
uint32_t t316_timeout_cnt; /*!< T316 timeout counter */
|
||||
};
|
||||
|
||||
typedef struct ftdm_libpri_b_chan ftdm_libpri_b_chan_t;
|
||||
|
|
|
@ -275,15 +275,17 @@ static int lpwrap_run_expired(struct lpwrap_pri *spri, ftdm_time_t now_ms)
|
|||
|
||||
/* fire callbacks */
|
||||
while ((cur = expired_list)) {
|
||||
timeout_handler handler = cur->callback;
|
||||
expired_list = cur->next;
|
||||
if (cur->callback)
|
||||
cur->callback(spri, cur);
|
||||
/* stop timer */
|
||||
|
||||
/* Stop timer */
|
||||
cur->next = NULL;
|
||||
cur->timeout = 0;
|
||||
cur->callback = NULL;
|
||||
}
|
||||
|
||||
if (handler)
|
||||
handler(spri, cur);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -2247,7 +2247,7 @@ static void fifo_caller_del(const char *uuid)
|
|||
if (uuid) {
|
||||
sql = switch_mprintf("delete from fifo_callers where uuid='%q'", uuid);
|
||||
} else {
|
||||
sql = switch_mprintf("delete from fifo_callers", uuid);
|
||||
sql = switch_mprintf("delete from fifo_callers");
|
||||
}
|
||||
|
||||
fifo_execute_sql(sql, globals.sql_mutex);
|
||||
|
@ -4251,7 +4251,6 @@ static switch_status_t load_config(int reload, int del_all)
|
|||
}
|
||||
}
|
||||
switch_mutex_unlock(globals.mutex);
|
||||
fifo_caller_del(NULL);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -341,6 +341,7 @@ typedef enum {
|
|||
TFLAG_REINVITED,
|
||||
TFLAG_SLA_BARGE,
|
||||
TFLAG_SLA_BARGING,
|
||||
TFLAG_PASS_ACK,
|
||||
/* No new flags below this line */
|
||||
TFLAG_MAX
|
||||
} TFLAGS;
|
||||
|
|
|
@ -954,6 +954,36 @@ void sofia_update_callee_id(switch_core_session_t *session, sofia_profile_t *pro
|
|||
switch_safe_free(dup);
|
||||
}
|
||||
|
||||
static void tech_send_ack(nua_handle_t *nh, private_object_t *tech_pvt)
|
||||
{
|
||||
const char *invite_full_from = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_from");
|
||||
const char *invite_full_to = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_to");
|
||||
|
||||
|
||||
if (sofia_test_pflag(tech_pvt->profile, PFLAG_TRACK_CALLS)) {
|
||||
const char *invite_full_via = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_via");
|
||||
const char *invite_route_uri = switch_channel_get_variable(tech_pvt->channel, "sip_invite_route_uri");
|
||||
|
||||
nua_ack(nh,
|
||||
TAG_IF(invite_full_from, SIPTAG_FROM_STR(invite_full_from)),
|
||||
TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)),
|
||||
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
|
||||
TAG_IF((zstr(tech_pvt->user_via) && !zstr(invite_full_via)), SIPTAG_VIA_STR(invite_full_via)),
|
||||
TAG_IF(!zstr(invite_route_uri), SIPTAG_ROUTE_STR(invite_route_uri)),
|
||||
TAG_END());
|
||||
|
||||
|
||||
} else {
|
||||
nua_ack(nh,
|
||||
TAG_IF(invite_full_from, SIPTAG_FROM_STR(invite_full_from)),
|
||||
TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)),
|
||||
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
|
||||
TAG_END());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//sofia_dispatch_event_t *de
|
||||
static void our_sofia_event_callback(nua_event_t event,
|
||||
int status,
|
||||
|
@ -1124,6 +1154,24 @@ static void our_sofia_event_callback(nua_event_t event,
|
|||
extract_header_vars(profile, sip, session, nh);
|
||||
switch_core_recovery_track(session);
|
||||
sofia_set_flag(tech_pvt, TFLAG_GOT_ACK);
|
||||
|
||||
if (sofia_test_flag(tech_pvt, TFLAG_PASS_ACK)) {
|
||||
switch_core_session_t *other_session;
|
||||
|
||||
sofia_clear_flag(tech_pvt, TFLAG_PASS_ACK);
|
||||
|
||||
|
||||
if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
|
||||
if (switch_core_session_compare(session, other_session)) {
|
||||
private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
|
||||
tech_send_ack(other_tech_pvt->nh, other_tech_pvt);
|
||||
}
|
||||
switch_core_session_rwunlock(other_session);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
case nua_r_ack:
|
||||
|
@ -6311,16 +6359,18 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
|||
break;
|
||||
case nua_callstate_completing:
|
||||
{
|
||||
const char *invite_full_from = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_from");
|
||||
const char *invite_full_to = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_to");
|
||||
const char *wait_for_ack = switch_channel_get_variable(channel, "sip_wait_for_aleg_ack");
|
||||
int send_ack = 1;
|
||||
|
||||
if (switch_true(wait_for_ack)) {
|
||||
switch_core_session_t *other_session;
|
||||
|
||||
if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
|
||||
switch_channel_wait_for_flag(other_channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
|
||||
if (switch_core_session_compare(session, other_session)) {
|
||||
private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
|
||||
sofia_set_flag(other_tech_pvt, TFLAG_PASS_ACK);
|
||||
send_ack = 0;
|
||||
}
|
||||
switch_core_session_rwunlock(other_session);
|
||||
}
|
||||
}
|
||||
|
@ -6341,26 +6391,13 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
|||
|
||||
}
|
||||
|
||||
if (sofia_test_pflag(profile, PFLAG_TRACK_CALLS)) {
|
||||
const char *invite_full_via = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_via");
|
||||
const char *invite_route_uri = switch_channel_get_variable(tech_pvt->channel, "sip_invite_route_uri");
|
||||
|
||||
nua_ack(nh,
|
||||
TAG_IF(invite_full_from, SIPTAG_FROM_STR(invite_full_from)),
|
||||
TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)),
|
||||
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
|
||||
TAG_IF((zstr(tech_pvt->user_via) && !zstr(invite_full_via)), SIPTAG_VIA_STR(invite_full_via)),
|
||||
|
||||
TAG_IF(!zstr(invite_route_uri), SIPTAG_ROUTE_STR(invite_route_uri)),
|
||||
TAG_END());
|
||||
|
||||
if (send_ack) {
|
||||
tech_send_ack(nh, tech_pvt);
|
||||
} else {
|
||||
nua_ack(nh,
|
||||
TAG_IF(invite_full_from, SIPTAG_FROM_STR(invite_full_from)),
|
||||
TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)),
|
||||
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
|
||||
TAG_END());
|
||||
ss_state = nua_callstate_ready;
|
||||
goto state_process;
|
||||
}
|
||||
|
||||
}
|
||||
goto done;
|
||||
case nua_callstate_received:
|
||||
|
|
|
@ -3915,9 +3915,9 @@ void sofia_glue_pass_zrtp_hash2(switch_core_session_t *aleg_session, switch_core
|
|||
bleg_channel = switch_core_session_get_channel(bleg_session);
|
||||
bleg_tech_pvt = switch_core_session_get_private(bleg_session);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_channel), SWITCH_LOG_DEBUG, "Deciding whether to pass zrtp-hash between a-leg and b-leg\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_channel), SWITCH_LOG_DEBUG1, "Deciding whether to pass zrtp-hash between a-leg and b-leg\n");
|
||||
if (!(switch_channel_test_flag(aleg_tech_pvt->channel, CF_ZRTP_PASSTHRU_REQ))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_channel), SWITCH_LOG_DEBUG, "CF_ZRTP_PASSTHRU_REQ not set on a-leg, so not propagating zrtp-hash\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_channel), SWITCH_LOG_DEBUG1, "CF_ZRTP_PASSTHRU_REQ not set on a-leg, so not propagating zrtp-hash\n");
|
||||
return;
|
||||
}
|
||||
if (aleg_tech_pvt->remote_sdp_audio_zrtp_hash) {
|
||||
|
@ -3947,15 +3947,15 @@ void sofia_glue_pass_zrtp_hash(switch_core_session_t *session)
|
|||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
private_object_t *tech_pvt = switch_core_session_get_private(session);
|
||||
switch_core_session_t *other_session;
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Deciding whether to pass zrtp-hash between legs\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG1, "Deciding whether to pass zrtp-hash between legs\n");
|
||||
if (!(switch_channel_test_flag(tech_pvt->channel, CF_ZRTP_PASSTHRU_REQ))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "CF_ZRTP_PASSTHRU_REQ not set, so not propagating zrtp-hash\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG1, "CF_ZRTP_PASSTHRU_REQ not set, so not propagating zrtp-hash\n");
|
||||
return;
|
||||
} else if (!(switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "No partner channel found, so not propagating zrtp-hash\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG1, "No partner channel found, so not propagating zrtp-hash\n");
|
||||
return;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Found peer channel; propagating zrtp-hash if set\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG1, "Found peer channel; propagating zrtp-hash if set\n");
|
||||
sofia_glue_pass_zrtp_hash2(session, other_session);
|
||||
switch_core_session_rwunlock(other_session);
|
||||
}
|
||||
|
@ -3969,7 +3969,7 @@ static void find_zrtp_hash(switch_core_session_t *session, sdp_session_t *sdp)
|
|||
sdp_attribute_t *attr;
|
||||
int got_audio = 0, got_video = 0;
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Looking for zrtp-hash\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG1, "Looking for zrtp-hash\n");
|
||||
for (m = sdp->sdp_media; m; m = m->m_next) {
|
||||
if (got_audio && got_video) break;
|
||||
if (m->m_port && ((m->m_type == sdp_media_audio && !got_audio)
|
||||
|
|
|
@ -145,6 +145,8 @@ namespace FreeSWITCH.Native
|
|||
switch_state_handler_t_delegate del = ptr => {
|
||||
using (var sess = new ManagedSession(new SWIGTYPE_p_switch_core_session(ptr, false))) {
|
||||
handler(sess);
|
||||
sess.SetAutoHangup(false);
|
||||
sess.destroy();
|
||||
return switch_status_t.SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -560,7 +560,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se
|
|||
|
||||
if (!switch_channel_test_flag(channel, CF_BROADCAST)) {
|
||||
switch_channel_set_flag(channel, CF_BROADCAST);
|
||||
inner--;
|
||||
if (inner) {
|
||||
inner--;
|
||||
}
|
||||
}
|
||||
|
||||
if (hold_bleg && switch_true(hold_bleg)) {
|
||||
|
@ -611,7 +613,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se
|
|||
|
||||
if (switch_core_session_execute_application(session, app_name, app_arg) != SWITCH_STATUS_SUCCESS) {
|
||||
if (!inner || switch_channel_test_flag(channel, CF_STOP_BROADCAST)) switch_channel_clear_flag(channel, CF_BROADCAST);
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
|
||||
aftr = switch_micro_time_now();
|
||||
|
|
|
@ -588,7 +588,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
|
|||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "BRIDGE THREAD DONE [%s]\n", switch_channel_get_name(chan_a));
|
||||
switch_channel_clear_flag(chan_a, CF_BRIDGED);
|
||||
|
||||
if (switch_channel_test_flag(chan_a, CF_LEG_HOLDING) && switch_channel_ready(chan_b)) {
|
||||
if (switch_channel_test_flag(chan_a, CF_LEG_HOLDING) && switch_channel_ready(chan_b) && switch_channel_get_state(chan_b) != CS_PARK) {
|
||||
const char *ext = switch_channel_get_variable(chan_a, "hold_hangup_xfer_exten");
|
||||
|
||||
switch_channel_stop_broadcast(chan_b);
|
||||
|
|
Loading…
Reference in New Issue