diff --git a/conf/testing/autoload_configs/amrwb.conf.xml b/conf/testing/autoload_configs/amrwb.conf.xml
new file mode 100644
index 0000000000..0bd8e6b733
--- /dev/null
+++ b/conf/testing/autoload_configs/amrwb.conf.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/vanilla/autoload_configs/amr.conf.xml b/conf/vanilla/autoload_configs/amr.conf.xml
index e1c3e3cc1b..19b8cb8891 100644
--- a/conf/vanilla/autoload_configs/amr.conf.xml
+++ b/conf/vanilla/autoload_configs/amr.conf.xml
@@ -15,5 +15,7 @@
+
+
diff --git a/conf/vanilla/autoload_configs/amrwb.conf.xml b/conf/vanilla/autoload_configs/amrwb.conf.xml
index 9dac3505a4..0bd8e6b733 100644
--- a/conf/vanilla/autoload_configs/amrwb.conf.xml
+++ b/conf/vanilla/autoload_configs/amrwb.conf.xml
@@ -1,7 +1,22 @@
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/erlang.spec b/erlang.spec
deleted file mode 100644
index 6cdd7245b9..0000000000
--- a/erlang.spec
+++ /dev/null
@@ -1,297 +0,0 @@
-%define ver %{VERSION_NUMBER}
-%define rel %{RELEASE_NUMBER}
-
-Name: erlang
-Version: %{ver}
-Release: %{rel}.1%{?dist}
-Summary: General-purpose programming language and runtime environment
-
-Group: Development/Languages
-License: ERPL
-URL: http://www.erlang.org
-Source: http://www.erlang.org/download/otp_src_R14B03.tar.gz
-Source1: http://www.erlang.org/download/otp_doc_html_R14B03.tar.gz
-Source2: http://www.erlang.org/download/otp_doc_man_R14B03.tar.gz
-Patch1: otp-R14B-00-0001-Do-not-format-man-pages.patch
-BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-
-BuildRequires: ncurses-devel
-BuildRequires: openssl-devel
-BuildRequires: unixODBC-devel
-BuildRequires: tcl-devel
-BuildRequires: tk-devel
-BuildRequires: gd-devel
-# BuildRequires: jdk
-BuildRequires: flex
-BuildRequires: m4
-
-Requires: tk
-
-# Added virtual Provides for each erlang module
-Provides: erlang-appmon = %{version}-%{release}
-Provides: erlang-asn1 = %{version}-%{release}
-Provides: erlang-common_test = %{version}-%{release}
-Provides: erlang-compiler = %{version}-%{release}
-Provides: erlang-cosEvent = %{version}-%{release}
-Provides: erlang-cosEventDomain = %{version}-%{release}
-Provides: erlang-cosFileTransfer = %{version}-%{release}
-Provides: erlang-cosNotification = %{version}-%{release}
-Provides: erlang-cosProperty = %{version}-%{release}
-Provides: erlang-cosTime = %{version}-%{release}
-Provides: erlang-cosTransactions = %{version}-%{release}
-Provides: erlang-crypto = %{version}-%{release}
-Provides: erlang-debugger = %{version}-%{release}
-Provides: erlang-dialyzer = %{version}-%{release}
-Provides: erlang-docbuilder = %{version}-%{release}
-Provides: erlang-edoc = %{version}-%{release}
-Provides: erlang-erts = %{version}-%{release}
-Provides: erlang-et = %{version}-%{release}
-Provides: erlang-eunit = %{version}-%{release}
-Provides: erlang-gs = %{version}-%{release}
-Provides: erlang-hipe = %{version}-%{release}
-Provides: erlang-ic = %{version}-%{release}
-Provides: erlang-inets = %{version}-%{release}
-Provides: erlang-inviso = %{version}-%{release}
-Provides: erlang-kernel = %{version}-%{release}
-Provides: erlang-megaco = %{version}-%{release}
-Provides: erlang-mnesia = %{version}-%{release}
-Provides: erlang-observer = %{version}-%{release}
-Provides: erlang-odbc = %{version}-%{release}
-Provides: erlang-orber = %{version}-%{release}
-Provides: erlang-os_mon = %{version}-%{release}
-Provides: erlang-otp_mibs = %{version}-%{release}
-Provides: erlang-parsetools = %{version}-%{release}
-Provides: erlang-percept = %{version}-%{release}
-Provides: erlang-pman = %{version}-%{release}
-Provides: erlang-public_key = %{version}-%{release}
-Provides: erlang-runtime_tools = %{version}-%{release}
-Provides: erlang-sasl = %{version}-%{release}
-Provides: erlang-snmp = %{version}-%{release}
-Provides: erlang-ssh = %{version}-%{release}
-Provides: erlang-ssl = %{version}-%{release}
-Provides: erlang-stdlib = %{version}-%{release}
-Provides: erlang-syntax_tools = %{version}-%{release}
-Provides: erlang-test_server = %{version}-%{release}
-Provides: erlang-toolbar = %{version}-%{release}
-Provides: erlang-tools = %{version}-%{release}
-Provides: erlang-tv = %{version}-%{release}
-Provides: erlang-typer = %{version}-%{release}
-Provides: erlang-webtool = %{version}-%{release}
-Provides: erlang-xmerl = %{version}-%{release}
-
-%description
-Erlang is a general-purpose programming language and runtime
-environment. Erlang has built-in support for concurrency, distribution
-and fault tolerance. Erlang is used in several large telecommunication
-systems from Ericsson.
-
-
-%package doc
-Summary: Erlang documentation
-Group: Development/Languages
-
-%description doc
-Documentation for Erlang.
-
-
-%prep
-%setup -q -n otp_src_%{ver}%{rel}
-#%setup -q -n otp_src_%{ver}
-
-%build
-# WARN: --enable-dynamic-ssl-lib needed for preventing strange messages about missing dependencies on EPEL
-# see https://bugzilla.redhat.com/458646 and https://bugzilla.redhat.com/499525
-%ifarch sparcv9 sparc64
-CFLAGS="$RPM_OPT_FLAGS -mcpu=ultrasparc -fno-strict-aliasing" %configure --enable-dynamic-ssl-lib
-%else
-CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing" %configure --enable-dynamic-ssl-lib
-%endif
-chmod -R u+w .
-make
-
-
-%install
-rm -rf $RPM_BUILD_ROOT
-make INSTALL_PREFIX=$RPM_BUILD_ROOT install
-
-# clean up
-find $RPM_BUILD_ROOT%{_libdir}/erlang -perm 0775 | xargs chmod 755
-find $RPM_BUILD_ROOT%{_libdir}/erlang -name Makefile | xargs chmod 644
-find $RPM_BUILD_ROOT%{_libdir}/erlang -name \*.o | xargs chmod 644
-find $RPM_BUILD_ROOT%{_libdir}/erlang -name \*.bat | xargs rm -f
-find $RPM_BUILD_ROOT%{_libdir}/erlang -name index.txt.old | xargs rm -f
-
-# doc
-mkdir -p erlang_doc
-tar -C erlang_doc -zxf %{SOURCE1}
-tar -C $RPM_BUILD_ROOT/%{_libdir}/erlang -zxf %{SOURCE2}
-
-# make links to binaries
-#mkdir -p $RPM_BUILD_ROOT/%{_bindir}
-#cd $RPM_BUILD_ROOT/%{_bindir}
-#for file in erl erlc escript dialyzer
-#do
-# ln -sf ../%{_lib}/erlang/bin/$file .
-#done
-
-# remove buildroot from installed files
-cd $RPM_BUILD_ROOT/%{_libdir}/erlang
-sed -i "s|$RPM_BUILD_ROOT||" erts*/bin/{erl,start} releases/RELEASES bin/{erl,start}
-
-
-%clean
-rm -rf $RPM_BUILD_ROOT
-
-
-%files
-%defattr(-,root,root)
-%doc AUTHORS EPLICENCE README.md
-%{_bindir}/*
-%{_libdir}/erlang
-
-
-%files doc
-%defattr(-,root,root)
-%doc erlang_doc/*
-
-
-%post
-%{_libdir}/erlang/Install -minimal %{_libdir}/erlang >/dev/null 2>/dev/null
-
-
-%changelog
-* Wed Sep 29 2010 Anthony Molinaro - R14B-00.1
-- modified R13B04 spec to work with R14B
-
-* Wed Jul 7 2010 Anthony Molinaro - R13B-04.1
-- modified the R12B spec to work with R13B04
-
-* Mon Jun 7 2010 Peter Lemenkov - R12B-5.10
-- Added missing virtual provides erlang-erts
-
-* Tue May 25 2010 Peter Lemenkov - R12B-5.9
-- Use java-1.4.2 only for EL-[45]
-- Added virtual provides for each erlang module
-- Small typo fix
-
-* Mon Apr 19 2010 Peter Lemenkov - R12B-5.8
-- Patches rebased
-- Added patches 6,7 from trunk
-- Use %%configure
-
-* Tue Apr 21 2009 Debarshi Ray R12B-5.7
-- Updated rpath patch.
-- Fixed configure to respect $RPM_OPT_FLAGS.
-
-* Sun Mar 1 2009 Gerard Milmeister - R12B-5.6
-- new release R12B-5
-- link escript and dialyzer to %{_bindir}
-
-* Tue Feb 24 2009 Fedora Release Engineering - R12B-5.5
-- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
-
-* Sat Feb 14 2009 Dennis Gilmore - R12B-4.5
-- fix sparc arches to compile
-
-* Fri Jan 16 2009 Tomas Mraz - R12B-4.4
-- rebuild with new openssl
-
-* Sat Oct 25 2008 Gerard Milmeister - R12B-4.1
-- new release R12B-4
-
-* Fri Sep 5 2008 Gerard Milmeister - R12B-3.3
-- fixed sslrpath patch
-
-* Thu Jul 17 2008 Tom "spot" Callaway - R12B-3.2
-- fix license tag
-
-* Sun Jul 6 2008 Gerard Milmeister - R12B-3.1
-- new release R12B-3
-
-* Thu Mar 27 2008 Gerard Milmeister - R12B-1.1
-- new release R12B-1
-
-* Sat Feb 23 2008 Gerard Milmeister - R12B-0.3
-- disable strict aliasing optimization
-
-* Mon Feb 18 2008 Fedora Release Engineering - R12B-0.2
-- Autorebuild for GCC 4.3
-
-* Sat Dec 8 2007 Gerard Milmeister - R12B-0.1
-- new release R12B-0
-
-* Wed Dec 05 2007 Release Engineering - R11B-6
- - Rebuild for deps
-
-* Sun Aug 19 2007 Gerard Milmeister - R11B-5.3
-- fix some permissions
-
-* Sat Aug 18 2007 Gerard Milmeister - R11B-5.2
-- enable dynamic linking for ssl
-
-* Sat Aug 18 2007 Gerard Milmeister - R11B-5.1
-- new release R11B-5
-
-* Sat Mar 24 2007 Thomas Fitzsimmons - R11B-2.4
-- Require java-1.5.0-gcj-devel for build.
-
-* Sun Dec 31 2006 Gerard Milmeister - R11B-2.3
-- remove buildroot from installed files
-
-* Sat Dec 30 2006 Gerard Milmeister - R11B-2.2
-- added patch for compiling with glibc 2.5
-
-* Sat Dec 30 2006 Gerard Milmeister - R11B-2.1
-- new version R11B-2
-
-* Mon Aug 28 2006 Gerard Milmeister - R11B-0.3
-- Rebuild for FE6
-
-* Wed Jul 5 2006 Gerard Milmeister - R11B-0.2
-- add BR m4
-
-* Thu May 18 2006 Gerard Milmeister - R11B-0.1
-- new version R11B-0
-
-* Wed May 3 2006 Gerard Milmeister - R10B-10.3
-- added patch for run_erl by Knut-HÃ¥vard Aksnes
-
-* Mon Mar 13 2006 Gerard Milmeister - R10B-10.1
-- new version R10B-10
-
-* Thu Dec 29 2005 Gerard Milmeister - R10B-9.1
-- New Version R10B-9
-
-* Sat Oct 29 2005 Gerard Milmeister - R10B-8.2
-- updated rpath patch
-
-* Sat Oct 29 2005 Gerard Milmeister - R10B-8.1
-- New Version R10B-8
-
-* Sat Oct 1 2005 Gerard Milmeister - R10B-6.4
-- Added tk-devel and tcl-devel to buildreq
-- Added tk to req
-
-* Tue Sep 6 2005 Gerard Milmeister - R10B-6.3
-- Remove perl BuildRequires
-
-* Tue Aug 30 2005 Gerard Milmeister - R10B-6.2
-- change /usr/lib to %%{_libdir}
-- redirect output in %%post to /dev/null
-- add unixODBC-devel to BuildRequires
-- split doc off to erlang-doc package
-
-* Sat Jun 25 2005 Gerard Milmeister - R10B-6.1
-- New Version R10B-6
-
-* Sun Feb 13 2005 Gerard Milmeister - R10B-3.1
-- New Version R10B-3
-
-* Mon Dec 27 2004 Gerard Milmeister - 0:R10B-2-0.fdr.1
-- New Version R10B-2
-
-* Wed Oct 6 2004 Gerard Milmeister - 0:R10B-0.fdr.1
-- New Version R10B
-
-* Thu Oct 16 2003 Gerard Milmeister - 0:R9B-1.fdr.1
-- First Fedora release
diff --git a/freeswitch.spec b/freeswitch.spec
index 4cf49c2118..66bd762caa 100644
--- a/freeswitch.spec
+++ b/freeswitch.spec
@@ -37,7 +37,6 @@
%define build_mod_esl 0
%define build_mod_rayo 1
%define build_mod_ssml 1
-%define build_mod_shout 1
%define build_mod_opusfile 0
%define build_mod_v8 0
@@ -47,7 +46,6 @@
%{?with_py26_esl:%define build_py26_esl 1 }
%{?with_timerfd:%define build_timerfd 1 }
%{?with_mod_esl:%define build_mod_esl 1 }
-%{?with_mod_shout:%define build_mod_shout 1 }
%{?with_mod_opusfile:%define build_mod_opusfile 1 }
%{?with_mod_v8:%define build_mod_v8 1 }
@@ -176,6 +174,9 @@ Requires: libsndfile
PreReq: %insserv_prereq %fillup_prereq
%endif
+%if 0%{?fedora}
+BuildRequires: gumbo-parser-devel
+%endif
######################################################################################################################
#
@@ -1078,7 +1079,6 @@ Mod shell stream is a FreeSWITCH module to allow you to stream audio from an
arbitrary shell command. You could use it to read audio from a database, from
a soundcard, etc.
-%if %{build_mod_shout}
%package format-mod-shout
Summary: Implements Media Steaming from arbitrary shell commands for the FreeSWITCH open source telephony platform
Group: System/Libraries
@@ -1093,7 +1093,6 @@ BuildRequires: lame-devel
%description format-mod-shout
Mod Shout is a FreeSWITCH module to allow you to stream audio from MP3s or a i
shoutcast stream.
-%endif
%if %{build_mod_opusfile}
%package format-mod-opusfile
@@ -1503,10 +1502,7 @@ EVENT_HANDLERS_MODULES+=" event_handlers/mod_rayo"
#
######################################################################################################################
FORMATS_MODULES="formats/mod_local_stream formats/mod_native_file formats/mod_portaudio_stream \
- formats/mod_shell_stream formats/mod_sndfile formats/mod_tone_stream"
-%if %{build_mod_shout}
-FORMATS_MODULES+=" formats/mod_shout "
-%endif
+ formats/mod_shell_stream formats/mod_shout formats/mod_sndfile formats/mod_tone_stream"
%if %{build_mod_ssml}
FORMATS_MODULES+=" formats/mod_ssml"
%endif
@@ -1622,6 +1618,7 @@ autoreconf --force --install
--with-odbc \
--with-erlang \
--with-openssl \
+--enable-zrtp \
%{?configure_options}
unset MODULES
@@ -1645,6 +1642,7 @@ cd libs/esl
%{__mkdir} -p %{buildroot}%{prefix}/log
%{__mkdir} -p %{buildroot}%{logfiledir}
%{__mkdir} -p %{buildroot}%{runtimedir}
+%{__mkdir} -p %{buildroot}%{_localstatedir}/cache/freeswitch
#install the esl stuff
cd libs/esl
@@ -2073,6 +2071,7 @@ fi
%{MODINSTDIR}/mod_httapi.so*
%files application-http-cache
+%dir %attr(0750, freeswitch, daemon) %{_localstatedir}/cache/freeswitch
%{MODINSTDIR}/mod_http_cache.so*
%files application-lcr
@@ -2324,10 +2323,8 @@ fi
%files format-shell-stream
%{MODINSTDIR}/mod_shell_stream.so*
-%if %{build_mod_shout}
%files format-mod-shout
%{MODINSTDIR}/mod_shout.so*
-%endif
%if %{build_mod_ssml}
%files format-ssml
@@ -2344,18 +2341,15 @@ fi
######################################################################################################################
%files lua
%{MODINSTDIR}/mod_lua*.so*
-%dir %attr(0750, freeswitch, daemon) %{sysconfdir}/autoload_configs
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/lua.conf.xml
%files perl
%{MODINSTDIR}/mod_perl*.so*
%{prefix}/perl/*
-%dir %attr(0750, freeswitch, daemon) %{sysconfdir}/autoload_configs
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/perl.conf.xml
%files python
%{MODINSTDIR}/mod_python*.so*
-%dir %attr(0750, freeswitch, daemon) %{sysconfdir}/autoload_configs
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/python.conf.xml
%if %{build_mod_v8}
@@ -2365,7 +2359,6 @@ fi
%{LIBDIR}/libicui18n.so
%{LIBDIR}/libicuuc.so
%endif
-%dir %attr(0750, freeswitch, daemon) %{sysconfdir}/autoload_configs
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/v8.conf.xml
######################################################################################################################
diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h
index c3478f109e..68a8d9c463 100644
--- a/src/include/private/switch_core_pvt.h
+++ b/src/include/private/switch_core_pvt.h
@@ -132,6 +132,7 @@ struct switch_core_session {
switch_mutex_t *mutex;
switch_mutex_t *stack_count_mutex;
switch_mutex_t *resample_mutex;
+ switch_mutex_t *codec_init_mutex;
switch_mutex_t *codec_read_mutex;
switch_mutex_t *codec_write_mutex;
switch_mutex_t *video_codec_read_mutex;
diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h
index d49f7f3eb6..d347b1c7fb 100644
--- a/src/include/switch_module_interfaces.h
+++ b/src/include/switch_module_interfaces.h
@@ -854,8 +854,8 @@ struct switch_json_api_interface {
struct switch_json_api_interface *next;
};
-#define PROTECT_INTERFACE(_it) if (_it) {switch_mutex_lock(_it->reflock); switch_thread_rwlock_rdlock(_it->parent->rwlock); switch_thread_rwlock_rdlock(_it->rwlock); _it->refs++; _it->parent->refs++; switch_mutex_unlock(_it->reflock);} //if (!strcmp(_it->interface_name, "user")) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "+++++++++++LOCK %s %d/%d\n", _it->interface_name, _it->refs, _it->parent->refs);
-#define UNPROTECT_INTERFACE(_it) if (_it) {switch_mutex_lock(_it->reflock); switch_thread_rwlock_unlock(_it->rwlock); switch_thread_rwlock_unlock(_it->parent->rwlock); _it->refs--; _it->parent->refs--; switch_mutex_unlock(_it->reflock);} //if (!strcmp(_it->interface_name, "user")) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "---------UNLOCK %s %d/%d\n", _it->interface_name, _it->refs, _it->parent->refs);
+#define PROTECT_INTERFACE(_it) if (_it) {switch_thread_rwlock_rdlock(_it->parent->rwlock); switch_thread_rwlock_rdlock(_it->rwlock); switch_mutex_lock(_it->reflock); _it->refs++; _it->parent->refs++; switch_mutex_unlock(_it->reflock);} //if (!strcmp(_it->interface_name, "user")) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "+++++++++++LOCK %s %d/%d\n", _it->interface_name, _it->refs, _it->parent->refs);
+#define UNPROTECT_INTERFACE(_it) if (_it) {switch_mutex_lock(_it->reflock); _it->refs--; _it->parent->refs--; switch_mutex_unlock(_it->reflock); switch_thread_rwlock_unlock(_it->rwlock); switch_thread_rwlock_unlock(_it->parent->rwlock);} //if (!strcmp(_it->interface_name, "user")) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "---------UNLOCK %s %d/%d\n", _it->interface_name, _it->refs, _it->parent->refs);
#include "switch_frame.h"
diff --git a/src/include/switch_scheduler.h b/src/include/switch_scheduler.h
index 14403917ca..1100fdb052 100644
--- a/src/include/switch_scheduler.h
+++ b/src/include/switch_scheduler.h
@@ -66,6 +66,23 @@ SWITCH_DECLARE(uint32_t) switch_scheduler_add_task(time_t task_runtime,
switch_scheduler_func_t func,
const char *desc, const char *group, uint32_t cmd_id, void *cmd_arg, switch_scheduler_flag_t flags);
+/*!
+ \brief Schedule a task in the future
+ \param task_runtime the time in epoch seconds to execute the task.
+ \param func the callback function to execute when the task is executed.
+ \param desc an arbitrary description of the task.
+ \param group a group id tag to link multiple tasks to a single entity.
+ \param cmd_id an arbitrary index number be used in the callback.
+ \param cmd_arg user data to be passed to the callback.
+ \param flags flags to alter behaviour
+ \param task_id pointer to put the id of the task to
+ \return the id of the task
+*/
+
+SWITCH_DECLARE(uint32_t) switch_scheduler_add_task_ex(time_t task_runtime,
+ switch_scheduler_func_t func,
+ const char *desc, const char *group, uint32_t cmd_id, void *cmd_arg, switch_scheduler_flag_t flags, uint32_t *task_id);
+
/*!
\brief Delete a scheduled task
\param task_id the id of the task
diff --git a/src/include/switch_types.h b/src/include/switch_types.h
index 133422764b..79ef9caa26 100644
--- a/src/include/switch_types.h
+++ b/src/include/switch_types.h
@@ -353,7 +353,8 @@ typedef enum {
ED_BRIDGE_READ = (1 << 4),
ED_BRIDGE_WRITE = (1 << 5),
ED_TAP_READ = (1 << 6),
- ED_TAP_WRITE = (1 << 7)
+ ED_TAP_WRITE = (1 << 7),
+ ED_STEREO = (1 << 8)
} switch_eavesdrop_flag_enum_t;
typedef uint32_t switch_eavesdrop_flag_t;
@@ -1415,6 +1416,7 @@ CF_HOLD_BLEG - B leg is on hold
CF_SERVICE - Channel has a service thread
CF_TAGGED - Channel is tagged
CF_WINNER - Channel is the winner
+CF_REUSE_CALLER_PROFILE - Channel reuse caller profile
CF_CONTROLLED - Channel is under control
CF_PROXY_MODE - Channel has no media
CF_SUSPEND - Suspend i/o
@@ -1467,6 +1469,7 @@ typedef enum {
CF_SERVICE,
CF_TAGGED,
CF_WINNER,
+ CF_REUSE_CALLER_PROFILE,
CF_CONTROLLED,
CF_PROXY_MODE,
CF_PROXY_OFF,
diff --git a/src/include/test/switch_fct.h b/src/include/test/switch_fct.h
index a9b3595d0e..f88821b49c 100644
--- a/src/include/test/switch_fct.h
+++ b/src/include/test/switch_fct.h
@@ -1716,6 +1716,12 @@ fct_clp__parse(fct_clp_t *clp, int argc, char const *argv[])
arg =NULL;
}
}
+
+ if (arg != NULL)
+ {
+ free(arg);
+ arg = NULL;
+ }
}
diff --git a/src/include/test/switch_test.h b/src/include/test/switch_test.h
index eb6f7f3ee6..3413884145 100644
--- a/src/include/test/switch_test.h
+++ b/src/include/test/switch_test.h
@@ -141,7 +141,7 @@ static switch_status_t fst_init_core_and_modload(const char *confdir, const char
*/
#define fst_session_park(session) \
switch_ivr_park_session(session); \
- switch_channel_wait_for_state(switch_core_session_get_channel(session), NULL, CS_PARK);
+ switch_channel_wait_for_flag(switch_core_session_get_channel(session), CF_PARK, SWITCH_TRUE, 10000, NULL);
/**
* check for test requirement - execute teardown on failure
diff --git a/src/mod/applications/mod_av/avcodec.c b/src/mod/applications/mod_av/avcodec.c
index f1a58cb7d7..01c862cf11 100644
--- a/src/mod/applications/mod_av/avcodec.c
+++ b/src/mod/applications/mod_av/avcodec.c
@@ -110,7 +110,7 @@ static void dump_encoder_ctx(AVCodecContext *ctx)
#ifdef DUMP_ENCODER_CTX
#define STRINGIFY(x) #x
#define my_dump_int(x) switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR, STRINGIFY(x) " = %d\n", ctx->x);
-#define my_dump_int64(x) switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR, STRINGIFY(x) " = % " SWITCH_INT64_T_FMT "\n", ctx->x);
+#define my_dump_int64(x) switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR, STRINGIFY(x) " = %" SWITCH_INT64_T_FMT "\n", ctx->x);
#define my_dump_float(x) switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR, STRINGIFY(x) " = %f\n", ctx->x);
#define my_dump_enum(x) switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR, STRINGIFY(x) " = %d\n", ctx->x);
#define my_dump_uint(x) switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR, STRINGIFY(x) " = 0x%x\n", ctx->x);
diff --git a/src/mod/applications/mod_av/avformat.c b/src/mod/applications/mod_av/avformat.c
index ae7d2e840c..0b3a452325 100644
--- a/src/mod/applications/mod_av/avformat.c
+++ b/src/mod/applications/mod_av/avformat.c
@@ -702,7 +702,7 @@ GCC_DIAG_ON(deprecated-declarations)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "sample_rate: %d nb_samples: %d\n", mst->frame->sample_rate, mst->frame->nb_samples);
- if (c->sample_fmt != AV_SAMPLE_FMT_S16) {
+ if (c->sample_fmt != AV_SAMPLE_FMT_S16 || c->sample_rate != mst->sample_rate) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "sample_fmt %d != AV_SAMPLE_FMT_S16, start resampler\n", c->sample_fmt);
mst->resample_ctx = swr_alloc();
@@ -1231,7 +1231,7 @@ GCC_DIAG_ON(deprecated-declarations)
context->audio_st[1].sample_rate = handle->samplerate;
GCC_DIAG_OFF(deprecated-declarations)
- if (context->audio_st[0].st->codec->sample_fmt != AV_SAMPLE_FMT_S16) {
+ if (context->audio_st[0].st->codec->sample_fmt != AV_SAMPLE_FMT_S16 || context->audio_st[0].st->codec->sample_rate != handle->samplerate) {
GCC_DIAG_ON(deprecated-declarations)
int x;
for (x = 0; x < context->has_audio && x < 2 && c[x]; x++) {
diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c
index 58816ea0ac..cba6dc84f4 100644
--- a/src/mod/applications/mod_callcenter/mod_callcenter.c
+++ b/src/mod/applications/mod_callcenter/mod_callcenter.c
@@ -998,7 +998,7 @@ cc_status_t cc_agent_update(const char *key, const char *value, const char *agen
{
cc_status_t result = CC_STATUS_SUCCESS;
char *sql;
- char res[256];
+ char res[256] = "";
switch_event_t *event;
/* Check to see if agent already exist */
diff --git a/src/mod/applications/mod_curl/mod_curl.c b/src/mod/applications/mod_curl/mod_curl.c
index e82502cb6c..f0c952a215 100644
--- a/src/mod/applications/mod_curl/mod_curl.c
+++ b/src/mod/applications/mod_curl/mod_curl.c
@@ -799,7 +799,7 @@ SWITCH_STANDARD_APP(curl_app_function)
switch_channel_t *channel = switch_core_session_get_channel(session);
char *url = NULL;
char *method = NULL;
- char *postdata = NULL;
+ char *postdata = "";
char *content_type = NULL;
switch_bool_t do_headers = SWITCH_FALSE;
switch_bool_t do_json = SWITCH_FALSE;
@@ -920,7 +920,7 @@ SWITCH_STANDARD_API(curl_function)
char *mydata = NULL;
char *url = NULL;
char *method = NULL;
- char *postdata = NULL;
+ char *postdata = "";
char *content_type = NULL;
switch_bool_t do_headers = SWITCH_FALSE;
switch_bool_t do_json = SWITCH_FALSE;
diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c
index f891c6a513..43329eb006 100644
--- a/src/mod/applications/mod_dptools/mod_dptools.c
+++ b/src/mod/applications/mod_dptools/mod_dptools.c
@@ -1150,6 +1150,13 @@ SWITCH_STANDARD_APP(break_function)
}
}
+SWITCH_STANDARD_APP(reuse_caller_profile_function)
+{
+ switch_channel_t *channel;
+ channel = switch_core_session_get_channel(session);
+ switch_channel_set_flag(channel, CF_REUSE_CALLER_PROFILE);
+}
+
SWITCH_STANDARD_APP(queue_dtmf_function)
{
switch_channel_queue_dtmf_string(switch_core_session_get_channel(session), (const char *) data);
@@ -6551,6 +6558,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "deflect", "Send call deflect", "Send a call deflect.", deflect_function, "", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "recovery_refresh", "Send call recovery_refresh", "Send a call recovery_refresh.", recovery_refresh_function, "", SAF_SUPPORT_NOMEDIA);
+ SWITCH_ADD_APP(app_interface, "reuse_caller_profile", "Reuse the caller profile", "Reuse the caller profile", reuse_caller_profile_function, "", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "queue_dtmf", "Queue dtmf to be sent", "Queue dtmf to be sent from a session", queue_dtmf_function, "",
SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "send_dtmf", "Send dtmf to be sent", "Send dtmf to be sent from a session", send_dtmf_function, "",
diff --git a/src/mod/applications/mod_enum/mod_enum.c b/src/mod/applications/mod_enum/mod_enum.c
index f6ca99abce..de5804e1fd 100644
--- a/src/mod/applications/mod_enum/mod_enum.c
+++ b/src/mod/applications/mod_enum/mod_enum.c
@@ -496,6 +496,9 @@ switch_status_t ldns_lookup(const char *number, const char *root, char *server_n
if (!added_server) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No Nameservers specified, using host default\n");
/* create a new resolver from /etc/resolv.conf */
+ if (res) {
+ ldns_resolver_free(res);
+ }
s = ldns_resolver_new_frm_file(&res, NULL);
}
diff --git a/src/mod/applications/mod_httapi/mod_httapi.c b/src/mod/applications/mod_httapi/mod_httapi.c
index 76d273d020..cc2c857a58 100644
--- a/src/mod/applications/mod_httapi/mod_httapi.c
+++ b/src/mod/applications/mod_httapi/mod_httapi.c
@@ -1534,6 +1534,7 @@ static switch_status_t httapi_sync(client_t *client)
char *q, *p = strstr(dynamic_url, "://");
use_url++;
+ switch_safe_free(dup_creds);
dup_creds = strdup(p+3);
*p = '\0';
diff --git a/src/mod/applications/mod_http_cache/aws.c b/src/mod/applications/mod_http_cache/aws.c
index 740fe2e9c4..cc02b4e5b5 100644
--- a/src/mod/applications/mod_http_cache/aws.c
+++ b/src/mod/applications/mod_http_cache/aws.c
@@ -144,10 +144,12 @@ static char* aws_s3_signature_key(char* key_signing, switch_aws_s3_profile* aws_
char key_service[SHA256_DIGEST_LENGTH];
char* aws4_secret_access_key = switch_mprintf("AWS4%s", aws_s3_profile->access_key_secret);
- hmac256(key_date, SHA256_DIGEST_LENGTH, aws4_secret_access_key, strlen(aws4_secret_access_key), aws_s3_profile->date_stamp);
- hmac256(key_region, SHA256_DIGEST_LENGTH, key_date, SHA256_DIGEST_LENGTH, aws_s3_profile->region);
- hmac256(key_service, SHA256_DIGEST_LENGTH, key_region, SHA256_DIGEST_LENGTH, "s3");
- hmac256(key_signing, SHA256_DIGEST_LENGTH, key_service, SHA256_DIGEST_LENGTH, "aws4_request");
+ if (!hmac256(key_date, SHA256_DIGEST_LENGTH, aws4_secret_access_key, (unsigned int)strlen(aws4_secret_access_key), aws_s3_profile->date_stamp)
+ || !hmac256(key_region, SHA256_DIGEST_LENGTH, key_date, SHA256_DIGEST_LENGTH, aws_s3_profile->region)
+ || !hmac256(key_service, SHA256_DIGEST_LENGTH, key_region, SHA256_DIGEST_LENGTH, "s3")
+ || !hmac256(key_signing, SHA256_DIGEST_LENGTH, key_service, SHA256_DIGEST_LENGTH, "aws4_request")) {
+ key_signing = NULL;
+ }
switch_safe_free(aws4_secret_access_key);
@@ -166,7 +168,7 @@ static char* aws_s3_standardized_query_string(switch_aws_s3_profile* aws_s3_prof
char* standardized_query_string;
credential = switch_mprintf("%s%%2F%s%%2F%s%%2Fs3%%2Faws4_request", aws_s3_profile->access_key_id, aws_s3_profile->date_stamp, aws_s3_profile->region);
- switch_snprintf(expires, 9, "%ld", aws_s3_profile->expires);
+ switch_snprintf(expires, 9, "%" SWITCH_TIME_T_FMT, aws_s3_profile->expires);
standardized_query_string = switch_mprintf(
"X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=%s&X-Amz-Date=%s&X-Amz-Expires=%s&X-Amz-SignedHeaders=host",
@@ -243,13 +245,14 @@ static char *aws_s3_authentication_create(switch_aws_s3_profile* aws_s3_profile)
string_to_sign = aws_s3_string_to_sign(standardized_request, aws_s3_profile);
// Get signature_key
- aws_s3_signature_key(signature_key, aws_s3_profile);
-
- // Get signature
- hmac256_hex(signature, signature_key, SHA256_DIGEST_LENGTH, string_to_sign);
-
- // Build final query string
- query_param = switch_mprintf("%s&X-Amz-Signature=%s", standardized_query_string, signature);
+ if (!aws_s3_signature_key(signature_key, aws_s3_profile)
+ // Get signature
+ || !hmac256_hex(signature, signature_key, SHA256_DIGEST_LENGTH, string_to_sign)) {
+ query_param = NULL;
+ } else {
+ // Build final query string
+ query_param = switch_mprintf("%s&X-Amz-Signature=%s", standardized_query_string, signature);
+ }
switch_safe_free(string_to_sign);
switch_safe_free(standardized_query_string);
diff --git a/src/mod/applications/mod_lcr/mod_lcr.c b/src/mod/applications/mod_lcr/mod_lcr.c
index a9adb3db10..ab7c163ce5 100644
--- a/src/mod/applications/mod_lcr/mod_lcr.c
+++ b/src/mod/applications/mod_lcr/mod_lcr.c
@@ -1186,6 +1186,8 @@ static switch_status_t lcr_load_config()
if (db_check("ALTER TABLE carrier_gateway add codec varchar(255);") == SWITCH_TRUE) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "adding codec field your lcr carrier_gateway database schema.\n");
} else {
+ switch_safe_free(order_by.data);
+ switch_safe_free(sql_stream.data);
switch_goto_status(SWITCH_STATUS_FALSE, done);
}
}
@@ -1197,6 +1199,8 @@ static switch_status_t lcr_load_config()
if (db_check("ALTER TABLE lcr add cid varchar(32);") == SWITCH_TRUE) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "adding cid field to your lcr database schema.\n");
} else {
+ switch_safe_free(order_by.data);
+ switch_safe_free(sql_stream.data);
switch_goto_status(SWITCH_STATUS_FALSE, done);
}
}
@@ -1205,6 +1209,8 @@ static switch_status_t lcr_load_config()
if (db_check("ALTER TABLE lcr ADD lrn BOOLEAN NOT NULL DEFAULT false")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "adding lrn field to your lcr database schema.\n");
} else {
+ switch_safe_free(order_by.data);
+ switch_safe_free(sql_stream.data);
switch_goto_status(SWITCH_STATUS_FALSE, done);
}
}
diff --git a/src/mod/applications/mod_mongo/mod_mongo.c b/src/mod/applications/mod_mongo/mod_mongo.c
index aac3221fe7..b66b01369a 100644
--- a/src/mod/applications/mod_mongo/mod_mongo.c
+++ b/src/mod/applications/mod_mongo/mod_mongo.c
@@ -698,6 +698,7 @@ SWITCH_LIMIT_RELEASE(mod_mongo_limit_release)
if (mod_mongo_increment(session, (const char *)p_key, -1, 0, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Couldn't decrement %s\n", (const char *)p_key);
status = SWITCH_STATUS_FALSE;
+ free(hi);
break;
} else {
switch_core_hash_delete(pvt->resources, (const char *) p_key);
diff --git a/src/mod/applications/mod_redis/mod_redis.c b/src/mod/applications/mod_redis/mod_redis.c
index 7f140fe7d6..5d4c132cd7 100644
--- a/src/mod/applications/mod_redis/mod_redis.c
+++ b/src/mod/applications/mod_redis/mod_redis.c
@@ -197,11 +197,13 @@ SWITCH_LIMIT_RELEASE(limit_release_redis)
if (credis_decr(redis, (const char*)p_key, &val) != 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Couldn't decrement value corresponding to %s\n", (char *)p_key);
+ free(hi);
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
p_uuid_key = switch_core_session_sprintf(session, "%s_%s", switch_core_get_switchname(), (char *)p_key);
if (credis_decr(redis,p_uuid_key,&uuid_val) != 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Couldn't decrement value corresponding to %s\n", p_uuid_key);
+ free(hi);
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
switch_core_hash_delete(pvt->hash, (const char *) p_key);
diff --git a/src/mod/applications/mod_snom/mod_snom.c b/src/mod/applications/mod_snom/mod_snom.c
index af460e7523..2f706c2556 100644
--- a/src/mod/applications/mod_snom/mod_snom.c
+++ b/src/mod/applications/mod_snom/mod_snom.c
@@ -143,7 +143,7 @@ SWITCH_STANDARD_API(snom_command_api_function)
}
if (switch_inet_pton(AF_INET, argv[0], &ip)) {
- strncpy(host, argv[0], sizeof(host));
+ snprintf(host, sizeof(host), "%s", argv[0]);
} else {
char *sql = NULL;
char *ret = NULL;
diff --git a/src/mod/applications/mod_video_filter/mod_video_filter.c b/src/mod/applications/mod_video_filter/mod_video_filter.c
index 3cd8c84ce9..613f8d9195 100644
--- a/src/mod/applications/mod_video_filter/mod_video_filter.c
+++ b/src/mod/applications/mod_video_filter/mod_video_filter.c
@@ -970,7 +970,7 @@ SWITCH_STANDARD_APP(video_replace_start_function)
return;
}
- switch_channel_wait_for_flag(channel, CF_VIDEO_READY, SWITCH_TRUE, 10000, NULL);
+ // switch_channel_wait_for_flag(channel, CF_VIDEO_READY, SWITCH_TRUE, 10000, NULL);
context = (video_replace_context_t *) switch_core_session_alloc(session, sizeof(*context));
switch_assert(context != NULL);
diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c
index aba1dc4cf0..dd3a74a463 100644
--- a/src/mod/applications/mod_voicemail/mod_voicemail.c
+++ b/src/mod/applications/mod_voicemail/mod_voicemail.c
@@ -3855,6 +3855,7 @@ SWITCH_STANDARD_API(boxcount_api_function)
total_new_messages = total_saved_messages = 0;
message_count(profile, id, domain, "inbox", &total_new_messages, &total_saved_messages,
&total_new_urgent_messages, &total_saved_urgent_messages);
+ free(hi);
}
switch_mutex_unlock(globals.mutex);
}
diff --git a/src/mod/codecs/mod_amr/mod_amr.c b/src/mod/codecs/mod_amr/mod_amr.c
index 04717ca52c..e7c45c7aff 100644
--- a/src/mod/codecs/mod_amr/mod_amr.c
+++ b/src/mod/codecs/mod_amr/mod_amr.c
@@ -137,6 +137,7 @@ static struct {
switch_byte_t volte; /* enable special fmtp for VoLTE compliance */
switch_byte_t adjust_bitrate;
int debug;
+ switch_byte_t force_oa; /*force OA when originating*/
} globals;
const int switch_amr_frame_sizes[] = {12,13,15,17,19,20,26,31,5,0,0,0,0,0,0,1};
@@ -179,7 +180,7 @@ static switch_bool_t switch_amr_pack_oa(unsigned char *shift_buf, int n)
return SWITCH_TRUE;
}
-static switch_bool_t switch_amr_info(unsigned char *encoded_buf, int encoded_data_len, int payload_format, char *print_text)
+static switch_bool_t switch_amr_info(switch_codec_t *codec, unsigned char *encoded_buf, int encoded_data_len, int payload_format, char *print_text)
{
uint8_t *tocs;
int framesz, index, not_last_frame, q, ft;
@@ -196,7 +197,7 @@ static switch_bool_t switch_amr_info(unsigned char *encoded_buf, int encoded_dat
tocs = encoded_buf;
index = (tocs[0] >> 3) & 0x0f;
if (index > SWITCH_AMR_MODES && index != 0xf) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "AMR decoder (OA): Invalid Table Of Contents (TOC): 0x%x\n", index);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), SWITCH_LOG_ERROR, "AMR decoder (OA): Invalid Table Of Contents (TOC): 0x%x\n", index);
return SWITCH_FALSE;
}
framesz = switch_amr_frame_sizes[index];
@@ -216,15 +217,15 @@ static switch_bool_t switch_amr_info(unsigned char *encoded_buf, int encoded_dat
ft &= ~(1 << 5); /* Frame Type */
index = (shift_tocs[0] >> 3) & 0x0f;
if (index > SWITCH_AMR_MODES && index != 0xf) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "AMR decoder (BE): Invalid Table Of Contents (TOC): 0x%x\n", index);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), SWITCH_LOG_ERROR, "AMR decoder (BE): Invalid Table Of Contents (TOC): 0x%x\n", index);
return SWITCH_FALSE;
}
framesz = switch_amr_frame_sizes[index];
}
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s (%s): FT: [0x%x] Q: [0x%x] Frame flag: [%d]\n",
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), SWITCH_LOG_DEBUG, "%s (%s): FT: [0x%x] Q: [0x%x] Frame flag: [%d]\n",
print_text, payload_format ? "OA":"BE", ft, q, not_last_frame);
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s (%s): AMR encoded voice payload sz: [%d] : | encoded_data_len: [%d]\n",
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), SWITCH_LOG_DEBUG, "%s (%s): AMR encoded voice payload sz: [%d] : | encoded_data_len: [%d]\n",
print_text, payload_format ? "OA":"BE", framesz, encoded_data_len);
return SWITCH_TRUE;
@@ -276,8 +277,11 @@ static switch_status_t switch_amr_init(switch_codec_t *codec, switch_codec_flag_
* bandwidth-efficient operation is employed."
*
*/
- switch_clear_flag(context, AMR_OPT_OCTET_ALIGN);
-
+ if (!globals.force_oa) {
+ switch_clear_flag(context, AMR_OPT_OCTET_ALIGN);
+ } else {
+ switch_set_flag(context, AMR_OPT_OCTET_ALIGN);
+ }
if (codec->fmtp_in) {
argc = switch_separate_string(codec->fmtp_in, ';', argv, (sizeof(argv) / sizeof(argv[0])));
for (x = 0; x < argc; x++) {
@@ -452,7 +456,7 @@ static switch_status_t switch_amr_encode(switch_codec_t *codec,
}
if (globals.debug) {
- switch_amr_info(shift_buf, *encoded_data_len, switch_test_flag(context, AMR_OPT_OCTET_ALIGN) ? 1 : 0, "AMR encoder");
+ switch_amr_info(codec, shift_buf, *encoded_data_len, switch_test_flag(context, AMR_OPT_OCTET_ALIGN) ? 1 : 0, "AMR encoder");
}
return SWITCH_STATUS_SUCCESS;
@@ -479,7 +483,7 @@ static switch_status_t switch_amr_decode(switch_codec_t *codec,
}
if (globals.debug) {
- switch_amr_info(buf, encoded_data_len, switch_test_flag(context, AMR_OPT_OCTET_ALIGN) ? 1 : 0, "AMR decoder");
+ switch_amr_info(codec, buf, encoded_data_len, switch_test_flag(context, AMR_OPT_OCTET_ALIGN) ? 1 : 0, "AMR decoder");
}
if (switch_test_flag(context, AMR_OPT_OCTET_ALIGN)) {
@@ -643,6 +647,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_amr_load)
if (!strcasecmp(var, "adjust-bitrate")) {
globals.adjust_bitrate = (switch_byte_t) atoi(val);
}
+ if (!strcasecmp(var, "force-oa")) {
+ globals.force_oa = (switch_byte_t) atoi(val);
+ }
}
}
}
diff --git a/src/mod/databases/mod_pgsql/mod_pgsql.c b/src/mod/databases/mod_pgsql/mod_pgsql.c
index a534594548..f7c2983f91 100644
--- a/src/mod/databases/mod_pgsql/mod_pgsql.c
+++ b/src/mod/databases/mod_pgsql/mod_pgsql.c
@@ -113,6 +113,7 @@ static int db_is_up(switch_pgsql_handle_t *handle)
int max_tries = DEFAULT_PGSQL_RETRIES;
int code = 0;
int recon = 0;
+ switch_byte_t sanity = 255;
if (handle) {
max_tries = handle->num_retries;
@@ -132,10 +133,24 @@ top:
}
/* Try a non-blocking read on the connection to gobble up any EOF from a closed connection and mark the connection BAD if it is closed. */
- PQconsumeInput(handle->con);
+ while (--sanity > 0)
+ {
+ if (PQisBusy(handle->con)) {
+ PQconsumeInput(handle->con);
+ switch_yield(1);
+ continue;
+ }
+ break;
+ }
+
+ if (!sanity) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Can not check DB Connection status: sanity = 0. Reconnecting...\n");
+ goto reset;
+ }
if (PQstatus(handle->con) == CONNECTION_BAD) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "PQstatus returned bad connection; reconnecting...\n");
+reset:
handle->state = SWITCH_PGSQL_STATE_ERROR;
PQreset(handle->con);
if (PQstatus(handle->con) == CONNECTION_BAD) {
@@ -358,6 +373,20 @@ switch_status_t pgsql_handle_connect(switch_pgsql_handle_t *handle)
return SWITCH_STATUS_FALSE;
}
+ if (PQsetnonblocking(handle->con, 1) == -1) {
+ char *err_str;
+
+ if ((err_str = pgsql_handle_get_error(handle))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", err_str);
+ switch_safe_free(err_str);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to setup socket for the database [%s]\n", handle->dsn);
+ pgsql_handle_disconnect(handle);
+ }
+
+ return SWITCH_STATUS_FALSE;
+ }
+
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Connected to [%s]\n", handle->dsn);
handle->state = SWITCH_PGSQL_STATE_CONNECTED;
handle->sock = PQsocket(handle->con);
@@ -486,15 +515,14 @@ error:
err_str = pgsql_handle_get_error(handle);
if (zstr(err_str)) {
- if (zstr(er)) {
+ switch_safe_free(err_str);
+ if (!er) {
err_str = strdup((char *)"SQL ERROR!");
} else {
err_str = er;
}
} else {
- if (!zstr(er)) {
- free(er);
- }
+ switch_safe_free(er);
}
if (err_str) {
@@ -622,89 +650,91 @@ switch_status_t pgsql_next_result_timed(switch_pgsql_handle_t *handle, switch_pg
return SWITCH_STATUS_FALSE;
}
- /* Try to consume input that might be waiting right away */
- if (PQconsumeInput(handle->con)) {
- /* And check to see if we have a full result ready for reading */
- if (PQisBusy(handle->con)) {
+ if (PQisBusy(handle->con)) {
+ /* Try to consume input that might be waiting right away */
+ if (PQconsumeInput(handle->con)) {
+ /* And check to see if we have a full result ready for reading */
+ if (PQisBusy(handle->con)) {
- /* Wait for a result to become available, up to msec milliseconds */
- start = switch_micro_time_now();
- while ((ctime = switch_micro_time_now()) - start <= usec) {
- switch_time_t wait_time = (usec - (ctime - start)) / 1000;
- /* Wait for the PostgreSQL socket to be ready for data reads. */
+ /* Wait for a result to become available, up to msec milliseconds */
+ start = switch_micro_time_now();
+ while ((ctime = switch_micro_time_now()) - start <= usec) {
+ switch_time_t wait_time = (usec - (ctime - start)) / 1000;
+ /* Wait for the PostgreSQL socket to be ready for data reads. */
#ifndef _WIN32
- fds[0].fd = handle->sock;
- fds[0].events |= POLLIN;
- fds[0].events |= POLLERR;
- fds[0].events |= POLLNVAL;
- fds[0].events |= POLLHUP;
- fds[0].events |= POLLPRI;
- fds[0].events |= POLLRDNORM;
- fds[0].events |= POLLRDBAND;
+ fds[0].fd = handle->sock;
+ fds[0].events |= POLLIN;
+ fds[0].events |= POLLERR;
+ fds[0].events |= POLLNVAL;
+ fds[0].events |= POLLHUP;
+ fds[0].events |= POLLPRI;
+ fds[0].events |= POLLRDNORM;
+ fds[0].events |= POLLRDBAND;
- poll_res = poll(&fds[0], 1, wait_time);
+ poll_res = poll(&fds[0], 1, wait_time);
#else
- struct timeval wait = { (long)wait_time * 1000, 0 };
- FD_ZERO(&rs);
- FD_SET(handle->sock, &rs);
- FD_ZERO(&es);
- FD_SET(handle->sock, &es);
- poll_res = select(0, &rs, 0, &es, &wait);
+ struct timeval wait = { (long)wait_time * 1000, 0 };
+ FD_ZERO(&rs);
+ FD_SET(handle->sock, &rs);
+ FD_ZERO(&es);
+ FD_SET(handle->sock, &es);
+ poll_res = select(0, &rs, 0, &es, &wait);
#endif
- if (poll_res > 0) {
+ if (poll_res > 0) {
#ifndef _WIN32
- if (fds[0].revents & POLLHUP || fds[0].revents & POLLNVAL) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "PGSQL socket closed or invalid while waiting for result for query (%s)\n", handle->sql);
- goto error;
- } else if (fds[0].revents & POLLERR) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Poll error trying to read PGSQL socket for query (%s)\n", handle->sql);
- goto error;
- } else if (fds[0].revents & POLLIN || fds[0].revents & POLLPRI || fds[0].revents & POLLRDNORM || fds[0].revents & POLLRDBAND) {
+ if (fds[0].revents & POLLHUP || fds[0].revents & POLLNVAL) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "PGSQL socket closed or invalid while waiting for result for query (%s)\n", handle->sql);
+ goto error;
+ } else if (fds[0].revents & POLLERR) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Poll error trying to read PGSQL socket for query (%s)\n", handle->sql);
+ goto error;
+ } else if (fds[0].revents & POLLIN || fds[0].revents & POLLPRI || fds[0].revents & POLLRDNORM || fds[0].revents & POLLRDBAND) {
#else
- if (FD_ISSET(handle->sock, &rs)) {
+ if (FD_ISSET(handle->sock, &rs)) {
#endif
- /* Then try to consume any input waiting. */
- if (PQconsumeInput(handle->con)) {
- if (PQstatus(handle->con) == CONNECTION_BAD) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Connection terminated while waiting for result.\n");
- handle->state = SWITCH_PGSQL_STATE_ERROR;
+ /* Then try to consume any input waiting. */
+ if (PQconsumeInput(handle->con)) {
+ if (PQstatus(handle->con) == CONNECTION_BAD) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Connection terminated while waiting for result.\n");
+ handle->state = SWITCH_PGSQL_STATE_ERROR;
+ goto error;
+ }
+
+ /* And check to see if we have a full result ready for reading */
+ if (!PQisBusy(handle->con)) {
+ /* If we can pull a full result without blocking, then break this loop */
+ break;
+ }
+ } else {
+ /* If we had an error trying to consume input, report it and cancel the query. */
+ err_str = pgsql_handle_get_error(handle);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "An error occurred trying to consume input for query (%s): %s\n", handle->sql, err_str);
+ switch_safe_free(err_str);
+ pgsql_cancel(handle);
goto error;
}
-
- /* And check to see if we have a full result ready for reading */
- if (!PQisBusy(handle->con)) {
- /* If we can pull a full result without blocking, then break this loop */
- break;
- }
- } else {
- /* If we had an error trying to consume input, report it and cancel the query. */
- err_str = pgsql_handle_get_error(handle);
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "An error occurred trying to consume input for query (%s): %s\n", handle->sql, err_str);
- switch_safe_free(err_str);
- pgsql_cancel(handle);
- goto error;
}
+ } else if (poll_res == -1) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Poll failed trying to read PGSQL socket for query (%s)\n", handle->sql);
+ goto error;
}
- } else if (poll_res == -1) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Poll failed trying to read PGSQL socket for query (%s)\n", handle->sql);
+ }
+
+ /* If we broke the loop above because of a timeout, report that and cancel the query. */
+ if (ctime - start > usec) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Query (%s) took too long to complete or database not responding.\n", handle->sql);
+ pgsql_cancel(handle);
goto error;
}
}
-
- /* If we broke the loop above because of a timeout, report that and cancel the query. */
- if (ctime - start > usec) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Query (%s) took too long to complete or database not responding.\n", handle->sql);
- pgsql_cancel(handle);
- goto error;
- }
+ } else {
+ /* If we had an error trying to consume input, report it and cancel the query. */
+ err_str = pgsql_handle_get_error(handle);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "An error occurred trying to consume input for query (%s): %s\n", handle->sql, err_str);
+ switch_safe_free(err_str);
+ /* pgsql_cancel(handle); */
+ goto error;
}
- } else {
- /* If we had an error trying to consume input, report it and cancel the query. */
- err_str = pgsql_handle_get_error(handle);
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "An error occurred trying to consume input for query (%s): %s\n", handle->sql, err_str);
- switch_safe_free(err_str);
- /* pgsql_cancel(handle); */
- goto error;
}
/* At this point, we know we can read a full result without blocking. */
diff --git a/src/mod/endpoints/mod_loopback/mod_loopback.c b/src/mod/endpoints/mod_loopback/mod_loopback.c
index 88400fcaf6..6fa0d4fbd4 100644
--- a/src/mod/endpoints/mod_loopback/mod_loopback.c
+++ b/src/mod/endpoints/mod_loopback/mod_loopback.c
@@ -1700,6 +1700,7 @@ static switch_call_cause_t null_channel_outgoing_channel(switch_core_session_t *
if (hangup_cause || !strncmp(caller_profile->destination_number, "cause-", 6)) {
if (!hangup_cause) hangup_cause = caller_profile->destination_number + 6;
+ switch_core_session_destroy(new_session);
return switch_channel_str2cause(hangup_cause);
}
diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c
index e236b09a38..ecc925cf78 100644
--- a/src/mod/endpoints/mod_sofia/mod_sofia.c
+++ b/src/mod/endpoints/mod_sofia/mod_sofia.c
@@ -2740,6 +2740,7 @@ const char *sofia_state_names[] = {
"FAIL_WAIT",
"EXPIRED",
"NOREG",
+ "DOWN",
"TIMEOUT",
NULL
};
@@ -3653,15 +3654,21 @@ static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t
if (!strcasecmp(gname, "all")) {
for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
- gateway_ptr->retry = 0;
- gateway_ptr->state = REG_STATE_UNREGED;
+ if (gateway_ptr->state != REG_STATE_NOREG) {
+ gateway_ptr->retry = 0;
+ gateway_ptr->state = REG_STATE_UNREGED;
+ }
}
stream->write_function(stream, "+OK\n");
} else if ((gateway_ptr = sofia_reg_find_gateway(gname))) {
- gateway_ptr->retry = 0;
- gateway_ptr->state = REG_STATE_UNREGED;
- stream->write_function(stream, "+OK\n");
- sofia_reg_release_gateway(gateway_ptr);
+ if (gateway_ptr->state != REG_STATE_NOREG) {
+ gateway_ptr->retry = 0;
+ gateway_ptr->state = REG_STATE_UNREGED;
+ stream->write_function(stream, "+OK\n");
+ sofia_reg_release_gateway(gateway_ptr);
+ } else {
+ stream->write_function(stream, "-ERR NOREG gateway [%s] can't be registered!\n", gname);
+ }
} else {
stream->write_function(stream, "Invalid gateway!\n");
}
@@ -3680,15 +3687,21 @@ static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t
if (!strcasecmp(gname, "all")) {
for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
- gateway_ptr->retry = 0;
- gateway_ptr->state = REG_STATE_UNREGISTER;
+ if (gateway_ptr->state != REG_STATE_NOREG) {
+ gateway_ptr->retry = 0;
+ gateway_ptr->state = REG_STATE_UNREGISTER;
+ }
}
stream->write_function(stream, "+OK\n");
} else if ((gateway_ptr = sofia_reg_find_gateway(gname))) {
- gateway_ptr->retry = 0;
- gateway_ptr->state = REG_STATE_UNREGISTER;
- stream->write_function(stream, "+OK\n");
- sofia_reg_release_gateway(gateway_ptr);
+ if (gateway_ptr->state != REG_STATE_NOREG) {
+ gateway_ptr->retry = 0;
+ gateway_ptr->state = REG_STATE_UNREGISTER;
+ stream->write_function(stream, "+OK\n");
+ sofia_reg_release_gateway(gateway_ptr);
+ } else {
+ stream->write_function(stream, "-ERR NOREG gateway [%s] can't be unregistered!\n", gname);
+ }
} else {
stream->write_function(stream, "Invalid gateway!\n");
}
@@ -5070,7 +5083,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
if (gateway_ptr && gateway_ptr->ob_vars) {
switch_event_header_t *hp;
for (hp = gateway_ptr->ob_vars->headers; hp; hp = hp->next) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s setting variable [%s]=[%s]\n",
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(nsession), SWITCH_LOG_DEBUG, "%s setting variable [%s]=[%s]\n",
switch_channel_get_name(nchannel), hp->name, hp->value);
if (!strncmp(hp->name, "p:", 2)) {
switch_channel_set_profile_var(nchannel, hp->name + 2, hp->value);
diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h
index 3249533730..d4631b02d6 100644
--- a/src/mod/endpoints/mod_sofia/mod_sofia.h
+++ b/src/mod/endpoints/mod_sofia/mod_sofia.h
@@ -432,6 +432,7 @@ typedef enum {
REG_STATE_FAIL_WAIT,
REG_STATE_EXPIRED,
REG_STATE_NOREG,
+ REG_STATE_DOWN,
REG_STATE_TIMEOUT,
REG_STATE_LAST
} reg_state_t;
diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c
index 7d8b2fe6eb..e1e6435670 100644
--- a/src/mod/endpoints/mod_sofia/sofia.c
+++ b/src/mod/endpoints/mod_sofia/sofia.c
@@ -1733,6 +1733,10 @@ static void our_sofia_event_callback(nua_event_t event,
switch_channel_set_variable(channel, "sip_call_id", sip->sip_call_id->i_id);
}
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
+ switch_channel_set_variable(channel, "dlg_req_swap_direction", "true");
+ }
+
extract_header_vars(profile, sip, session, nh);
switch_core_recovery_track(session);
sofia_set_flag(tech_pvt, TFLAG_GOT_ACK);
@@ -2278,7 +2282,7 @@ void sofia_process_dispatch_event(sofia_dispatch_event_t **dep)
profile->queued_events--;
switch_mutex_unlock(profile->flag_mutex);
- nua_handle_unref(nh);
+ if (nh) nua_handle_unref(nh);
nua_unref(nua);
}
@@ -2435,11 +2439,16 @@ void sofia_event_callback(nua_event_t event,
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "detaching session %s\n", sofia_private->uuid);
if (!zstr(tech_pvt->call_id)) {
+ char *uuid = strdup(switch_core_session_get_uuid(session));
tech_pvt->sofia_private = NULL;
tech_pvt->nh = NULL;
sofia_set_flag(tech_pvt, TFLAG_BYE);
switch_mutex_lock(profile->flag_mutex);
- switch_core_hash_insert_auto_free(profile->chat_hash, tech_pvt->call_id, strdup(switch_core_session_get_uuid(session)));
+
+ if (switch_core_hash_insert_auto_free(profile->chat_hash, tech_pvt->call_id, uuid) != SWITCH_STATUS_SUCCESS) {
+ switch_safe_free(uuid);
+ }
+
switch_mutex_unlock(profile->flag_mutex);
nua_handle_destroy(nh);
} else {
@@ -2507,7 +2516,7 @@ void sofia_event_callback(nua_event_t event,
de = su_alloc(nua_handle_get_home(nh), sizeof(*de));
memset(de, 0, sizeof(*de));
nua_save_event(nua, de->event);
- de->nh = nua_handle_ref(nh);
+ de->nh = nh ? nua_handle_ref(nh) : NULL;
de->data = nua_event_data(de->event);
de->sip = sip_object(de->data->e_msg);
de->profile = profile;
@@ -3171,7 +3180,6 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
if (!sofia_glue_init_sql(profile)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open SQL Database [%s]!\n", profile->name);
sofia_profile_start_failure(profile, profile->name);
- sofia_glue_del_profile(profile);
goto end;
}
@@ -3323,7 +3331,6 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
}
sofia_profile_start_failure(profile, profile->name);
- sofia_glue_del_profile(profile);
goto end;
}
@@ -3491,6 +3498,20 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
}
}
+ /* Do gateway cleanups */
+ sofia_glue_del_every_gateway(profile);
+ sofia_reg_check_gateway(profile, switch_epoch_time_now(NULL));
+ sofia_sub_check_gateway(profile, switch_epoch_time_now(NULL));
+ sofia_glue_fire_events(profile);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Waiting for worker thread\n");
+
+ if (worker_thread) {
+ switch_thread_join(&st, worker_thread);
+ }
+ else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: Sofia worker thead failed to start\n");
+ }
sofia_reg_unregister(profile);
nua_shutdown(profile->nua);
@@ -3505,13 +3526,6 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
sofia_clear_pflag_locked(profile, PFLAG_RUNNING);
sofia_clear_pflag_locked(profile, PFLAG_SHUTDOWN);
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Waiting for worker thread\n");
-
- if ( worker_thread ) {
- switch_thread_join(&st, worker_thread);
- } else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: Sofia worker thead failed to start\n");
- }
sanity = 4;
while (profile->inuse) {
@@ -3560,6 +3574,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
}
}
+ end:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock %s\n", profile->name);
switch_thread_rwlock_wrlock(profile->rwlock);
@@ -3581,7 +3596,6 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
sofia_profile_destroy(profile);
- end:
switch_mutex_lock(mod_sofia_globals.mutex);
mod_sofia_globals.threads--;
switch_mutex_unlock(mod_sofia_globals.mutex);
@@ -6502,7 +6516,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
const char *uuid;
switch_core_session_t *other_session;
private_object_t *tech_pvt = switch_core_session_get_private(session);
- char network_ip[80];
+ char network_ip[80] = "";
int network_port = 0;
switch_caller_profile_t *caller_profile = NULL;
int has_t38 = 0;
@@ -7106,8 +7120,13 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
+ switch_channel_set_variable(channel, "dlg_req_swap_direction", "true");
+ }
+
extract_header_vars(profile, sip, session, nh);
extract_vars(profile, sip, session);
+ switch_core_recovery_track(session);
switch_channel_clear_flag(tech_pvt->channel, CF_RECOVERING);
}
@@ -7911,7 +7930,9 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
//switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 0);
sofia_set_flag(tech_pvt, TFLAG_LATE_NEGOTIATION);
//Moves into CS_INIT so call moves forward into the dialplan
- switch_channel_set_state(channel, CS_INIT);
+ if (switch_channel_get_state(channel) == CS_NEW) {
+ switch_channel_set_state(channel, CS_INIT);
+ }
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "No SDP in INVITE and 3pcc not enabled, hanging up.\n");
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "3PCC DISABLED");
@@ -10891,9 +10912,10 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia
if (switch_channel_get_variable(channel, "sip_to_uri")) {
const char *ipv6;
const char *tmp, *at, *url = NULL;
-
+ const char *tmp_user = switch_channel_get_variable(channel, "sip_to_user");
+
+ user = switch_core_session_url_encode(session, tmp_user);
host = switch_channel_get_variable(channel, "sip_to_host");
- user = switch_channel_get_variable(channel, "sip_to_user");
switch_channel_set_variable(channel, "sip_to_comment", sip->sip_to->a_comment);
diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c
index a49bd998a9..0c0035412f 100644
--- a/src/mod/endpoints/mod_sofia/sofia_glue.c
+++ b/src/mod/endpoints/mod_sofia/sofia_glue.c
@@ -1211,7 +1211,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
}
sofia_glue_get_url_from_contact(rpid_domain, 0);
- if ((rpid_domain = strrchr(rpid_domain, '@'))) {
+ if (rpid_domain && (rpid_domain = strrchr(rpid_domain, '@'))) {
rpid_domain++;
if ((p = strchr(rpid_domain, ';'))) {
*p = '\0';
@@ -2235,7 +2235,7 @@ int sofia_recover_callback(switch_core_session_t *session)
const char *rr;
int r = 0;
const char *profile_name = switch_channel_get_variable_dup(channel, "recovery_profile_name", SWITCH_FALSE, -1);
-
+ int swap = switch_channel_var_true(channel, "dlg_req_swap_direction");
if (zstr(profile_name)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Missing profile\n");
@@ -2275,10 +2275,9 @@ int sofia_recover_callback(switch_core_session_t *session)
rr = switch_channel_get_variable(channel, "sip_invite_record_route");
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
- int break_rfc = switch_true(switch_channel_get_variable(channel, "sip_recovery_break_rfc"));
tech_pvt->dest = switch_core_session_sprintf(session, "sip:%s", switch_channel_get_variable(channel, "sip_req_uri"));
- switch_channel_set_variable(channel, "sip_handle_full_from", switch_channel_get_variable(channel, break_rfc ? "sip_full_to" : "sip_full_from"));
- switch_channel_set_variable(channel, "sip_handle_full_to", switch_channel_get_variable(channel, break_rfc ? "sip_full_from" : "sip_full_to"));
+ switch_channel_set_variable(channel, "sip_handle_full_from", switch_channel_get_variable(channel, swap ? "sip_full_to" : "sip_full_from"));
+ switch_channel_set_variable(channel, "sip_handle_full_to", switch_channel_get_variable(channel, swap ? "sip_full_from" : "sip_full_to"));
} else {
const char *contact_params = switch_channel_get_variable(channel, "sip_contact_params");
const char *contact_uri = switch_channel_get_variable(channel, "sip_contact_uri");
@@ -2297,11 +2296,11 @@ int sofia_recover_callback(switch_core_session_t *session)
tech_pvt->dest = switch_core_session_sprintf(session, "sip:%s", switch_channel_get_variable(channel, "sip_from_uri"));
if (!switch_channel_get_variable_dup(channel, "sip_handle_full_from", SWITCH_FALSE, -1)) {
- switch_channel_set_variable(channel, "sip_handle_full_from", switch_channel_get_variable(channel, "sip_full_to"));
+ switch_channel_set_variable(channel, "sip_handle_full_from", switch_channel_get_variable(channel, swap ? "sip_full_from" :"sip_full_to"));
}
if (!switch_channel_get_variable_dup(channel, "sip_handle_full_to", SWITCH_FALSE, -1)) {
- switch_channel_set_variable(channel, "sip_handle_full_to", switch_channel_get_variable(channel, "sip_full_from"));
+ switch_channel_set_variable(channel, "sip_handle_full_to", switch_channel_get_variable(channel, swap ? "sip_full_to" : "sip_full_from"));
}
}
diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c
index e1c31c99c8..e27b0495ff 100644
--- a/src/mod/endpoints/mod_sofia/sofia_presence.c
+++ b/src/mod/endpoints/mod_sofia/sofia_presence.c
@@ -4284,7 +4284,11 @@ void sofia_presence_handle_sip_i_subscribe(int status,
}
}
}
+
+ switch_xml_free(xml);
}
+
+ switch_safe_free(pd_dup);
}
switch_event_fire(&event);
} else if (!strcasecmp(event, "message-summary")) {
diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c
index 81d2ffdabd..22997cecae 100644
--- a/src/mod/endpoints/mod_sofia/sofia_reg.c
+++ b/src/mod/endpoints/mod_sofia/sofia_reg.c
@@ -323,7 +323,7 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now)
free(pkey);
}
- if (gateway_ptr->state == REG_STATE_NOREG) {
+ if (gateway_ptr->state == REG_STATE_NOREG || gateway_ptr->state == REG_STATE_DOWN) {
if (last) {
last->next = gateway_ptr->next;
@@ -356,7 +356,7 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now)
char *user_via = NULL;
char *register_host = NULL;
- if (!now) {
+ if (!now && ostate != REG_STATE_NOREG) {
gateway_ptr->state = ostate = REG_STATE_UNREGED;
gateway_ptr->expires_str = "0";
}
@@ -398,6 +398,7 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now)
}
switch (ostate) {
+ case REG_STATE_DOWN:
case REG_STATE_NOREG:
if (!gateway_ptr->ping && !gateway_ptr->pinging && gateway_ptr->status != SOFIA_GATEWAY_UP) {
gateway_ptr->status = SOFIA_GATEWAY_UP;
@@ -432,7 +433,7 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now)
case REG_STATE_UNREGISTER:
sofia_reg_kill_reg(gateway_ptr);
- gateway_ptr->state = REG_STATE_NOREG;
+ gateway_ptr->state = REG_STATE_DOWN;
gateway_ptr->status = SOFIA_GATEWAY_DOWN;
break;
case REG_STATE_UNREGED:
@@ -1932,7 +1933,6 @@ uint8_t sofia_reg_handle_register_token(nua_t *nua, sofia_profile_t *profile, nu
switch_mutex_lock(profile->flag_mutex);
hnh = switch_core_hash_find(profile->reg_nh_hash, key);
- switch_mutex_unlock(profile->flag_mutex);
if (!hnh) {
if (!(sofia_private = su_alloc(nua_handle_get_home(nh), sizeof(*sofia_private)))) {
@@ -1953,6 +1953,8 @@ uint8_t sofia_reg_handle_register_token(nua_t *nua, sofia_profile_t *profile, nu
nua_handle_ref(nh);
switch_core_hash_insert(profile->reg_nh_hash, key, nh);
}
+
+ switch_mutex_unlock(profile->flag_mutex);
}
diff --git a/src/mod/event_handlers/mod_snmp/subagent.c b/src/mod/event_handlers/mod_snmp/subagent.c
index dd29939e6a..cd61955461 100644
--- a/src/mod/event_handlers/mod_snmp/subagent.c
+++ b/src/mod/event_handlers/mod_snmp/subagent.c
@@ -79,22 +79,22 @@ static int channelList_callback(void *pArg, int argc, char **argv, char **column
row->data = entry;
entry->idx = idx++;
- strncpy(entry->uuid, switch_str_nil(argv[0]), sizeof(entry->uuid));
- strncpy(entry->direction, switch_str_nil(argv[1]), sizeof(entry->direction));
+ snprintf(entry->uuid, sizeof(entry->uuid), "%s", switch_str_nil(argv[0]));
+ snprintf(entry->direction, sizeof(entry->direction), "%s", switch_str_nil(argv[1]));
entry->created_epoch = atoi(argv[3]);
- strncpy(entry->name, switch_str_nil(argv[4]), sizeof(entry->name));
- strncpy(entry->state, switch_str_nil(argv[5]), sizeof(entry->state));
- strncpy(entry->cid_name, switch_str_nil(argv[6]), sizeof(entry->cid_name));
- strncpy(entry->cid_num, switch_str_nil(argv[7]), sizeof(entry->cid_num));
- strncpy(entry->dest, switch_str_nil(argv[9]), sizeof(entry->dest));
- strncpy(entry->application, switch_str_nil(argv[10]), sizeof(entry->application));
- strncpy(entry->application_data, switch_str_nil(argv[11]), sizeof(entry->application_data));
- strncpy(entry->dialplan, switch_str_nil(argv[12]), sizeof(entry->dialplan));
- strncpy(entry->context, switch_str_nil(argv[13]), sizeof(entry->context));
- strncpy(entry->read_codec, switch_str_nil(argv[14]), sizeof(entry->read_codec));
+ snprintf(entry->name, sizeof(entry->name), "%s", switch_str_nil(argv[4]));
+ snprintf(entry->state, sizeof(entry->state), "%s", switch_str_nil(argv[5]));
+ snprintf(entry->cid_name, sizeof(entry->cid_name), "%s", switch_str_nil(argv[6]));
+ snprintf(entry->cid_num, sizeof(entry->cid_num), "%s", switch_str_nil(argv[7]));
+ snprintf(entry->dest, sizeof(entry->dest), "%s", switch_str_nil(argv[9]));
+ snprintf(entry->application, sizeof(entry->application), "%s", switch_str_nil(argv[10]));
+ snprintf(entry->application_data, sizeof(entry->application_data), "%s", switch_str_nil(argv[11]));
+ snprintf(entry->dialplan, sizeof(entry->dialplan), "%s", switch_str_nil(argv[12]));
+ snprintf(entry->context, sizeof(entry->context), "%s", switch_str_nil(argv[13]));
+ snprintf(entry->read_codec, sizeof(entry->read_codec), "%s", switch_str_nil(argv[14]));
entry->read_rate = atoi(switch_str_nil(argv[15]));
entry->read_bitrate = atoi(switch_str_nil(argv[16]));
- strncpy(entry->write_codec, switch_str_nil(argv[17]), sizeof(entry->write_codec));
+ snprintf(entry->write_codec, sizeof(entry->write_codec), "%s", switch_str_nil(argv[17]));
entry->write_rate = atoi(switch_str_nil(argv[18]));
entry->write_bitrate = atoi(switch_str_nil(argv[19]));
@@ -186,7 +186,7 @@ int handle_identity(netsnmp_mib_handler *handler, netsnmp_handler_registration *
snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR, (u_char *) &version, strlen(version));
break;
case ID_UUID:
- strncpy(uuid, switch_core_get_uuid(), sizeof(uuid));
+ snprintf(uuid, sizeof(uuid), "%s", switch_core_get_uuid());
snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR, (u_char *) &uuid, strlen(uuid));
break;
default:
diff --git a/src/mod/formats/mod_shout/mod_shout.c b/src/mod/formats/mod_shout/mod_shout.c
index 6799b38391..14cba068d3 100644
--- a/src/mod/formats/mod_shout/mod_shout.c
+++ b/src/mod/formats/mod_shout/mod_shout.c
@@ -1333,8 +1333,6 @@ void do_telecast(switch_stream_handle_t *stream)
end:
- switch_safe_free(uuid);
-
if (gfp) {
lame_close(gfp);
gfp = NULL;
@@ -1350,6 +1348,8 @@ void do_telecast(switch_stream_handle_t *stream)
switch_core_session_rwunlock(tsession);
}
+
+ switch_safe_free(uuid);
}
void do_broadcast(switch_stream_handle_t *stream)
diff --git a/src/mod/formats/mod_sndfile/mod_sndfile.c b/src/mod/formats/mod_sndfile/mod_sndfile.c
index 5d2962a8c4..0977a4950b 100644
--- a/src/mod/formats/mod_sndfile/mod_sndfile.c
+++ b/src/mod/formats/mod_sndfile/mod_sndfile.c
@@ -309,6 +309,12 @@ static switch_status_t sndfile_file_open(switch_file_handle_t *handle, const cha
sf_command(context->handle, SFC_FILE_TRUNCATE, &frames, sizeof(frames));
}
+ /*
+ http://www.mega-nerd.com/libsndfile/api.html#note2
+ */
+ if (switch_test_flag(handle, SWITCH_FILE_DATA_SHORT)) {
+ sf_command(context->handle, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);
+ }
end:
diff --git a/src/switch_channel.c b/src/switch_channel.c
index c5c61d43ae..09a0697f9f 100644
--- a/src/switch_channel.c
+++ b/src/switch_channel.c
@@ -4175,6 +4175,7 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables_check(switch_channel_t *c
if (!switch_core_test_flag(SCF_API_EXPANSION) || (api_list && !switch_event_check_permission_list(api_list, vname))) {
func_val = NULL;
sub_val = "";
+ free(stream.data);
} else {
if (switch_api_execute(vname, vval, channel->session, &stream) == SWITCH_STATUS_SUCCESS) {
func_val = stream.data;
diff --git a/src/switch_core_io.c b/src/switch_core_io.c
index 22d0474e3e..1d5ff7510b 100644
--- a/src/switch_core_io.c
+++ b/src/switch_core_io.c
@@ -227,7 +227,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
switch_assert((*frame)->codec != NULL);
- if (!(session->read_codec && (*frame)->codec && (*frame)->codec->implementation) && switch_core_codec_ready((*frame)->codec)) {
+ if (!switch_core_codec_ready(session->read_codec) || !switch_core_codec_ready((*frame)->codec)) {
status = SWITCH_STATUS_FALSE;
goto done;
}
diff --git a/src/switch_core_media.c b/src/switch_core_media.c
index 1449724782..23e77047b9 100644
--- a/src/switch_core_media.c
+++ b/src/switch_core_media.c
@@ -3587,24 +3587,27 @@ static void switch_core_session_parse_codec_settings(switch_core_session_t *sess
//?
SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_session_t *session, int force)
{
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_media_handle_t *smh;
switch_rtp_engine_t *v_engine;
switch_assert(session);
+ switch_mutex_lock(session->codec_init_mutex);
+
if (!(smh = session->media_handle)) {
- return SWITCH_STATUS_FALSE;
+ switch_goto_status(SWITCH_STATUS_FALSE, end);
}
v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
if (!v_engine->codec_negotiated) {
- return SWITCH_STATUS_FALSE;
+ switch_goto_status(SWITCH_STATUS_FALSE, end);
}
if (v_engine->read_codec.implementation && switch_core_codec_ready(&v_engine->read_codec)) {
if (!force) {
- return SWITCH_STATUS_SUCCESS;
+ switch_goto_status(SWITCH_STATUS_SUCCESS, end);
}
if (strcasecmp(v_engine->read_codec.implementation->iananame, v_engine->cur_payload_map->rm_encoding) ||
v_engine->read_codec.implementation->samples_per_second != v_engine->cur_payload_map->rm_rate) {
@@ -3616,7 +3619,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_se
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Already using %s\n",
v_engine->read_codec.implementation->iananame);
- return SWITCH_STATUS_SUCCESS;
+ switch_goto_status(SWITCH_STATUS_SUCCESS, end);
}
}
@@ -3632,7 +3635,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_se
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
&v_engine->codec_settings, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n");
- return SWITCH_STATUS_FALSE;
+ switch_goto_status(SWITCH_STATUS_FALSE, end);
} else {
if (switch_core_codec_init(&v_engine->write_codec,
v_engine->cur_payload_map->rm_encoding,
@@ -3644,7 +3647,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_se
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
&v_engine->codec_settings, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n");
- return SWITCH_STATUS_FALSE;
+ switch_goto_status(SWITCH_STATUS_FALSE, end);
} else {
v_engine->read_frame.rate = v_engine->cur_payload_map->rm_rate;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set VIDEO Codec %s %s/%ld %d ms\n",
@@ -3685,7 +3688,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_se
switch_channel_set_variable_printf(session->channel, "rtp_use_video_codec_ptime", "%d", 0);
}
}
- return SWITCH_STATUS_SUCCESS;
+
+end:
+ switch_mutex_unlock(session->codec_init_mutex);
+
+ return status;
}
@@ -3698,9 +3705,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_codec(switch_core_session_
switch_rtp_engine_t *a_engine;
switch_assert(session);
+
+ switch_mutex_lock(session->codec_init_mutex);
if (!(smh = session->media_handle)) {
- return SWITCH_STATUS_FALSE;
+ switch_goto_status(SWITCH_STATUS_FALSE, end);
}
a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
@@ -3860,10 +3869,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_codec(switch_core_session_
end:
if (resetting) {
- switch_core_session_unlock_codec_write(session);
- switch_core_session_unlock_codec_read(session);
+ switch_channel_execute_on(session->channel, "execute_on_audio_change");
+ switch_core_session_unlock_codec_write(session);
+ switch_core_session_unlock_codec_read(session);
}
+ switch_mutex_unlock(session->codec_init_mutex);
+
return status;
}
static void clear_ice(switch_core_session_t *session, switch_media_type_t type)
@@ -4814,11 +4826,7 @@ static void switch_core_media_set_rmode(switch_core_session_t *session, switch_m
if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
- if (!switch_channel_media_up(session->channel) && sdp_type == SDP_TYPE_REQUEST) {
- engine->rmode = switch_core_session_remote_media_flow(other_session, type);
-
- media_flow_get_mode(engine->rmode, &rmode_str, &opp_rmode);
- } else if (sdp_type == SDP_TYPE_RESPONSE && (switch_channel_test_flag(other_session->channel, CF_REINVITE) || switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND)) {
+ if (sdp_type == SDP_TYPE_RESPONSE && (switch_channel_test_flag(other_session->channel, CF_REINVITE) || switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND)) {
switch_core_media_set_smode(other_session, type, rmode, sdp_type);
}
@@ -6790,6 +6798,7 @@ static void *SWITCH_THREAD_FUNC video_write_thread(switch_thread_t *thread, void
}
if (!(smh = session->media_handle)) {
+ switch_core_session_rwunlock(session);
return NULL;
}
@@ -7300,12 +7309,14 @@ static void *SWITCH_THREAD_FUNC text_helper_thread(switch_thread_t *thread, void
return NULL;
}
- mh->ready = 1;
-
if (!(smh = session->media_handle)) {
+ switch_core_session_rwunlock(session);
+ mh->ready = -1;
return NULL;
}
+ mh->ready = 1;
+
channel = switch_core_session_get_channel(session);
if (switch_channel_var_true(session->channel, "fire_text_events")) {
@@ -7459,12 +7470,14 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi
return NULL;
}
- mh->ready = 1;
-
if (!(smh = session->media_handle)) {
+ switch_core_session_rwunlock(session);
+ mh->ready = -1;
return NULL;
}
+ mh->ready = 1;
+
channel = switch_core_session_get_channel(session);
switch_core_autobind_cpu();
@@ -9038,6 +9051,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
// goto video;
//}
+ if (!t_engine->cur_payload_map) {
+ goto text_up;
+ }
+
if (switch_channel_test_flag(session->channel, CF_TEXT_POSSIBLE) && t_engine->cur_payload_map->rm_encoding && t_engine->cur_payload_map->remote_sdp_port) {
/******************************************************************************************/
if (t_engine->rtp_session && is_reinvite) {
@@ -15496,6 +15513,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_text_frame(switch_core
t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
+ if (!t_engine || !t_engine->tf) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "text engine not available for processing\n");
+ switch_goto_status(SWITCH_STATUS_BREAK, done);
+ }
+
if (!is_msrp && switch_channel_test_cap(session->channel, CC_RTP_RTT)) {
if (frame) {
@@ -16012,7 +16034,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
session->write_codec->cur_frame = frame;
frame->codec->cur_frame = frame;
switch_assert(enc_frame->datalen <= SWITCH_RECOMMENDED_BUFFER_SIZE);
- switch_assert(session->enc_read_frame.datalen <= SWITCH_RECOMMENDED_BUFFER_SIZE);
+ switch_assert(session->enc_write_frame.datalen <= SWITCH_RECOMMENDED_BUFFER_SIZE);
status = switch_core_codec_encode(session->write_codec,
frame->codec,
enc_frame->data,
@@ -16020,7 +16042,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
session->write_impl.actual_samples_per_second,
session->enc_write_frame.data, &session->enc_write_frame.datalen, &session->enc_write_frame.rate, &flag);
- switch_assert(session->enc_read_frame.datalen <= SWITCH_RECOMMENDED_BUFFER_SIZE);
+ switch_assert(session->enc_write_frame.datalen <= SWITCH_RECOMMENDED_BUFFER_SIZE);
session->write_codec->cur_frame = NULL;
frame->codec->cur_frame = NULL;
@@ -16122,7 +16144,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
session->write_codec->cur_frame = frame;
frame->codec->cur_frame = frame;
switch_assert(enc_frame->datalen <= SWITCH_RECOMMENDED_BUFFER_SIZE);
- switch_assert(session->enc_read_frame.datalen <= SWITCH_RECOMMENDED_BUFFER_SIZE);
+ switch_assert(session->enc_write_frame.datalen <= SWITCH_RECOMMENDED_BUFFER_SIZE);
status = switch_core_codec_encode(session->write_codec,
frame->codec,
enc_frame->data,
@@ -16130,7 +16152,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
rate,
session->enc_write_frame.data, &session->enc_write_frame.datalen, &session->enc_write_frame.rate, &flag);
- switch_assert(session->enc_read_frame.datalen <= SWITCH_RECOMMENDED_BUFFER_SIZE);
+ switch_assert(session->enc_write_frame.datalen <= SWITCH_RECOMMENDED_BUFFER_SIZE);
session->write_codec->cur_frame = NULL;
frame->codec->cur_frame = NULL;
diff --git a/src/switch_core_session.c b/src/switch_core_session.c
index ca58566b2f..4dde4cba84 100644
--- a/src/switch_core_session.c
+++ b/src/switch_core_session.c
@@ -1026,8 +1026,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_queue_indication(switch_core
msg->message_id = indication;
msg->from = __FILE__;
switch_set_flag(msg, SCSMF_DYNAMIC);
- switch_core_session_queue_message(session, msg);
- return SWITCH_STATUS_SUCCESS;
+
+ if (switch_core_session_queue_message(session, msg) == SWITCH_STATUS_SUCCESS) {
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ free(msg);
}
return SWITCH_STATUS_FALSE;
@@ -2417,6 +2421,7 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request_uuid(switch_
switch_mutex_init(&session->mutex, SWITCH_MUTEX_NESTED, session->pool);
switch_mutex_init(&session->stack_count_mutex, SWITCH_MUTEX_NESTED, session->pool);
switch_mutex_init(&session->resample_mutex, SWITCH_MUTEX_NESTED, session->pool);
+ switch_mutex_init(&session->codec_init_mutex, SWITCH_MUTEX_NESTED, session->pool);
switch_mutex_init(&session->codec_read_mutex, SWITCH_MUTEX_NESTED, session->pool);
switch_mutex_init(&session->codec_write_mutex, SWITCH_MUTEX_NESTED, session->pool);
switch_mutex_init(&session->video_codec_read_mutex, SWITCH_MUTEX_NESTED, session->pool);
diff --git a/src/switch_event.c b/src/switch_event.c
index efe43e603a..709ea95e7e 100644
--- a/src/switch_event.c
+++ b/src/switch_event.c
@@ -129,6 +129,8 @@ static char *my_dup(const char *s)
#define FREE(ptr) switch_safe_free(ptr)
#endif
+static void free_header(switch_event_header_t **header);
+
/* make sure this is synced with the switch_event_types_t enum in switch_types.h
also never put any new ones before EVENT_ALL
*/
@@ -891,27 +893,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_del_header_val(switch_event_t *even
if (hp == event->last_header || !hp->next) {
event->last_header = lp;
}
- FREE(hp->name);
-
- if (hp->idx) {
- int i = 0;
-
- for (i = 0; i < hp->idx; i++) {
- FREE(hp->array[i]);
- }
- FREE(hp->array);
- }
-
- FREE(hp->value);
-
- memset(hp, 0, sizeof(*hp));
-#ifdef SWITCH_EVENT_RECYCLE
- if (switch_queue_trypush(EVENT_HEADER_RECYCLE_QUEUE, hp) != SWITCH_STATUS_SUCCESS) {
- FREE(hp);
- }
-#else
- FREE(hp);
-#endif
+ free_header(&hp);
status = SWITCH_STATUS_SUCCESS;
} else {
lp = hp;
@@ -944,6 +926,37 @@ static switch_event_header_t *new_header(const char *header_name)
}
+static void free_header(switch_event_header_t **header)
+{
+ assert(header);
+
+ if (*header) {
+ if ((*header)->idx) {
+ if (!(*header)->array) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "INDEX WITH NO ARRAY ?? [%s][%s]\n", (*header)->name, (*header)->value);
+ } else {
+ int i = 0;
+
+ for (i = 0; i < (*header)->idx; i++) {
+ FREE((*header)->array[i]);
+ }
+ FREE((*header)->array);
+ }
+ }
+
+ FREE((*header)->name);
+ FREE((*header)->value);
+
+#ifdef SWITCH_EVENT_RECYCLE
+ if (switch_queue_trypush(EVENT_HEADER_RECYCLE_QUEUE, *header) != SWITCH_STATUS_SUCCESS) {
+ FREE(*header);
+ }
+#else
+ FREE(*header);
+#endif
+ }
+}
+
SWITCH_DECLARE(int) switch_event_add_array(switch_event_t *event, const char *var, const char *val)
{
char *data;
@@ -1012,10 +1025,11 @@ static switch_status_t switch_event_base_add_header(switch_event_t *event, switc
}
if (index_ptr || (stack & SWITCH_STACK_PUSH) || (stack & SWITCH_STACK_UNSHIFT)) {
+ switch_event_header_t *tmp_header = NULL;
if (!(header = switch_event_get_header_ptr(event, header_name)) && index_ptr) {
- header = new_header(header_name);
+ tmp_header = header = new_header(header_name);
if (switch_test_flag(event, EF_UNIQ_HEADERS)) {
switch_event_del_header(event, header_name);
@@ -1049,6 +1063,8 @@ static switch_status_t switch_event_base_add_header(switch_event_t *event, switc
goto redraw;
}
+ } else if (tmp_header) {
+ free_header(&tmp_header);
}
goto end;
} else {
@@ -1266,33 +1282,7 @@ SWITCH_DECLARE(void) switch_event_destroy(switch_event_t **event)
for (hp = ep->headers; hp;) {
this = hp;
hp = hp->next;
-
- if (this->idx) {
- if (!this->array) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "INDEX WITH NO ARRAY WTF?? [%s][%s]\n", this->name, this->value);
- } else {
- int i = 0;
-
- for (i = 0; i < this->idx; i++) {
- FREE(this->array[i]);
- }
- FREE(this->array);
- }
- }
-
- FREE(this->name);
- FREE(this->value);
-
-
-#ifdef SWITCH_EVENT_RECYCLE
- if (switch_queue_trypush(EVENT_HEADER_RECYCLE_QUEUE, this) != SWITCH_STATUS_SUCCESS) {
- FREE(this);
- }
-#else
- FREE(this);
-#endif
-
-
+ free_header(&this);
}
FREE(ep->body);
FREE(ep->subclass_name);
@@ -2464,8 +2454,6 @@ SWITCH_DECLARE(char *) switch_event_expand_headers_check(switch_event_t *event,
char *expanded = NULL;
char *expanded_vname = NULL;
- SWITCH_STANDARD_STREAM(stream);
-
if ((expanded_vname = switch_event_expand_headers_check(event, (char *) vname, var_list, api_list, recur+1)) == vname) {
expanded_vname = NULL;
} else {
@@ -2482,6 +2470,7 @@ SWITCH_DECLARE(char *) switch_event_expand_headers_check(switch_event_t *event,
func_val = NULL;
sub_val = "";
} else {
+ SWITCH_STANDARD_STREAM(stream);
if (switch_api_execute(vname, vval, NULL, &stream) == SWITCH_STATUS_SUCCESS) {
func_val = stream.data;
sub_val = func_val;
diff --git a/src/switch_ivr.c b/src/switch_ivr.c
index 8d21513388..f1493a723d 100644
--- a/src/switch_ivr.c
+++ b/src/switch_ivr.c
@@ -1011,7 +1011,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session,
rate = read_impl.actual_samples_per_second;
bpf = read_impl.decoded_bytes_per_packet;
- if ((var = switch_channel_get_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE)) && (sval = atoi(var))) {
+ if (rate && (var = switch_channel_get_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE)) && (sval = atoi(var))) {
switch_core_session_get_read_impl(session, &imp);
if (switch_core_codec_init(&codec,
@@ -2192,7 +2192,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_session_transfer(switch_core_session_
extension = "service";
}
- new_profile = switch_caller_profile_clone(session, profile);
+
+ if (switch_channel_test_flag(channel, CF_REUSE_CALLER_PROFILE)){
+ new_profile = switch_channel_get_caller_profile(channel);
+ } else {
+ new_profile = switch_caller_profile_clone(session, profile);
+ }
new_profile->dialplan = switch_core_strdup(new_profile->pool, use_dialplan);
new_profile->context = switch_core_strdup(new_profile->pool, use_context);
@@ -2238,7 +2243,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_session_transfer(switch_core_session_
switch_core_session_rwunlock(other_session);
}
- switch_channel_set_caller_profile(channel, new_profile);
+ if (!switch_channel_test_flag(channel, CF_REUSE_CALLER_PROFILE)){
+ switch_channel_set_caller_profile(channel, new_profile);
+ }
switch_channel_set_state(channel, CS_ROUTING);
switch_channel_audio_sync(channel);
@@ -3515,8 +3522,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_generate_json_cdr(switch_core_session
SWITCH_DECLARE(void) switch_ivr_park_session(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
- switch_channel_set_state(channel, CS_PARK);
switch_channel_set_flag(channel, CF_TRANSFER);
+ switch_channel_set_state(channel, CS_PARK);
}
diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c
index 705142228c..07f28a36e8 100644
--- a/src/switch_ivr_async.c
+++ b/src/switch_ivr_async.c
@@ -2084,7 +2084,7 @@ static switch_bool_t eavesdrop_callback(switch_media_bug_t *bug, void *user_data
memcpy(frame.data, nframe->data, nframe->datalen);
- if (switch_core_session_write_frame(ep->eavesdropper, nframe, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
+ if (switch_core_session_write_frame(ep->eavesdropper, &frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
return SWITCH_FALSE;
}
}
@@ -2184,6 +2184,25 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_update_display(switch_core_
return status;
}
+/*Greatest Common Divisor*/
+static uint32_t switch_gcd(uint32_t x, uint32_t y)
+{
+ if (y == 0) {
+ return x;
+ }
+
+ return switch_gcd(y, x % y);
+}
+
+/*Least Common Multiple*/
+static uint32_t switch_lcm(uint32_t x, uint32_t y)
+{
+ uint32_t gcd = switch_gcd(x, y);
+
+ if (gcd) return (x * y) / gcd;
+
+ return 0;
+}
SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session_t *session,
const char *uuid, const char *require_group, switch_eavesdrop_flag_t flags)
@@ -2209,14 +2228,21 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session
char cid_buf[1024] = "";
switch_caller_profile_t *cp = NULL;
uint32_t sanity = 600;
- switch_media_bug_flag_t read_flags = 0, write_flags = 0;
+ switch_media_bug_flag_t read_flags = 0, write_flags = 0, stereo_flag = 0;
const char *vval;
int buf_size = 0;
+ int channels;
+ int lcm, buff_min_len, buffered = 1;
if (!switch_channel_media_up(channel)) {
goto end;
}
+ if (tsession == session) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Eavesdrop target invalid.\n");
+ goto end;
+ }
+
while(switch_channel_state_change_pending(tchannel) || !switch_channel_media_up(tchannel)) {
switch_yield(10000);
if (!--sanity) break;
@@ -2280,15 +2306,26 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session
ep = switch_core_session_alloc(session, sizeof(*ep));
- tlen = tread_impl.decoded_bytes_per_packet;
-
if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
goto end;
}
-
- if (switch_core_codec_init(&codec,
+ if (tread_impl.decoded_bytes_per_packet < read_impl.decoded_bytes_per_packet) {
+ if (switch_core_codec_init(&codec,
+ "L16",
+ NULL,
+ NULL,
+ read_impl.actual_samples_per_second,
+ read_impl.microseconds_per_packet / 1000,
+ read_impl.number_of_channels,
+ SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
+ NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot init codec\n");
+ goto end;
+ }
+ } else {
+ if (switch_core_codec_init(&codec,
"L16",
NULL,
NULL,
@@ -2299,10 +2336,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session
NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot init codec\n");
goto end;
+ }
+ buffered = 0;
}
- switch_core_session_get_read_impl(session, &read_impl);
-
ep->read_impl = read_impl;
ep->tread_impl = tread_impl;
@@ -2355,7 +2392,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session
write_flags = SMBF_TAP_NATIVE_WRITE;
read_flags = 0;
}
-
+
+ if (flags & ED_STEREO) {
+ stereo_flag = SMBF_STEREO;
+ }
if (switch_channel_test_flag(session->channel, CF_VIDEO) && switch_channel_test_flag(tsession->channel, CF_VIDEO)) {
if ((vval = switch_channel_get_variable(session->channel, "eavesdrop_show_listener_video"))) {
@@ -2384,7 +2424,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session
if (switch_core_media_bug_add(tsession, "eavesdrop", uuid,
eavesdrop_callback, ep, 0,
- read_flags | write_flags | SMBF_READ_PING | SMBF_THREAD_LOCK | SMBF_NO_PAUSE,
+ read_flags | write_flags | SMBF_READ_PING | SMBF_THREAD_LOCK | SMBF_NO_PAUSE | stereo_flag,
&bug) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot attach bug\n");
goto end;
@@ -2438,6 +2478,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session
switch_core_session_receive_message(tsession, &msg);
}
+ lcm = switch_lcm(tread_impl.decoded_bytes_per_packet, read_impl.decoded_bytes_per_packet);
+
while (switch_channel_up_nosig(tchannel) && switch_channel_ready(channel)) {
uint32_t len = sizeof(buf);
switch_event_t *event = NULL;
@@ -2561,18 +2603,35 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session
switch_buffer_unlock(ep->w_buffer);
}
+ channels = switch_core_media_bug_test_flag(bug, SMBF_STEREO) ? 2 : tread_impl.number_of_channels;
+
+ if (channels == 0) {
+ channels = 1;
+ }
+
+ tlen = ep->read_impl.decoded_bytes_per_packet * channels;
+
if (len > tlen) {
len = tlen;
}
- if (ep->buffer && switch_buffer_inuse(ep->buffer) >= len) {
+ if (buffered) {
+ buff_min_len = lcm * 2;
+ if (switch_buffer_inuse(ep->buffer) < buff_min_len) {
+ continue;
+ }
+ } else {
+ buff_min_len = len;
+ }
+
+ if (ep->buffer) {
switch_buffer_lock(ep->buffer);
- while (switch_buffer_inuse(ep->buffer) >= len) {
+ while (switch_buffer_inuse(ep->buffer) >= buff_min_len) {
int tchanged = 0, changed = 0;
write_frame.datalen = (uint32_t) switch_buffer_read(ep->buffer, buf, len);
- write_frame.samples = write_frame.datalen / 2;
-
+ write_frame.samples = write_frame.datalen / 2 / channels;
+ write_frame.channels = channels;
switch_core_session_get_read_impl(tsession, &tread_impl);
switch_core_session_get_read_impl(session, &read_impl);
@@ -2582,7 +2641,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session
tchanged = 1;
}
- if (read_impl.number_of_channels != ep->tread_impl.number_of_channels ||
+ if (read_impl.number_of_channels != ep->read_impl.number_of_channels ||
read_impl.actual_samples_per_second != ep->read_impl.actual_samples_per_second) {
changed = 1;
}
@@ -2596,6 +2655,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session
ep->read_impl.number_of_channels,
read_impl.actual_samples_per_second,
read_impl.number_of_channels);
+
+ tlen = read_impl.decoded_bytes_per_packet * channels;
+
+ if (len > tlen) {
+ len = tlen;
+ }
+
}
if (tchanged) {
@@ -2605,28 +2671,44 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session
ep->tread_impl.number_of_channels,
tread_impl.actual_samples_per_second,
tread_impl.number_of_channels);
+ }
+
- tlen = tread_impl.decoded_bytes_per_packet;
-
- if (len > tlen) {
- len = tlen;
- }
-
- switch_core_codec_destroy(&codec);
+ switch_core_codec_destroy(&codec);
+ if (tread_impl.decoded_bytes_per_packet < read_impl.decoded_bytes_per_packet) {
if (switch_core_codec_init(&codec,
"L16",
NULL,
NULL,
- tread_impl.actual_samples_per_second,
- tread_impl.microseconds_per_packet / 1000,
- tread_impl.number_of_channels,
+ read_impl.actual_samples_per_second,
+ read_impl.microseconds_per_packet / 1000,
+ read_impl.number_of_channels,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot init codec\n");
+ switch_buffer_unlock(ep->buffer);
+ goto end;
+ }
+ buffered = 1;
+ lcm = switch_lcm(tread_impl.decoded_bytes_per_packet, read_impl.decoded_bytes_per_packet);
+ } else {
+ if (switch_core_codec_init(&codec,
+ "L16",
+ NULL,
+ NULL,
+ tread_impl.actual_samples_per_second,
+ tread_impl.microseconds_per_packet / 1000,
+ tread_impl.number_of_channels,
+ SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
+ NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot init codec\n");
- switch_core_session_rwunlock(tsession);
+ switch_buffer_unlock(ep->buffer);
goto end;
}
+ if (buffered == 1) {
+ buffered = 0;
+ }
}
ep->read_impl = read_impl;
@@ -2645,10 +2727,17 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session
if ((status = switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0)) != SWITCH_STATUS_SUCCESS) {
break;
}
+
+ switch_buffer_unlock(ep->buffer);
+ switch_buffer_lock(ep->buffer);
+
+ if (ep->tread_impl.decoded_bytes_per_packet == ep->read_impl.decoded_bytes_per_packet) {
+ /* push just the number of samples worth of a packet. */
+ break;
+ }
}
switch_buffer_unlock(ep->buffer);
}
-
}
end_loop:
diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c
index 2ae0919519..d2baeb2741 100644
--- a/src/switch_ivr_originate.c
+++ b/src/switch_ivr_originate.c
@@ -830,6 +830,12 @@ static uint8_t check_channel_status(originate_global_t *oglobals, uint32_t len,
}
} else if (switch_channel_test_flag(oglobals->originate_status[i].peer_channel, CF_WINNER)) {
+ /* unset group_confirm variables */
+ switch_channel_set_variable(oglobals->originate_status[i].peer_channel, "group_confirm_key", NULL);
+ switch_channel_set_variable(oglobals->originate_status[i].peer_channel, "group_confirm_file", NULL);
+ switch_channel_set_variable(oglobals->originate_status[i].peer_channel, "group_confirm_error_file", NULL);
+ switch_channel_set_variable(oglobals->originate_status[i].peer_channel, "group_confirm_cancel_timeout", NULL);
+ switch_channel_set_variable(oglobals->originate_status[i].peer_channel, "group_confirm_read_timeout", NULL);
oglobals->idx = i;
rval = 0;
pindex = (uint32_t) i;
@@ -2855,6 +2861,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
if (oglobals.session) {
if (!switch_channel_ready(caller_channel)) {
status = SWITCH_STATUS_FALSE;
+ if (local_var_event) switch_event_destroy(&local_var_event);
goto done;
}
diff --git a/src/switch_ivr_play_say.c b/src/switch_ivr_play_say.c
index e217950958..a8cb5fd4a1 100644
--- a/src/switch_ivr_play_say.c
+++ b/src/switch_ivr_play_say.c
@@ -1309,8 +1309,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
*arg++ = '\0';
}
if ((status = switch_ivr_phrase_macro(session, dup, arg, lang, args)) != SWITCH_STATUS_SUCCESS) {
- arg_recursion_check_stop(args);
- return status;
+ break;
}
continue;
} else {
@@ -1327,8 +1326,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
if (engine && text) {
if ((status = switch_ivr_speak_text(session, engine, voice, (char *)text, args)) != SWITCH_STATUS_SUCCESS) {
- arg_recursion_check_stop(args);
- return status;
+ break;
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Args\n");
diff --git a/src/switch_odbc.c b/src/switch_odbc.c
index 31161ee158..fbad0e371a 100644
--- a/src/switch_odbc.c
+++ b/src/switch_odbc.c
@@ -605,17 +605,75 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_callback_exec_detailed(c
for (x = 1; x <= c; x++) {
SQLSMALLINT NameLength = 0, DataType = 0, DecimalDigits = 0, Nullable = 0;
SQLULEN ColumnSize = 0;
+ SQLLEN numRecs = 0;
+ SQLCHAR SqlState[6], Msg[SQL_MAX_MESSAGE_LENGTH];
+ SQLINTEGER NativeError;
+ SQLSMALLINT diagCount, MsgLen;
names[y] = malloc(name_len);
switch_assert(names[y]);
memset(names[y], 0, name_len);
SQLDescribeCol(stmt, x, (SQLCHAR *) names[y], (SQLSMALLINT) name_len, &NameLength, &DataType, &ColumnSize, &DecimalDigits, &Nullable);
- if (!ColumnSize) {
+ if (ColumnSize <= 16383 || ColumnSize == 2147483647) {
SQLCHAR val[16384] = { 0 };
+ SQLLEN StrLen_or_IndPtr;
+ SQLRETURN rc;
ColumnSize = 16384;
- SQLGetData(stmt, x, SQL_C_CHAR, val, ColumnSize, NULL);
- vals[y] = strdup((char *)val);
+
+ /* check diag record and see if we can get real size
+ * https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/using-sqlgetdiagrec-and-sqlgetdiagfield?view=sql-server-ver15
+ * szSqlState = "01004" and StrLen_or_IndPtr=15794
+ */
+ rc = SQLGetData(stmt, x, SQL_C_CHAR, val, ColumnSize, &StrLen_or_IndPtr);
+
+ if (rc == SQL_SUCCESS_WITH_INFO) {
+ int truncated = 0;
+ diagCount = 1;
+
+ SQLGetDiagField(SQL_HANDLE_STMT, stmt, 0, SQL_DIAG_NUMBER, &numRecs, 0, 0);
+
+ while (diagCount <= numRecs) {
+ SQLGetDiagRec(SQL_HANDLE_STMT, stmt, diagCount, SqlState, &NativeError,Msg, sizeof(Msg), &MsgLen);
+ if (!strcmp((char*)SqlState,"01004")){
+ truncated = 1;
+ break;
+ }
+
+ diagCount++;
+ }
+
+ if (truncated) {
+ if (StrLen_or_IndPtr && StrLen_or_IndPtr <= 268435456) {
+ int ValLen = strlen((char*)val);
+ ColumnSize = StrLen_or_IndPtr + 1;
+ vals[y] = malloc(ColumnSize);
+ switch_assert(vals[y]);
+ memset(vals[y], 0, ColumnSize);
+ strcpy(vals[y], (char*)val);
+ rc = SQLGetData(stmt, x, SQL_C_CHAR, (SQLCHAR *)vals[y] + ValLen, ColumnSize - ValLen, NULL);
+ if (rc != SQL_SUCCESS
+#if (ODBCVER >= 0x0300)
+ && rc != SQL_NO_DATA
+#endif
+ ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQLGetData was truncated and failed to complete.\n");
+ switch_safe_free(vals[y]);
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sql data truncated - %s\n",SqlState);
+ vals[y] = NULL;
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQLGetData failed\n");
+ vals[y] = NULL;
+ }
+ } else if (rc == SQL_SUCCESS){
+ vals[y] = strdup((char *)val);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQLGetData failed\n");
+ vals[y] = NULL;
+ }
} else {
ColumnSize++;
@@ -633,7 +691,7 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_callback_exec_detailed(c
for (x = 0; x < y; x++) {
free(names[x]);
- free(vals[x]);
+ switch_safe_free(vals[x]);
}
free(names);
free(vals);
diff --git a/src/switch_rtp.c b/src/switch_rtp.c
index e7aafd0482..e2e6dedc2d 100644
--- a/src/switch_rtp.c
+++ b/src/switch_rtp.c
@@ -2991,7 +2991,7 @@ static void ping_socket(switch_rtp_t *rtp_session)
switch_size_t len = sizeof(o);
switch_socket_sendto(rtp_session->sock_input, rtp_session->local_addr, 0, (void *) &o, &len);
- if (rtp_session->flags[SWITCH_RTP_FLAG_ENABLE_RTCP] && rtp_session->rtcp_sock_input) {
+ if (rtp_session->flags[SWITCH_RTP_FLAG_ENABLE_RTCP] && rtp_session->rtcp_sock_input && rtp_session->rtcp_sock_input != rtp_session->sock_input) {
switch_socket_sendto(rtp_session->rtcp_sock_input, rtp_session->rtcp_local_addr, 0, (void *) &o, &len);
}
}
@@ -5077,11 +5077,11 @@ SWITCH_DECLARE(void) switch_rtp_kill_socket(switch_rtp_t *rtp_session)
}
if (rtp_session->flags[SWITCH_RTP_FLAG_ENABLE_RTCP]) {
- if (rtp_session->rtcp_sock_input) {
+ if (rtp_session->rtcp_sock_input && rtp_session->rtcp_sock_input != rtp_session->sock_input) {
ping_socket(rtp_session);
switch_socket_shutdown(rtp_session->rtcp_sock_input, SWITCH_SHUTDOWN_READWRITE);
}
- if (rtp_session->rtcp_sock_output && rtp_session->rtcp_sock_output != rtp_session->rtcp_sock_input) {
+ if (rtp_session->rtcp_sock_output && rtp_session->rtcp_sock_output != rtp_session->sock_output && rtp_session->rtcp_sock_output != rtp_session->rtcp_sock_input) {
switch_socket_shutdown(rtp_session->rtcp_sock_output, SWITCH_SHUTDOWN_READWRITE);
}
}
@@ -5197,6 +5197,13 @@ SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session)
free_dtls(&(*rtp_session)->rtcp_dtls);
}
+ if ((*rtp_session)->rtcp_sock_input == (*rtp_session)->sock_input) {
+ (*rtp_session)->rtcp_sock_input = NULL;
+ }
+
+ if ((*rtp_session)->rtcp_sock_output == (*rtp_session)->sock_output) {
+ (*rtp_session)->rtcp_sock_output = NULL;
+ }
sock = (*rtp_session)->sock_input;
(*rtp_session)->sock_input = NULL;
@@ -5211,13 +5218,12 @@ SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session)
if ((sock = (*rtp_session)->rtcp_sock_input)) {
(*rtp_session)->rtcp_sock_input = NULL;
switch_socket_close(sock);
+ }
- if ((*rtp_session)->rtcp_sock_output && (*rtp_session)->rtcp_sock_output != sock) {
- if ((sock = (*rtp_session)->rtcp_sock_output)) {
- (*rtp_session)->rtcp_sock_output = NULL;
- switch_socket_close(sock);
- }
- }
+ if ((*rtp_session)->rtcp_sock_output && (*rtp_session)->rtcp_sock_output != sock) {
+ sock = (*rtp_session)->rtcp_sock_output;
+ (*rtp_session)->rtcp_sock_output = NULL;
+ switch_socket_close(sock);
}
#ifdef ENABLE_SRTP
diff --git a/src/switch_scheduler.c b/src/switch_scheduler.c
index c08d1071b4..9c0f29a35b 100644
--- a/src/switch_scheduler.c
+++ b/src/switch_scheduler.c
@@ -209,9 +209,21 @@ static void *SWITCH_THREAD_FUNC switch_scheduler_task_thread(switch_thread_t *th
}
SWITCH_DECLARE(uint32_t) switch_scheduler_add_task(time_t task_runtime,
- switch_scheduler_func_t func,
- const char *desc, const char *group, uint32_t cmd_id, void *cmd_arg, switch_scheduler_flag_t flags)
+ switch_scheduler_func_t func,
+ const char *desc, const char *group, uint32_t cmd_id, void *cmd_arg, switch_scheduler_flag_t flags)
{
+ uint32_t task_id;
+
+ switch_scheduler_add_task_ex(task_runtime, func, desc, group, cmd_id, cmd_arg, flags, &task_id);
+
+ return task_id;
+}
+
+SWITCH_DECLARE(uint32_t) switch_scheduler_add_task_ex(time_t task_runtime,
+ switch_scheduler_func_t func,
+ const char *desc, const char *group, uint32_t cmd_id, void *cmd_arg, switch_scheduler_flag_t flags, uint32_t *task_id)
+{
+ uint32_t result;
switch_scheduler_task_container_t *container, *tp;
switch_event_t *event;
switch_time_t now = switch_epoch_time_now(NULL);
@@ -220,6 +232,7 @@ SWITCH_DECLARE(uint32_t) switch_scheduler_add_task(time_t task_runtime,
switch_mutex_lock(globals.task_mutex);
switch_zmalloc(container, sizeof(*container));
switch_assert(func);
+ switch_assert(task_id);
if (task_runtime < now) {
container->task.repeat = (uint32_t)task_runtime;
@@ -246,8 +259,6 @@ SWITCH_DECLARE(uint32_t) switch_scheduler_add_task(time_t task_runtime,
for (container->task.task_id = 0; !container->task.task_id; container->task.task_id = ++globals.task_id);
- switch_mutex_unlock(globals.task_mutex);
-
tp = container;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Added task %u %s (%s) to run at %" SWITCH_INT64_T_FMT "\n",
tp->task.task_id, tp->desc, switch_str_nil(tp->task.group), tp->task.runtime);
@@ -260,7 +271,12 @@ SWITCH_DECLARE(uint32_t) switch_scheduler_add_task(time_t task_runtime,
switch_queue_push(globals.event_queue, event);
event = NULL;
}
- return container->task.task_id;
+
+ result = *task_id = container->task.task_id;
+
+ switch_mutex_unlock(globals.task_mutex);
+
+ return result;
}
SWITCH_DECLARE(uint32_t) switch_scheduler_del_task_id(uint32_t task_id)
diff --git a/src/switch_utils.c b/src/switch_utils.c
index e4e26a6eef..5d6b8f2aaf 100644
--- a/src/switch_utils.c
+++ b/src/switch_utils.c
@@ -4176,11 +4176,12 @@ SWITCH_DECLARE(void) switch_http_parse_qs(switch_http_request_t *request, char *
char *q;
char *next;
char *name, *val;
+ char *dup = NULL;
if (qs) {
q = qs;
} else { /*parse our own qs, dup to avoid modify the original string */
- q = strdup(request->qs);
+ dup = q = strdup(request->qs);
}
switch_assert(q);
@@ -4207,9 +4208,7 @@ SWITCH_DECLARE(void) switch_http_parse_qs(switch_http_request_t *request, char *
q = next;
} while (q);
- if (!qs) {
- switch_safe_free(q);
- }
+ switch_safe_free(dup);
}
/* clean the uri to protect us from vulnerability attack */
diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am
index 6e7e128d62..231225c5aa 100644
--- a/tests/unit/Makefile.am
+++ b/tests/unit/Makefile.am
@@ -2,13 +2,18 @@ include $(top_srcdir)/build/modmake.rulesam
noinst_PROGRAMS = switch_event switch_hash switch_ivr_originate switch_utils switch_core switch_console switch_vpx switch_core_file \
switch_ivr_play_say switch_core_codec switch_rtp switch_xml
-noinst_PROGRAMS += switch_core_video switch_core_db switch_vad switch_core_asr
+noinst_PROGRAMS += switch_core_video switch_core_db switch_vad switch_core_asr test_sofia
AM_LDFLAGS += -avoid-version -no-undefined $(SWITCH_AM_LDFLAGS) $(openssl_LIBS)
AM_LDFLAGS += $(FREESWITCH_LIBS) $(switch_builddir)/libfreeswitch.la $(CORE_LIBS) $(APR_LIBS)
+# "make check" will not run these.
+examples = switch_eavesdrop
+
if HAVE_FVAD
AM_CFLAGS += -DSWITCH_HAVE_FVAD
endif
TESTS = $(noinst_PROGRAMS)
+
+bin_PROGRAMS = $(examples)
diff --git a/tests/unit/conf_eavesdrop/freeswitch.xml b/tests/unit/conf_eavesdrop/freeswitch.xml
new file mode 100644
index 0000000000..4a65caf6d8
--- /dev/null
+++ b/tests/unit/conf_eavesdrop/freeswitch.xml
@@ -0,0 +1,238 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/unit/conf_eavesdrop/gw/eavestest.xml b/tests/unit/conf_eavesdrop/gw/eavestest.xml
new file mode 100644
index 0000000000..a2f268424e
--- /dev/null
+++ b/tests/unit/conf_eavesdrop/gw/eavestest.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/unit/conf_sofia/freeswitch.xml b/tests/unit/conf_sofia/freeswitch.xml
new file mode 100644
index 0000000000..793ac5a04a
--- /dev/null
+++ b/tests/unit/conf_sofia/freeswitch.xml
@@ -0,0 +1,144 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/unit/switch_eavesdrop.c b/tests/unit/switch_eavesdrop.c
new file mode 100644
index 0000000000..18c293f833
--- /dev/null
+++ b/tests/unit/switch_eavesdrop.c
@@ -0,0 +1,387 @@
+#include
+#include
+
+static switch_status_t test_detect_long_tone_in_file(const char *filepath, int rate, int freq, int ptime) {
+ teletone_multi_tone_t mt;
+ teletone_tone_map_t map;
+ int16_t data[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 };
+ switch_size_t len = (rate * ptime / 1000) /*packet len in samples */ * 8; /*length of chunk that must contain tone*/
+ switch_size_t fin = 0;
+ switch_status_t status;
+ switch_file_handle_t fh = { 0 };
+ uint8_t fail = 0, gaps = 0, audio = 0;
+
+ status = switch_core_file_open(&fh, filepath, 1, rate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL);
+ if (status != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot open file [%s]\n", filepath);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ mt.sample_rate = rate;
+ map.freqs[0] = (teletone_process_t)freq;
+
+ teletone_multi_tone_init(&mt, &map);
+
+ len = (rate * 2 / 100) /*packet len in samples */ * 8;
+
+ while (switch_core_file_read(&fh, &data, &len) == SWITCH_STATUS_SUCCESS) {
+ fin += len;
+ /*skip silence at the beginning of the file, 1 second max. */
+ if (!teletone_multi_tone_detect(&mt, data, len)) {
+ if ((fin > rate && !audio) || gaps > 30) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Too many gaps in audio or no tone detected 1st second. [%" SWITCH_SIZE_T_FMT "][%d]\n", fin, gaps);
+ fail = 1;
+ break;
+ }
+ gaps++;
+ continue;
+ } else {
+ audio++;
+ }
+ }
+
+ switch_core_file_close(&fh);
+
+ if (fail) {
+ return SWITCH_STATUS_FALSE;
+ }
+ return SWITCH_STATUS_SUCCESS;
+}
+
+FST_CORE_BEGIN("./conf_eavesdrop")
+
+{
+FST_SUITE_BEGIN(switch_eavesdrop)
+{
+ FST_SETUP_BEGIN()
+ {
+ fst_requires_module("mod_loopback");
+ fst_requires_module("mod_sofia");
+ switch_core_set_variable("link_ip", switch_core_get_variable("local_ip_v4"));
+ }
+ FST_SETUP_END()
+
+ FST_TEARDOWN_BEGIN()
+ {
+ }
+ FST_TEARDOWN_END()
+
+ FST_TEST_BEGIN(test_eavesdrop_bridged_same_ptime_20ms)
+ {
+ switch_core_session_t *session1 = NULL;
+ switch_core_session_t *session2 = NULL;
+ switch_core_session_t *session3 = NULL;
+
+ switch_channel_t *channel1 = NULL;
+ switch_channel_t *channel2 = NULL;
+ switch_channel_t *channel3 = NULL;
+
+ switch_status_t status;
+ switch_call_cause_t cause;
+ switch_stream_handle_t stream = { 0 };
+ char eavesdrop_command[256] = { 0 };
+ char rec_path[1024];
+ char rec_uuid[SWITCH_UUID_FORMATTED_LENGTH + 1] = { 0 };
+ char eaves_dialstr[512] = { 0 };
+
+ switch_uuid_str(rec_uuid, sizeof(rec_uuid));
+
+ /*parked 20 ms ptime */
+ status = switch_ivr_originate(NULL, &session1, &cause, "{ignore_early_media=true}sofia/gateway/eavestest/+15553332220", 2, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL);
+ fst_requires(session1);
+ fst_check(status == SWITCH_STATUS_SUCCESS);
+ channel1 = switch_core_session_get_channel(session1);
+ fst_requires(channel1);
+
+ snprintf(eaves_dialstr, sizeof(eaves_dialstr), "{ignore_early_media=true}{sip_h_X-UnitTestRecfile=%s}sofia/gateway/eavestest/+15553332230", rec_uuid);
+
+ /*eavesdropper 20 ms ptime*/
+ status = switch_ivr_originate(NULL, &session2, &cause, eaves_dialstr, 2, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL);
+ fst_requires(session2);
+ fst_check(status == SWITCH_STATUS_SUCCESS);
+ channel2 = switch_core_session_get_channel(session2);
+ fst_requires(channel2);
+
+ /*milliwatt tone 20 ms ptime*/
+ status = switch_ivr_originate(NULL, &session3, &cause, "{ignore_early_media=true}sofia/gateway/eavestest/+15553332226", 2, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL);
+ fst_requires(session3);
+ fst_check(status == SWITCH_STATUS_SUCCESS);
+ channel3 = switch_core_session_get_channel(session3);
+ fst_requires(channel3);
+
+ SWITCH_STANDARD_STREAM(stream);
+ switch_snprintf(eavesdrop_command, sizeof(eavesdrop_command), "uuid_bridge %s %s", switch_core_session_get_uuid(session1), switch_core_session_get_uuid(session2));
+ switch_api_execute("bgapi", eavesdrop_command, session1, &stream);
+ memset(eavesdrop_command, 0, sizeof(eavesdrop_command));
+ switch_snprintf(eavesdrop_command, sizeof(eavesdrop_command),"uuid_setvar_multi %s eavesdrop_enable_dtmf=false;eavesdrop_whisper_bleg=true;eavesdrop_whisper_aleg=false", switch_core_session_get_uuid(session3));
+ switch_api_execute("bgapi", eavesdrop_command, session3, &stream);
+ memset(eavesdrop_command, 0, sizeof(eavesdrop_command));
+ switch_snprintf(eavesdrop_command, sizeof(eavesdrop_command), "uuid_transfer %s 'eavesdrop:%s' inline", switch_core_session_get_uuid(session3), switch_core_session_get_uuid(session2));
+ switch_api_execute("bgapi", eavesdrop_command, session3, &stream);
+ switch_safe_free(stream.data);
+
+ sleep(5); // it will record ~ 5 secs
+
+ snprintf(rec_path, sizeof(rec_path), "/tmp/eaves-%s.wav", rec_uuid);
+
+ fst_requires(switch_file_exists(rec_path, fst_pool) == SWITCH_STATUS_SUCCESS);
+
+ fst_requires(test_detect_long_tone_in_file(rec_path, 8000, 300, 20) == SWITCH_STATUS_SUCCESS);
+
+ unlink(rec_path);
+
+ switch_channel_hangup(channel1, SWITCH_CAUSE_NORMAL_CLEARING);
+ switch_channel_hangup(channel2, SWITCH_CAUSE_NORMAL_CLEARING);
+ switch_channel_hangup(channel3, SWITCH_CAUSE_NORMAL_CLEARING);
+
+ switch_core_session_rwunlock(session1);
+ switch_core_session_rwunlock(session2);
+ switch_core_session_rwunlock(session3);
+
+ }
+ FST_TEST_END()
+
+ FST_TEST_BEGIN(test_eavesdrop_bridged_ptime_mismatch_20ms_30ms)
+ {
+ switch_core_session_t *session1 = NULL;
+ switch_core_session_t *session2 = NULL;
+ switch_core_session_t *session3 = NULL;
+
+ switch_channel_t *channel1 = NULL;
+ switch_channel_t *channel2 = NULL;
+ switch_channel_t *channel3 = NULL;
+
+ switch_status_t status;
+ switch_call_cause_t cause;
+ switch_stream_handle_t stream = { 0 };
+ char eavesdrop_command[256] = { 0 };
+ char rec_path[1024];
+ char rec_uuid[SWITCH_UUID_FORMATTED_LENGTH + 1] = { 0 };
+ char eaves_dialstr[512] = { 0 };
+
+ switch_uuid_str(rec_uuid, sizeof(rec_uuid));
+
+ /*parked 20 ms ptime */
+ status = switch_ivr_originate(NULL, &session1, &cause, "{ignore_early_media=true}sofia/gateway/eavestest/+15553332220", 2, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL);
+ fst_requires(session1);
+ fst_check(status == SWITCH_STATUS_SUCCESS);
+ channel1 = switch_core_session_get_channel(session1);
+ fst_requires(channel1);
+
+ snprintf(eaves_dialstr, sizeof(eaves_dialstr), "{ignore_early_media=true}{sip_h_X-UnitTestRecfile=%s}sofia/gateway/eavestest/+15553332230", rec_uuid);
+
+ /*eavesdropper 20 ms ptime*/
+ status = switch_ivr_originate(NULL, &session2, &cause, eaves_dialstr, 2, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL);
+ fst_requires(session2);
+ fst_check(status == SWITCH_STATUS_SUCCESS);
+ channel2 = switch_core_session_get_channel(session2);
+ fst_requires(channel2);
+
+ /*milliwatt tone 30 ms ptime*/
+ status = switch_ivr_originate(NULL, &session3, &cause, "{ignore_early_media=true}sofia/gateway/eavestest/+15553332222", 2, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL);
+ fst_requires(session3);
+ fst_check(status == SWITCH_STATUS_SUCCESS);
+ channel3 = switch_core_session_get_channel(session3);
+ fst_requires(channel3);
+
+ SWITCH_STANDARD_STREAM(stream);
+ switch_snprintf(eavesdrop_command, sizeof(eavesdrop_command), "uuid_bridge %s %s", switch_core_session_get_uuid(session1), switch_core_session_get_uuid(session2));
+ switch_api_execute("bgapi", eavesdrop_command, session1, &stream);
+ memset(eavesdrop_command, 0, sizeof(eavesdrop_command));
+ switch_snprintf(eavesdrop_command, sizeof(eavesdrop_command),"uuid_setvar_multi %s eavesdrop_enable_dtmf=false;eavesdrop_whisper_bleg=true;eavesdrop_whisper_aleg=false", switch_core_session_get_uuid(session3));
+ switch_api_execute("bgapi", eavesdrop_command, session3, &stream);
+ memset(eavesdrop_command, 0, sizeof(eavesdrop_command));
+ switch_snprintf(eavesdrop_command, sizeof(eavesdrop_command), "uuid_transfer %s 'eavesdrop:%s' inline", switch_core_session_get_uuid(session3), switch_core_session_get_uuid(session2));
+ switch_api_execute("bgapi", eavesdrop_command, session3, &stream);
+ switch_safe_free(stream.data);
+
+ sleep(5); // it will record ~ 5 secs
+
+ snprintf(rec_path, sizeof(rec_path), "/tmp/eaves-%s.wav", rec_uuid);
+
+ fst_requires(switch_file_exists(rec_path, fst_pool) == SWITCH_STATUS_SUCCESS);
+
+ fst_requires(test_detect_long_tone_in_file(rec_path, 8000, 300, 20) == SWITCH_STATUS_SUCCESS);
+
+ unlink(rec_path);
+
+ switch_channel_hangup(channel1, SWITCH_CAUSE_NORMAL_CLEARING);
+ switch_channel_hangup(channel2, SWITCH_CAUSE_NORMAL_CLEARING);
+ switch_channel_hangup(channel3, SWITCH_CAUSE_NORMAL_CLEARING);
+
+ switch_core_session_rwunlock(session1);
+ switch_core_session_rwunlock(session2);
+ switch_core_session_rwunlock(session3);
+
+ }
+ FST_TEST_END()
+
+ FST_TEST_BEGIN(test_eavesdrop_bridged_ptime_mismatch_30ms_20ms)
+ {
+ switch_core_session_t *session1 = NULL;
+ switch_core_session_t *session2 = NULL;
+ switch_core_session_t *session3 = NULL;
+
+ switch_channel_t *channel1 = NULL;
+ switch_channel_t *channel2 = NULL;
+ switch_channel_t *channel3 = NULL;
+
+ switch_status_t status;
+ switch_call_cause_t cause;
+ switch_stream_handle_t stream = { 0 };
+ char eavesdrop_command[256] = { 0 };
+ char rec_path[1024];
+ char rec_uuid[SWITCH_UUID_FORMATTED_LENGTH + 1] = { 0 };
+ char eaves_dialstr[512] = { 0 };
+
+ switch_uuid_str(rec_uuid, sizeof(rec_uuid));
+
+ /*parked 30 ms ptime */
+ status = switch_ivr_originate(NULL, &session1, &cause, "{ignore_early_media=true}sofia/gateway/eavestest/+15553332231", 2, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL);
+ fst_requires(session1);
+ fst_check(status == SWITCH_STATUS_SUCCESS);
+ channel1 = switch_core_session_get_channel(session1);
+ fst_requires(channel1);
+
+ snprintf(eaves_dialstr, sizeof(eaves_dialstr), "{ignore_early_media=true}{sip_h_X-UnitTestRecfile=%s}sofia/gateway/eavestest/+15553332240", rec_uuid);
+
+ /*eavesdropper 30 ms ptime*/
+ status = switch_ivr_originate(NULL, &session2, &cause, eaves_dialstr, 2, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL);
+ fst_requires(session2);
+ fst_check(status == SWITCH_STATUS_SUCCESS);
+ channel2 = switch_core_session_get_channel(session2);
+ fst_requires(channel2);
+
+ /*milliwatt tone 20 ms ptime*/
+ status = switch_ivr_originate(NULL, &session3, &cause, "{ignore_early_media=true}sofia/gateway/eavestest/+15553332226", 2, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL);
+ fst_requires(session3);
+ fst_check(status == SWITCH_STATUS_SUCCESS);
+ channel3 = switch_core_session_get_channel(session3);
+ fst_requires(channel3);
+
+ SWITCH_STANDARD_STREAM(stream);
+ switch_snprintf(eavesdrop_command, sizeof(eavesdrop_command), "uuid_bridge %s %s", switch_core_session_get_uuid(session1), switch_core_session_get_uuid(session2));
+ switch_api_execute("bgapi", eavesdrop_command, session1, &stream);
+ memset(eavesdrop_command, 0, sizeof(eavesdrop_command));
+ switch_snprintf(eavesdrop_command, sizeof(eavesdrop_command),"uuid_setvar_multi %s eavesdrop_enable_dtmf=false;eavesdrop_whisper_bleg=true;eavesdrop_whisper_aleg=false", switch_core_session_get_uuid(session3));
+ switch_api_execute("bgapi", eavesdrop_command, session3, &stream);
+ memset(eavesdrop_command, 0, sizeof(eavesdrop_command));
+ switch_snprintf(eavesdrop_command, sizeof(eavesdrop_command), "uuid_transfer %s 'eavesdrop:%s' inline", switch_core_session_get_uuid(session3), switch_core_session_get_uuid(session2));
+ switch_api_execute("bgapi", eavesdrop_command, session3, &stream);
+ switch_safe_free(stream.data);
+
+ sleep(5); // it will record ~ 5 secs
+
+ snprintf(rec_path, sizeof(rec_path), "/tmp/eaves-%s.wav", rec_uuid);
+
+ fst_requires(switch_file_exists(rec_path, fst_pool) == SWITCH_STATUS_SUCCESS);
+
+ fst_requires(test_detect_long_tone_in_file(rec_path, 8000, 300, 30) == SWITCH_STATUS_SUCCESS);
+
+ unlink(rec_path);
+
+ switch_channel_hangup(channel1, SWITCH_CAUSE_NORMAL_CLEARING);
+ switch_channel_hangup(channel2, SWITCH_CAUSE_NORMAL_CLEARING);
+ switch_channel_hangup(channel3, SWITCH_CAUSE_NORMAL_CLEARING);
+
+ switch_core_session_rwunlock(session1);
+ switch_core_session_rwunlock(session2);
+ switch_core_session_rwunlock(session3);
+
+ }
+ FST_TEST_END()
+
+ FST_TEST_BEGIN(test_eavesdrop_bridged_ptime_mismatch_reneg)
+ {
+ switch_core_session_t *session1 = NULL;
+ switch_core_session_t *session2 = NULL;
+ switch_core_session_t *session3 = NULL;
+
+ switch_channel_t *channel1 = NULL;
+ switch_channel_t *channel2 = NULL;
+ switch_channel_t *channel3 = NULL;
+
+ switch_status_t status;
+ switch_call_cause_t cause;
+ switch_stream_handle_t stream = { 0 };
+ char eavesdrop_command[256] = { 0 };
+ char rec_path[1024];
+ char rec_uuid[SWITCH_UUID_FORMATTED_LENGTH + 1] = { 0 };
+ char eaves_dialstr[512] = { 0 };
+
+ switch_uuid_str(rec_uuid, sizeof(rec_uuid));
+
+ /*parked 30 ms ptime */
+ status = switch_ivr_originate(NULL, &session1, &cause, "{ignore_early_media=true}sofia/gateway/eavestest/+15553332231", 2, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL);
+ fst_requires(session1);
+ fst_check(status == SWITCH_STATUS_SUCCESS);
+ channel1 = switch_core_session_get_channel(session1);
+ fst_requires(channel1);
+
+ snprintf(eaves_dialstr, sizeof(eaves_dialstr), "{ignore_early_media=true}{sip_h_X-UnitTestRecfile=%s}sofia/gateway/eavestest/+15553332240", rec_uuid);
+
+ /*eavesdropper 30 ms ptime*/
+ status = switch_ivr_originate(NULL, &session2, &cause, eaves_dialstr, 2, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL);
+ fst_requires(session2);
+ fst_check(status == SWITCH_STATUS_SUCCESS);
+ channel2 = switch_core_session_get_channel(session2);
+ fst_requires(channel2);
+
+ /*milliwatt tone 20 ms ptime*/
+ status = switch_ivr_originate(NULL, &session3, &cause, "{ignore_early_media=true}sofia/gateway/eavestest/+15553332226", 2, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL);
+ fst_requires(session3);
+ fst_check(status == SWITCH_STATUS_SUCCESS);
+ channel3 = switch_core_session_get_channel(session3);
+ fst_requires(channel3);
+
+ SWITCH_STANDARD_STREAM(stream);
+ switch_snprintf(eavesdrop_command, sizeof(eavesdrop_command), "uuid_bridge %s %s", switch_core_session_get_uuid(session1), switch_core_session_get_uuid(session2));
+ switch_api_execute("bgapi", eavesdrop_command, session1, &stream);
+ memset(eavesdrop_command, 0, sizeof(eavesdrop_command));
+ switch_snprintf(eavesdrop_command, sizeof(eavesdrop_command),"uuid_setvar_multi %s eavesdrop_enable_dtmf=false;eavesdrop_whisper_bleg=true;eavesdrop_whisper_aleg=false", switch_core_session_get_uuid(session3));
+ switch_api_execute("bgapi", eavesdrop_command, session3, &stream);
+ memset(eavesdrop_command, 0, sizeof(eavesdrop_command));
+ switch_snprintf(eavesdrop_command, sizeof(eavesdrop_command), "uuid_transfer %s 'eavesdrop:%s' inline", switch_core_session_get_uuid(session3), switch_core_session_get_uuid(session2));
+ switch_api_execute("bgapi", eavesdrop_command, session3, &stream);
+
+ sleep(2);
+
+ // codec reneg for eavesdropper
+ memset(eavesdrop_command, 0, sizeof(eavesdrop_command));
+ switch_snprintf(eavesdrop_command, sizeof(eavesdrop_command), "uuid_media_reneg %s = PCMU@20i", switch_core_session_get_uuid(session2));
+ switch_api_execute("bgapi", eavesdrop_command, session3, &stream);
+
+ sleep(1);
+
+ // codec reneg for eavesdroppee
+ memset(eavesdrop_command, 0, sizeof(eavesdrop_command));
+ switch_snprintf(eavesdrop_command, sizeof(eavesdrop_command), "uuid_media_reneg %s = PCMU@30i", switch_core_session_get_uuid(session3));
+ switch_api_execute("bgapi", eavesdrop_command, session3, &stream);
+ switch_safe_free(stream.data);
+
+ sleep(2);
+
+ snprintf(rec_path, sizeof(rec_path), "/tmp/eaves-%s.wav", rec_uuid);
+
+ fst_requires(switch_file_exists(rec_path, fst_pool) == SWITCH_STATUS_SUCCESS);
+
+ fst_requires(test_detect_long_tone_in_file(rec_path, 8000, 300, 30) == SWITCH_STATUS_SUCCESS);
+
+ unlink(rec_path);
+
+ switch_channel_hangup(channel1, SWITCH_CAUSE_NORMAL_CLEARING);
+ switch_channel_hangup(channel2, SWITCH_CAUSE_NORMAL_CLEARING);
+ switch_channel_hangup(channel3, SWITCH_CAUSE_NORMAL_CLEARING);
+
+ switch_core_session_rwunlock(session1);
+ switch_core_session_rwunlock(session2);
+ switch_core_session_rwunlock(session3);
+
+ }
+ FST_TEST_END()
+
+}
+FST_SUITE_END()
+}
+FST_CORE_END()
+
diff --git a/tests/unit/test_sofia.c b/tests/unit/test_sofia.c
new file mode 100644
index 0000000000..e45bd5d3fd
--- /dev/null
+++ b/tests/unit/test_sofia.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2018-2019, Signalwire, Inc. ALL RIGHTS RESERVED
+ * test_sofia.c -- Tests mod_sofia for memory leaks
+ */
+
+#include
+#include
+
+FST_CORE_DB_BEGIN("conf_sofia")
+{
+ FST_SUITE_BEGIN(switch_sofia)
+ {
+ FST_SETUP_BEGIN()
+ {
+ fst_requires_module("mod_sofia");
+ }
+ FST_SETUP_END()
+
+ FST_TEARDOWN_BEGIN()
+ {
+ }
+ FST_TEARDOWN_END()
+
+ FST_TEST_BEGIN(sofia_leaks)
+ {
+ }
+ FST_TEST_END()
+ }
+ FST_SUITE_END()
+}
+FST_CORE_END()