diff --git a/Makefile.am b/Makefile.am index 413fe49bfc..8c61da454a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 diff --git a/docs/phrase/phrase_en.xml b/docs/phrase/phrase_en.xml index 17c4ce5f03..fa9f4f7cc8 100644 --- a/docs/phrase/phrase_en.xml +++ b/docs/phrase/phrase_en.xml @@ -382,6 +382,7 @@ + @@ -566,7 +567,6 @@ - @@ -583,18 +583,13 @@ - - - - - - - + + @@ -622,6 +617,12 @@ + + + + + + diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index 033d24b620..9412d75c9b 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -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"); diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h index fcaa1bc457..f439694886 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h @@ -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; diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c b/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c index 7cbcc7cd41..fb478901b3 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c @@ -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; } diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 15c6d124f9..2ef5c7fca9 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -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); } diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 7d6659cdfc..f0c57cb988 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -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; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index d132d15918..d1e4a09e73 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -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: diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index c642657fb7..c381ead0d4 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -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) diff --git a/src/mod/languages/mod_managed/managed/ManagedSession.cs b/src/mod/languages/mod_managed/managed/ManagedSession.cs index 07832ae102..9629215c70 100644 --- a/src/mod/languages/mod_managed/managed/ManagedSession.cs +++ b/src/mod/languages/mod_managed/managed/ManagedSession.cs @@ -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; } }; diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 0f98a9b856..95f0e901d8 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -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(); diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index f2aec42fdd..590ebcea34 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -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);