Merge branch 'master' into v1.6

This commit is contained in:
Ken Rice
2016-08-24 16:50:18 -05:00
94 changed files with 3115 additions and 896 deletions
+2 -2
View File
@@ -159,7 +159,7 @@ check_lt_ver() {
check_libtoolize() {
# check libtoolize availability
if [ -n "${LIBTOOL}" ]; then
libtoolize=${LIBTOOLIZE:-`dirname "${libtool}"`/libtoolize}
libtoolize=${LIBTOOLIZE:-`dirname "${LIBTOOL}"`/libtoolize}
else
libtoolize=${LIBTOOLIZE:-`${LIBDIR}/apr/build/PrintPath glibtoolize libtoolize libtoolize22 libtoolize15 libtoolize14`}
fi
@@ -190,7 +190,7 @@ check_make() {
make=`which make`
if [ -x "$make" ]; then
make_version=`$make --version | grep GNU`
make_version=`$make --version || true | grep GNU`
if [ $? -ne 0 ]; then
make=`which gmake`
if [ -x "$make" ]; then
+1
View File
@@ -40,6 +40,7 @@ applications/mod_httapi
#applications/mod_redis
#applications/mod_rss
applications/mod_sms
#applications/mod_sms_flowroute
#applications/mod_snapshot
#applications/mod_snom
#applications/mod_sonar
@@ -238,7 +238,7 @@
<param name="muted-sound" value="conference/conf-muted.wav"/>
<param name="unmuted-sound" value="conference/conf-unmuted.wav"/>
<param name="alone-sound" value="conference/conf-alone.wav"/>
<param name="moh-sound" value="local_stream://stereo"/>
<param name="moh-sound" value="$${hold_music}"/>
<param name="enter-sound" value="tone_stream://%(200,0,500,600,700)"/>
<param name="exit-sound" value="tone_stream://%(500,0,300,200,100,50,25)"/>
<param name="kicked-sound" value="conference/conf-kicked.wav"/>
@@ -71,6 +71,7 @@
<!--<load module="mod_fsk"/>-->
<!--<load module="mod_spy"/>-->
<!--<load module="mod_sms"/>-->
<!--<load module="mod_sms_flowroute"/>-->
<!--<load module="mod_smpp"/>-->
<!--<load module="mod_random"/>-->
<load module="mod_httapi"/>
@@ -100,6 +101,7 @@
<load module="mod_opus"/>
<!-- File Format Interfaces -->
<!--<load module="mod_av"/>-->
<load module="mod_sndfile"/>
<load module="mod_native_file"/>
<load module="mod_png"/>
@@ -0,0 +1,13 @@
<configuration name="sms_flowroute.conf" description="SMS_FLOWROUTE send configs">
<profiles>
<profile name="default">
<params>
<param name="host" value="https://api.flowroute.com/v2/messages"/>
<param name="debug" value="1"/>
<param name="port" value="8090"/>
<param name="access-key" value="ACCESS-KEY"/>
<param name="secret-key" value="SECRET-KEY"/>
</params>
</profile>
</profiles>
</configuration>
@@ -2,6 +2,12 @@
<settings>
<param name="debug" value="0"/>
<!-- seconds to wait before hanging up a disconnected channel -->
<!-- <param name="detach-timeout-sec" value="120"/> -->
<!-- enable broadcasting all FreeSWITCH events in Verto -->
<!-- <param name="enable-fs-events" value="false"/> -->
<!-- enable broadcasting FreeSWITCH presence events in Verto -->
<!-- <param name="enable-presence" value="true"/> -->
</settings>
<profiles>
+1 -1
View File
@@ -6,7 +6,7 @@
<condition field="to" expression="^(.*)$">
<!-- <action application="lua" data="test.lua"/> -->
<action application="reply" data="Hello, you said: ${_body}"/>
<action application="reply" data="Hello, you said: ${body}"/>
</condition>
</extension>
+25
View File
@@ -382,6 +382,31 @@
</extension>
<!-- STEREO 48kHz conferences / Video MCU -->
<extension name="cdquality_stereo_conferences">
<condition field="destination_number" expression="^(35\d{2}).*?-screen$">
<action application="answer"/>
<action application="send_display" data="FreeSWITCH Conference|$1"/>
<action application="set" data="conference_member_flags=join-vid-floor"/>
<action application="conference" data="$1-${domain_name}@video-mcu-stereo"/>
</condition>
</extension>
<extension name="conference-canvases" continue="true">
<condition field="destination_number" expression="(35\d{2})-canvas-(\d+)">
<action application="push" data="conference_member_flags=second-screen"/>
<action application="set" data="video_initial_watching_canvas=$2"/>
<action application="transfer" data="$1"/>
</condition>
</extension>
<extension name="conf mod">
<condition field="destination_number" expression="^6070-moderator$">
<action application="answer"/>
<action application="set" data="conference_member_flags=moderator"/>
<action application="conference" data="$1-${domain_name}@video-mcu-stereo"/>
</condition>
</extension>
<extension name="cdquality_conferences">
<condition field="destination_number" expression="^(35\d{2})$">
<action application="answer"/>
+31 -18
View File
@@ -597,7 +597,7 @@ AC_SUBST(SYS_XMLRPC_CFLAGS)
AC_SUBST(SYS_XMLRPC_LDFLAGS)
AM_CONDITIONAL([SYSTEM_XMLRPCC],[test "${enable_xmlrpcc}" = "yes"])
for luaversion in lua5.2 lua-5.2 lua5.1 lua-5.1 lua; do
for luaversion in lua5.2 lua-5.2 lua52 lua5.1 lua-5.1 lua; do
PKG_CHECK_MODULES([LUA],[${luaversion}],[have_lua=yes],[have_lua=no])
if test ${have_lua} = yes; then
break
@@ -793,7 +793,7 @@ case "$host" in
;;
*openbsd*)
APR_ADDTO(CPPFLAGS, -I/usr/local/include)
APR_ADDTO(LDFLAGS, -L/usr/local/lib)
APR_ADDTO(LDFLAGS, -L/usr/local/lib -ltermcap)
APR_ADDTO(SWITCH_AM_CFLAGS, -I/usr/local/include)
;;
*netbsd*)
@@ -1413,6 +1413,18 @@ PKG_CHECK_MODULES([AMQP], [librabbitmq >= 0.5.2],[
AM_CONDITIONAL([HAVE_AMQP],[true])],[
AC_MSG_RESULT([no]); AM_CONDITIONAL([HAVE_AMQP],[false])])
PKG_CHECK_MODULES([H2O], [libh2o-evloop >= 0.11.0],[
AM_CONDITIONAL([HAVE_H2O],[true])],[
AC_MSG_RESULT([no]); AM_CONDITIONAL([HAVE_H2O],[false])])
PKG_CHECK_MODULES([BROTLIENC], [libbrotlienc >= 0.1.0],[
AM_CONDITIONAL([HAVE_BROTLIENC],[true])],[
AC_MSG_RESULT([no]); AM_CONDITIONAL([HAVE_BROTLIENC],[false])])
PKG_CHECK_MODULES([BROTLIDEC], [libbrotlidec >= 0.1.0],[
AM_CONDITIONAL([HAVE_BROTLIDEC],[true])],[
AC_MSG_RESULT([no]); AM_CONDITIONAL([HAVE_BROTLIDEC],[false])])
PKG_CHECK_MODULES([TAP], [tap >= 0.1.0],[
AM_CONDITIONAL([HAVE_TAP],[true])],[
AC_MSG_RESULT([no]); AM_CONDITIONAL([HAVE_TAP],[false])])
@@ -1693,6 +1705,22 @@ else
AC_MSG_WARN([python support disabled, building mod_python will fail!])
fi
#
# SNMP checks for mod_snmp
#
AC_PATH_PROG([NET_SNMP_CONFIG], [net-snmp-config], [no])
if test "$NET_SNMP_CONFIG" != "no"; then
AC_MSG_CHECKING([for Net-SNMP libraries via net-snmp-config])
SNMP_LIBS="`$NET_SNMP_CONFIG --base-agent-libs`"
else
# net-snmp-config not in path, fallback to sensible defaults
SNMP_LIBS="-lnetsnmpmibs -lnetsnmpagent -lnetsnmp"
fi
# fix linking error on Solaris patched Net-SNMP
AS_CASE([$host], [*-solaris2*], [AC_CHECK_LIB([dladm], [dladm_open], [SNMP_LIBS="$SNMP_LIBS -ldladm"])])
AC_SUBST(SNMP_LIBS)
CHECK_ERLANG
# we never use this, and hard setting it will make cross compile work better
@@ -1746,6 +1774,7 @@ AC_CONFIG_FILES([Makefile
src/mod/applications/mod_rss/Makefile
src/mod/applications/mod_skel/Makefile
src/mod/applications/mod_sms/Makefile
src/mod/applications/mod_sms_flowroute/Makefile
src/mod/applications/mod_snapshot/Makefile
src/mod/applications/mod_snom/Makefile
src/mod/applications/mod_sonar/Makefile
@@ -1962,22 +1991,6 @@ esac
AC_OUTPUT
##
## Registering for ClueCon
##
if ! test -f noreg -o -f /noreg; then
echo ""
echo ""
echo $ECHO_N "Registering you for ClueCon http://www.cluecon.com $ECHO_C" 1>&6
sleep 1
echo $ECHO_N ".$ECHO_C" 1>&6
sleep 1
echo $ECHO_N ".$ECHO_C" 1>&6
sleep 1
AC_MSG_RESULT([ See you in August. ;-)])
echo ""
fi
##
## Configuration summary
##
+162 -2
View File
@@ -32,6 +32,7 @@ supported_debian_distros="wheezy jessie stretch sid"
supported_ubuntu_distros="trusty utopic"
supported_distros="$supported_debian_distros $supported_ubuntu_distros"
avoid_mods=(
applications/mod_sms_flowroute
applications/mod_limit
applications/mod_mongo
applications/mod_mp4
@@ -634,10 +635,12 @@ Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
freeswitch-mod-dingaling (= \${binary:Version}),
freeswitch-mod-loopback (= \${binary:Version}),
freeswitch-mod-portaudio (= \${binary:Version}),
freeswitch-mod-rtc (= \${binary:Version}),
freeswitch-mod-rtmp (= \${binary:Version}),
freeswitch-mod-skinny (= \${binary:Version}),
freeswitch-mod-skypopen (= \${binary:Version}),
freeswitch-mod-sofia (= \${binary:Version}),
freeswitch-mod-verto (= \${binary:Version}),
freeswitch-mod-cdr-csv (= \${binary:Version}),
freeswitch-mod-cdr-mongodb (= \${binary:Version}),
freeswitch-mod-cdr-sqlite (= \${binary:Version}),
@@ -704,6 +707,33 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch
This is a metapackage which depends on the packages needed to install
most FreeSWITCH codecs.
Package: freeswitch-meta-codecs-dbg
Architecture: any
Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
freeswitch-mod-amr-dbg (= \${binary:Version}),
freeswitch-mod-amrwb-dbg (= \${binary:Version}),
freeswitch-mod-b64-dbg (= \${binary:Version}),
freeswitch-mod-bv-dbg (= \${binary:Version}),
freeswitch-mod-codec2-dbg (= \${binary:Version}),
freeswitch-mod-dahdi-codec-dbg (= \${binary:Version}),
freeswitch-mod-g723-1-dbg (= \${binary:Version}),
freeswitch-mod-g729-dbg (= \${binary:Version}),
freeswitch-mod-h26x-dbg (= \${binary:Version}),
freeswitch-mod-isac-dbg (= \${binary:Version}),
freeswitch-mod-mp4v-dbg (= \${binary:Version}),
freeswitch-mod-opus-dbg (= \${binary:Version}),
freeswitch-mod-silk-dbg (= \${binary:Version}),
freeswitch-mod-spandsp-dbg (= \${binary:Version}),
freeswitch-mod-theora-dbg (= \${binary:Version}),
Suggests:
freeswitch-mod-ilbc-dbg (= \${binary:Version}),
freeswitch-mod-siren-dbg (= \${binary:Version})
Description: Cross-Platform Scalable Multi-Protocol Soft Switch
$(debian_wrap "${fs_description}")
.
This is a metapackage which depends on the packages needed to install
most FreeSWITCH codecs.
Package: freeswitch-meta-conf
Architecture: all
Depends: \${misc:Depends},
@@ -759,11 +789,141 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch
This is a metapackage which depends on all mod_say languages for
FreeSWITCH.
Package: freeswitch-meta-mod-say-dbg
Architecture: any
Depends: \${misc:Depends},
freeswitch-mod-say-de-dbg (= \${binary:Version}),
freeswitch-mod-say-en-dbg (= \${binary:Version}),
freeswitch-mod-say-es-dbg (= \${binary:Version}),
freeswitch-mod-say-fa-dbg (= \${binary:Version}),
freeswitch-mod-say-fr-dbg (= \${binary:Version}),
freeswitch-mod-say-he-dbg (= \${binary:Version}),
freeswitch-mod-say-hr-dbg (= \${binary:Version}),
freeswitch-mod-say-hu-dbg (= \${binary:Version}),
freeswitch-mod-say-it-dbg (= \${binary:Version}),
freeswitch-mod-say-ja-dbg (= \${binary:Version}),
freeswitch-mod-say-nl-dbg (= \${binary:Version}),
freeswitch-mod-say-pl-dbg (= \${binary:Version}),
freeswitch-mod-say-pt-dbg (= \${binary:Version}),
freeswitch-mod-say-ru-dbg (= \${binary:Version}),
freeswitch-mod-say-th-dbg (= \${binary:Version}),
freeswitch-mod-say-zh-dbg (= \${binary:Version}),
Description: Cross-Platform Scalable Multi-Protocol Soft Switch
$(debian_wrap "${fs_description}")
.
This is a metapackage which depends on all mod_say languages for
FreeSWITCH.
Package: freeswitch-meta-all-dbg
Architecture: any
Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
freeswitch-meta-codecs-dbg (= \${binary:Version}),
freeswitch-meta-lang-dbg (= \${binary:Version}),
freeswitch-meta-mod-say (= \${binary:Version}),
freeswitch-mod-abstraction-dbg (= \${binary:Version}),
freeswitch-mod-avmd-dbg (= \${binary:Version}),
freeswitch-mod-av-dbg (= \${binary:Version}),
freeswitch-mod-blacklist-dbg (= \${binary:Version}),
freeswitch-mod-callcenter-dbg (= \${binary:Version}),
freeswitch-mod-cidlookup-dbg (= \${binary:Version}),
freeswitch-mod-commands-dbg (= \${binary:Version}),
freeswitch-mod-conference-dbg (= \${binary:Version}),
freeswitch-mod-curl-dbg (= \${binary:Version}),
freeswitch-mod-db-dbg (= \${binary:Version}),
freeswitch-mod-directory-dbg (= \${binary:Version}),
freeswitch-mod-distributor-dbg (= \${binary:Version}),
freeswitch-mod-dptools-dbg (= \${binary:Version}),
freeswitch-mod-easyroute-dbg (= \${binary:Version}),
freeswitch-mod-enum-dbg (= \${binary:Version}),
freeswitch-mod-esf-dbg (= \${binary:Version}),
freeswitch-mod-esl-dbg (= \${binary:Version}),
freeswitch-mod-expr-dbg (= \${binary:Version}),
freeswitch-mod-fifo-dbg (= \${binary:Version}),
freeswitch-mod-fsk-dbg (= \${binary:Version}),
freeswitch-mod-fsv-dbg (= \${binary:Version}),
freeswitch-mod-hash-dbg (= \${binary:Version}),
freeswitch-mod-httapi-dbg (= \${binary:Version}),
freeswitch-mod-http-cache-dbg (= \${binary:Version}),
freeswitch-mod-lcr-dbg (= \${binary:Version}),
freeswitch-mod-memcache-dbg (= \${binary:Version}),
freeswitch-mod-nibblebill-dbg (= \${binary:Version}),
freeswitch-mod-oreka-dbg (= \${binary:Version}),
freeswitch-mod-png-dbg (= \${binary:Version}),
freeswitch-mod-redis-dbg (= \${binary:Version}),
freeswitch-mod-rss-dbg (= \${binary:Version}),
freeswitch-mod-sms-dbg (= \${binary:Version}),
freeswitch-mod-snapshot-dbg (= \${binary:Version}),
freeswitch-mod-snom-dbg (= \${binary:Version}),
freeswitch-mod-sonar-dbg (= \${binary:Version}),
freeswitch-mod-soundtouch-dbg (= \${binary:Version}),
freeswitch-mod-spandsp-dbg (= \${binary:Version}),
freeswitch-mod-spy-dbg (= \${binary:Version}),
freeswitch-mod-stress-dbg (= \${binary:Version}),
freeswitch-mod-translate-dbg (= \${binary:Version}),
freeswitch-mod-valet-parking-dbg (= \${binary:Version}),
freeswitch-mod-voicemail-dbg (= \${binary:Version}),
freeswitch-mod-voicemail-ivr-dbg (= \${binary:Version}),
freeswitch-mod-flite-dbg (= \${binary:Version}),
freeswitch-mod-pocketsphinx-dbg (= \${binary:Version}),
freeswitch-mod-tts-commandline-dbg (= \${binary:Version}),
freeswitch-mod-unimrcp-dbg (= \${binary:Version}),
freeswitch-mod-dialplan-asterisk-dbg (= \${binary:Version}),
freeswitch-mod-dialplan-directory-dbg (= \${binary:Version}),
freeswitch-mod-dialplan-xml-dbg (= \${binary:Version}),
freeswitch-mod-ldap-dbg (= \${binary:Version}),
freeswitch-mod-dingaling-dbg (= \${binary:Version}),
freeswitch-mod-loopback-dbg (= \${binary:Version}),
freeswitch-mod-portaudio-dbg (= \${binary:Version}),
freeswitch-mod-rtc-dbg (= \${binary:Version}),
freeswitch-mod-rtmp-dbg (= \${binary:Version}),
freeswitch-mod-skinny-dbg (= \${binary:Version}),
freeswitch-mod-skypopen-dbg (= \${binary:Version}),
freeswitch-mod-sofia-dbg (= \${binary:Version}),
freeswitch-mod-verto-dbg (= \${binary:Version}),
freeswitch-mod-cdr-csv-dbg (= \${binary:Version}),
freeswitch-mod-cdr-mongodb-dbg (= \${binary:Version}),
freeswitch-mod-cdr-sqlite-dbg (= \${binary:Version}),
freeswitch-mod-erlang-event-dbg (= \${binary:Version}),
freeswitch-mod-event-multicast-dbg (= \${binary:Version}),
freeswitch-mod-event-socket-dbg (= \${binary:Version}),
freeswitch-mod-json-cdr-dbg (= \${binary:Version}),
freeswitch-mod-kazoo-dbg (= \${binary:Version}),
freeswitch-mod-snmp-dbg (= \${binary:Version}),
freeswitch-mod-local-stream-dbg (= \${binary:Version}),
freeswitch-mod-native-file-dbg (= \${binary:Version}),
freeswitch-mod-portaudio-stream-dbg (= \${binary:Version}),
freeswitch-mod-shell-stream-dbg (= \${binary:Version}),
freeswitch-mod-sndfile-dbg (= \${binary:Version}),
freeswitch-mod-tone-stream-dbg (= \${binary:Version}),
freeswitch-mod-java-dbg (= \${binary:Version}),
freeswitch-mod-lua-dbg (= \${binary:Version}),
freeswitch-mod-perl-dbg (= \${binary:Version}),
freeswitch-mod-python-dbg (= \${binary:Version}),
freeswitch-mod-yaml-dbg (= \${binary:Version}),
freeswitch-mod-console-dbg (= \${binary:Version}),
freeswitch-mod-logfile-dbg (= \${binary:Version}),
freeswitch-mod-syslog-dbg (= \${binary:Version}),
freeswitch-mod-posix-timer-dbg (= \${binary:Version}),
freeswitch-mod-timerfd-dbg (= \${binary:Version}),
freeswitch-mod-xml-cdr-dbg (= \${binary:Version}),
freeswitch-mod-xml-curl-dbg (= \${binary:Version}),
freeswitch-mod-xml-rpc-dbg (= \${binary:Version}),
freeswitch-mod-xml-scgi-dbg (= \${binary:Version}),
Recommends:
Suggests:
freeswitch-mod-vmd-dbg (= \${binary:Version}),
freeswitch-mod-vlc-dbg (= \${binary:Version}),
Description: Cross-Platform Scalable Multi-Protocol Soft Switch
$(debian_wrap "${fs_description}")
.
This is a metapackage which recommends or suggests all packaged
FreeSWITCH modules.
Package: freeswitch-all-dbg
Section: debug
Priority: extra
Architecture: any
Depends: \${misc:Depends}, freeswitch-meta-all (= \${binary:Version})
Depends: \${misc:Depends}, freeswitch-meta-all (= \${binary:Version}), freeswitch-meta-all-dbg (= \${binary:Version})
Description: debugging symbols for FreeSWITCH
$(debian_wrap "${fs_description}")
.
@@ -840,7 +1000,7 @@ if [ ${use_sysvinit} = "true" ]; then
cat <<EOF
Package: freeswitch-sysvinit
Architecture: all
Depends: \${misc:Depends}, lsb-base (>= 3.0-6), sysvinit
Depends: \${misc:Depends}, lsb-base (>= 3.0-6), sysvinit | sysvinit-utils
Conflicts: freeswitch-init
Provides: freeswitch-init
Description: FreeSWITCH SysV init script
+1
View File
@@ -1935,6 +1935,7 @@ fi
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/shout.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/skinny.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/smpp.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/sms_flowroute.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/sofia.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/spandsp.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/switch.conf.xml
+1 -1
View File
@@ -1089,7 +1089,7 @@
return [w, h];
}
var resList = [[320, 180], [320, 240], [640, 360], [640, 480], [1280, 720], [1920, 1080]];
var resList = [[160, 120], [320, 180], [320, 240], [640, 360], [640, 480], [1280, 720], [1920, 1080]];
var resI = 0;
var ttl = 0;
@@ -88,7 +88,7 @@
<script src="bower_components/angular-directive.g-signin/google-plus-signin.js"></script>
<script src="bower_components/angular-fullscreen/src/angular-fullscreen.js"></script>
<script src="bower_components/ngstorage/ngStorage.js"></script>
<script src="bower_components/momentjs/moment.js"></script>
<script src="bower_components/moment/moment.js"></script>
<script src="bower_components/humanize-duration/humanize-duration.js"></script>
<script src="bower_components/angular-timer/dist/angular-timer.js"></script>
<script src="bower_components/angular-tooltips/dist/angular-tooltips.min.js"></script>
@@ -292,7 +292,10 @@
$scope.closeSettings = function() {
var settingsEl = angular.element(document.querySelector('#settings'));
settingsEl.removeClass('toggled');
if (settingsEl.hasClass('toggled')) {
settingsEl.removeClass('toggled');
$rootScope.$emit('toggledSettings', settingsEl.hasClass('toggled'));
}
};
$scope.goFullscreen = function() {
@@ -3,6 +3,11 @@
/* Controllers */
var videoQuality = [];
var videoQualitySource = [{
id: 'qqvga',
label: 'QQVGA 160x120',
width: 160,
height: 120
}, {
id: 'qvga',
label: 'QVGA 320x240',
width: 320,
@@ -35,6 +40,10 @@ var videoQualitySource = [{
}, ];
var videoResolution = {
qqvga: {
width: 160,
height: 120
},
qvga: {
width: 320,
height: 240
@@ -910,7 +919,10 @@ vertoService.service('verto', ['$rootScope', '$cookieStore', '$location', 'stora
storage.data.useDedenc = false;
storage.data.vidQual = 'hd';
if (upBand < 512) {
if (upBand < 256) {
storage.data.vidQual = 'qqvga';
}
else if (upBand < 512) {
storage.data.vidQual = 'qvga';
}
else if (upBand < 1024) {
+4
View File
@@ -394,6 +394,10 @@ if ($('#devices').is(':visible')) {
<div >
<fieldset data-role="controlgroup" data-type="horizontal">
<legend><b>Video Quality</b>:</legend>
<input type="radio" name="vqual" id="vqual_qqvga" value="qqvga">
<label for="vqual_qqvga">QQVGA 160x120</label>
<input type="radio" name="vqual" id="vqual_qvga" value="qvga">
<label for="vqual_qvga">QVGA 320x240</label>
+20 -2
View File
@@ -21,7 +21,7 @@ var master = null;
var canvas_id = null;
var second_screen = null;
var save_settings = true;
var vertoHandle = null;
var video_screen = "webcam"
$( ".selector" ).pagecontainer({ "theme": "a" });
@@ -140,7 +140,12 @@ function real_size() {
function check_vid_res()
{
if ($("#vqual_qvga").is(':checked')) {
if ($("#vqual_qqvga").is(':checked')) {
vid_width = 160;
vid_height = 120;
local_vid_width = 80;
local_vid_height = 60;
} else if ($("#vqual_qvga").is(':checked')) {
vid_width = 320;
vid_height = 240;
local_vid_width = 160;
@@ -218,6 +223,10 @@ function do_speed_test(fn)
$("#vqual_qvga").prop("checked", true);
vid = "320x240";
}
if (outgoingBandwidth < 256) {
$("#vqual_qqvga").prop("checked", true);
vid = "160x120";
}
//}
if (incomingBandwidth === "default") {
@@ -1315,6 +1324,15 @@ function init() {
$("#vqual_qqvga").prop("checked", vqual === "qqvga").change(function(e) {
if ($("#vqual_qqvga").is(':checked')) {
vqual = "qqvga";
$.cookie("verto_demo_vqual", vqual, {
expires: 365
});
}
});
$("#vqual_qvga").prop("checked", vqual === "qvga").change(function(e) {
if ($("#vqual_qvga").is(':checked')) {
vqual = "qvga";
@@ -1021,7 +1021,6 @@ static void ftdm_r2_on_chan_log(openr2_chan_t *r2chan, const char *file, const c
static int ftdm_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
{
ftdm_sigmsg_t sigev;
ftdm_r2_data_t *r2data;
ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
ftdm_size_t collected_len = R2CALL(ftdmchan)->dnis_index;
@@ -1039,7 +1038,6 @@ static int ftdm_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
sigev.span_id = ftdmchan->span_id;
sigev.channel = ftdmchan;
sigev.event_id = FTDM_SIGEVENT_COLLECTED_DIGIT;
r2data = ftdmchan->span->signal_data;
if (ftdm_span_send_signal(ftdmchan->span, &sigev) == FTDM_BREAK) {
ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Requested to stop getting DNIS. Current DNIS = %s\n", ftdmchan->caller_data.dnis.digits);
return OR2_STOP_DNIS_REQUEST;
+1
View File
@@ -4,6 +4,7 @@
Makefile
config.mk
libs-*.mk
libs.doxy
vp8_rtcd.h
vp9_rtcd.h
vpx_config.asm
+1 -1
View File
@@ -1 +1 @@
Wed Apr 27 16:01:46 EDT 2016
Tue Aug 16 13:39:03 CDT 2016
@@ -1397,6 +1397,8 @@ void sdp_media_transport(sdp_media_t *m, char const *s)
m->m_proto = sdp_proto_rtp, m->m_proto_name = "RTP/AVP";
else if (su_casematch(s, "RTP/SAVP"))
m->m_proto = sdp_proto_srtp, m->m_proto_name = "RTP/SAVP";
else if (su_casematch(s, "UDP/TLS/RTP/SAVP"))
m->m_proto = sdp_proto_srtp, m->m_proto_name = "RTP/SAVP";
else if (su_casematch(s, "RTP/SAVPF"))
m->m_proto = sdp_proto_extended_srtp, m->m_proto_name = "RTP/SAVPF";
else if (su_casematch(s, "UDP/TLS/RTP/SAVPF"))
@@ -1061,9 +1061,11 @@ int soa_sdp_mode_set(sdp_session_t const *user,
continue;
}
send_mode = (sdp_mode_t)(um->m_mode & sdp_sendonly);
if (rm)
send_mode = (rm->m_mode & sdp_recvonly) ? sdp_sendonly : 0;
if (um->m_mode) { /* when its inactive, keep it inactive */
send_mode = (sdp_mode_t)(um->m_mode & sdp_sendonly);
if (rm)
send_mode = (rm->m_mode & sdp_recvonly) ? sdp_sendonly : 0;
} else send_mode = um->m_mode;
recv_mode = (sdp_mode_t)(um->m_mode & sdp_recvonly);
+1 -1
View File
@@ -398,7 +398,7 @@ uint64_t su_nanocounter(void)
static int init = 0;
static clockid_t cpu = CLOCK_REALTIME;
# define CLOCK_GETTIMEOFDAY 0xdedbeefUL
# define CLOCK_GETTIMEOFDAY ((clockid_t)-1)
if (init == 0) {
init = 1;
@@ -467,7 +467,7 @@ int tport_capt_msg_hepv2 (tport_t const *self, msg_t *msg, size_t n,
struct hep_ip6hdr hep_ip6header = {{{{0}}}};
#endif
int eth_frame_len = 16000;
size_t i, dst = 0;
size_t i, dst = 1;
tport_master_t *mr;
assert(self); assert(msg);
@@ -501,25 +501,25 @@ int tport_capt_msg_hepv2 (tport_t const *self, msg_t *msg, size_t n,
else hep_header.hp_p = IPPROTO_UDP; /* DEFAULT UDP */
/* Check destination */
if(strncmp("sent", what, 4) == 0) dst = 1;
if(strncmp("sent", what, 4) == 0) dst = 0;
/* copy destination and source IPs*/
if(su->su_family == AF_INET) {
memcpy(dst ? &hep_ipheader.hp_dst : &hep_ipheader.hp_src, &su->su_sin.sin_addr.s_addr, sizeof(su->su_sin.sin_addr.s_addr));
memcpy(dst ? &hep_ipheader.hp_src : &hep_ipheader.hp_dst, &su_self->su_sin.sin_addr.s_addr, sizeof(su_self->su_sin.sin_addr.s_addr));
memcpy(dst ? &hep_ipheader.hp_src : &hep_ipheader.hp_dst, &su->su_sin.sin_addr.s_addr, sizeof(su->su_sin.sin_addr.s_addr));
memcpy(dst ? &hep_ipheader.hp_dst : &hep_ipheader.hp_src, &su_self->su_sin.sin_addr.s_addr, sizeof(su_self->su_sin.sin_addr.s_addr));
hep_header.hp_l += sizeof(struct hep_iphdr);
}
#if SU_HAVE_IN6
else {
memcpy(dst ? &hep_ip6header.hp6_dst : &hep_ip6header.hp6_src, &su->su_sin.sin_addr.s_addr, sizeof(su->su_sin.sin_addr.s_addr));
memcpy(dst ? &hep_ip6header.hp6_src : &hep_ip6header.hp6_dst, &su_self->su_sin.sin_addr.s_addr, sizeof(su_self->su_sin.sin_addr.s_addr));
memcpy(dst ? &hep_ip6header.hp6_src : &hep_ip6header.hp6_dst, &su->su_sin.sin_addr.s_addr, sizeof(su->su_sin.sin_addr.s_addr));
memcpy(dst ? &hep_ip6header.hp6_dst : &hep_ip6header.hp6_src, &su_self->su_sin.sin_addr.s_addr, sizeof(su_self->su_sin.sin_addr.s_addr));
hep_header.hp_l += sizeof(struct hep_ip6hdr);
}
#endif
hep_header.hp_dport = dst ? su->su_port : su_self->su_port;
hep_header.hp_sport = dst ? su_self->su_port : su->su_port;
hep_header.hp_dport = dst ? su_self->su_port : su->su_port;
hep_header.hp_sport = dst ? su->su_port : su_self->su_port;
if (hep_header.hp_v == 2){
hep_header.hp_l += sizeof(struct hep_timehdr);
@@ -605,7 +605,7 @@ int tport_capt_msg_hepv3 (tport_t const *self, msg_t *msg, size_t n,
#endif
int eth_frame_len = 16000;
size_t i, dst = 0;
size_t i, dst = 1;
tport_master_t *mr;
assert(self); assert(msg);
@@ -649,7 +649,7 @@ int tport_capt_msg_hepv3 (tport_t const *self, msg_t *msg, size_t n,
hg->ip_proto.chunk.length = htons(sizeof(hg->ip_proto));
/* Check destination */
if(strncmp("sent", what, 4) == 0) dst = 1;
if(strncmp("sent", what, 4) == 0) dst = 0;
/* copy destination and source IPs*/
if(su->su_family == AF_INET) {
@@ -657,13 +657,13 @@ int tport_capt_msg_hepv3 (tport_t const *self, msg_t *msg, size_t n,
/* SRC IP */
src_ip4.chunk.vendor_id = htons(0x0000);
src_ip4.chunk.type_id = htons(0x0003);
memcpy(dst ? &dst_ip4.data : &src_ip4.data, &su->su_sin.sin_addr.s_addr, sizeof(su->su_sin.sin_addr.s_addr));
memcpy(dst ? &src_ip4.data : &dst_ip4.data, &su->su_sin.sin_addr.s_addr, sizeof(su->su_sin.sin_addr.s_addr));
src_ip4.chunk.length = htons(sizeof(src_ip4));
/* DST IP */
dst_ip4.chunk.vendor_id = htons(0x0000);
dst_ip4.chunk.type_id = htons(0x0004);
memcpy(dst ? &src_ip4.data : &dst_ip4.data, &su_self->su_sin.sin_addr.s_addr, sizeof(su_self->su_sin.sin_addr.s_addr));
memcpy(dst ? &dst_ip4.data : &src_ip4.data, &su_self->su_sin.sin_addr.s_addr, sizeof(su_self->su_sin.sin_addr.s_addr));
dst_ip4.chunk.length = htons(sizeof(dst_ip4));
iplen = sizeof(dst_ip4) + sizeof(src_ip4);
@@ -674,13 +674,13 @@ int tport_capt_msg_hepv3 (tport_t const *self, msg_t *msg, size_t n,
/* SRC IPv6 */
src_ip6.chunk.vendor_id = htons(0x0000);
src_ip6.chunk.type_id = htons(0x0005);
memcpy(dst ? &dst_ip6.data : &src_ip6.data, &su->su_sin.sin_addr.s_addr, sizeof(su->su_sin.sin_addr.s_addr));
memcpy(dst ? &src_ip6.data : &dst_ip6.data, &su->su_sin.sin_addr.s_addr, sizeof(su->su_sin.sin_addr.s_addr));
src_ip6.chunk.length = htons(sizeof(src_ip6));
/* DST IPv6 */
dst_ip6.chunk.vendor_id = htons(0x0000);
dst_ip6.chunk.type_id = htons(0x0006);
memcpy(dst ? &src_ip6.data : &dst_ip6.data, &su_self->su_sin.sin_addr.s_addr, sizeof(su_self->su_sin.sin_addr.s_addr));
memcpy(dst ? &dst_ip6.data : &src_ip6.data, &su_self->su_sin.sin_addr.s_addr, sizeof(su_self->su_sin.sin_addr.s_addr));
dst_ip6.chunk.length = htons(sizeof(dst_ip6));
iplen = sizeof(dst_ip6) + sizeof(src_ip6);
@@ -461,6 +461,7 @@ int tport_ws_init_secondary(tport_t *self, int socket, int accepted,
tport_ws_t *wstp = (tport_ws_t *)self;
self->tp_has_connection = 1;
self->tp_params->tpp_keepalive = 5000;
/* override the default 30 minute timeout on tport connections */
self->tp_params->tpp_idle = UINT_MAX;
@@ -493,10 +494,12 @@ int tport_ws_init_secondary(tport_t *self, int socket, int accepted,
return *return_reason = "WS_INIT", -1;
}
wstp->connected = time(NULL);
wstp->ws_initialized = 1;
self->tp_pre_framed = 1;
tport_set_secondary_timer(self);
return 0;
}
@@ -592,6 +595,32 @@ int tport_ws_next_timer(tport_t *self,
su_time_t *return_target,
char const **return_why)
{
tport_ws_t *wstp = (tport_ws_t *)self;
int ll = establish_logical_layer(&wstp->ws);
int punt = 0;
if (ll == -1) {
punt = 1;
} else if (ll < 0) {
time_t now = time(NULL);
if (now - wstp->connected > 5) {
punt = 2;
}
} else {
self->tp_params->tpp_keepalive = 0;
}
if (punt) {
tport_close(self);
SU_DEBUG_7(("%s(%p): %s to " TPN_FORMAT "%s\n",
__func__, (void *)self,
(punt == 2 ? "Timeout establishing SSL" : "Error establishing SSL"), TPN_ARGS(self->tp_name), ""));
return -1;
}
return
tport_next_recv_timeout(self, return_target, return_why) |
tport_next_keepalive(self, return_target, return_why);
@@ -59,6 +59,7 @@ typedef struct tport_ws_s {
char wstp_buffer[65536];
size_t wstp_buflen;
SU_S8_T ws_initialized;
time_t connected;
unsigned ws_secure:1;
unsigned:0;
} tport_ws_t;
+1 -1
View File
@@ -500,7 +500,7 @@ static int restore_socket(ws_socket_t sock)
#endif
static int establish_logical_layer(wsh_t *wsh)
int establish_logical_layer(wsh_t *wsh)
{
if (!wsh->sanity) {
+1 -1
View File
@@ -119,7 +119,7 @@ typedef struct wsh_s {
ssize_t ws_send_buf(wsh_t *wsh, ws_opcode_t oc);
ssize_t ws_feed_buf(wsh_t *wsh, void *data, size_t bytes);
int establish_logical_layer(wsh_t *wsh);
ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block);
ssize_t ws_raw_write(wsh_t *wsh, void *data, size_t bytes);
ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data);
+6 -3
View File
@@ -284,12 +284,15 @@ aes_icm_set_octet(aes_icm_ctx_t *c,
err_status_t
aes_icm_set_iv(aes_icm_ctx_t *c, void *iv, int direction) {
v128_t *nonce = (v128_t *) iv;
v128_t nonce;
/* set nonce (for alignment) */
v128_copy_octet_string(&nonce, iv);
debug_print(mod_aes_icm,
"setting iv: %s", v128_hex_string(nonce));
"setting iv: %s", v128_hex_string(&nonce));
v128_xor(&c->counter, &c->offset, nonce);
v128_xor(&c->counter, &c->offset, &nonce);
debug_print(mod_aes_icm,
"set_counter: %s", v128_hex_string(&c->counter));
+6 -3
View File
@@ -263,11 +263,14 @@ err_status_t aes_icm_openssl_context_init (aes_icm_ctx_t *c, const uint8_t *key)
err_status_t aes_icm_openssl_set_iv (aes_icm_ctx_t *c, void *iv, int dir)
{
const EVP_CIPHER *evp;
v128_t *nonce = (v128_t*)iv;
v128_t nonce;
debug_print(mod_aes_icm, "setting iv: %s", v128_hex_string(nonce));
/* set nonce (for alignment) */
v128_copy_octet_string(&nonce, iv);
v128_xor(&c->counter, &c->offset, nonce);
debug_print(mod_aes_icm, "setting iv: %s", v128_hex_string(&nonce));
v128_xor(&c->counter, &c->offset, &nonce);
debug_print(mod_aes_icm, "set_counter: %s", v128_hex_string(&c->counter));
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -64,8 +64,6 @@ typedef enum {
SCMF_CODEC_GREEDY,
SCMF_CODEC_SCROOGE,
SCMF_DISABLE_HOLD,
SCMF_RENEG_ON_HOLD,
SCMF_RENEG_ON_REINVITE,
SCMF_LIBERAL_DTMF,
SCMF_SUPPRESS_CNG,
SCMF_DISABLE_RTP_AUTOADJ,
@@ -75,6 +73,7 @@ typedef enum {
SCMF_RTP_AUTOFLUSH_DURING_BRIDGE,
SCMF_MULTI_ANSWER_AUDIO,
SCMF_MULTI_ANSWER_VIDEO,
SCMF_RECV_SDP,
SCMF_MAX
} switch_core_media_flag_t;
@@ -230,6 +229,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_choose_ports(switch_core_sessi
SWITCH_DECLARE(void) switch_core_media_check_dtmf_type(switch_core_session_t *session);
SWITCH_DECLARE(void) switch_core_media_absorb_sdp(switch_core_session_t *session);
SWITCH_DECLARE(switch_status_t) switch_core_media_proxy_remote_addr(switch_core_session_t *session, const char *sdp_str);
SWITCH_DECLARE(void) switch_core_media_parse_media_flags(switch_core_session_t *session);
SWITCH_DECLARE(void) switch_core_media_deactivate_rtp(switch_core_session_t *session);
SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_session_t *session);
SWITCH_DECLARE(switch_status_t) switch_core_media_ext_address_lookup(switch_core_session_t *session, char **ip, switch_port_t *port, const char *sourceip);
+2 -2
View File
@@ -352,10 +352,10 @@ SWITCH_DECLARE(void) switch_img_find_position(switch_img_position_t pos, int sw,
*
* \param[in] src The image descriptor
* \param[in] dest The target memory address
* \param[in] size The size of target memory address used for bounds check
* \param[in] stride Bytes in a row for the destination. Pass 0 if the buffer has contiguous rows. Can be negative. A multiple of 16 is optimal.
* \param[in] fmt The target format
*/
SWITCH_DECLARE(switch_status_t) switch_img_to_raw(switch_image_t *src, void *dest, switch_size_t size, switch_img_fmt_t fmt);
SWITCH_DECLARE(switch_status_t) switch_img_to_raw(switch_image_t *src, void *dest, int stride, switch_img_fmt_t fmt);
/*!\brief convert raw memory to switch_img_t
*
* if dest is NULL then a new img is created, user should destroy it later,
+6
View File
@@ -414,6 +414,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_tone_detect_session(switch_core_sessi
SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *session, switch_file_handle_t *fh, const char *file,
switch_input_args_t *args);
SWITCH_DECLARE(switch_status_t) switch_ivr_detect_audio(switch_core_session_t *session, uint32_t thresh, uint32_t audio_hits,
uint32_t timeout_ms, const char *file);
SWITCH_DECLARE(switch_status_t) switch_ivr_detect_silence(switch_core_session_t *session, uint32_t thresh, uint32_t silence_hits,
uint32_t timeout_ms, const char *file);
SWITCH_DECLARE(switch_status_t) switch_ivr_wait_for_silence(switch_core_session_t *session, uint32_t thresh, uint32_t silence_hits,
uint32_t listen_hits, uint32_t timeout_ms, const char *file);
+3
View File
@@ -139,6 +139,9 @@ typedef int gid_t;
#ifndef __BYTE_ORDER
#ifdef SWITCH_BYTE_ORDER
#define __BYTE_ORDER SWITCH_BYTE_ORDER
/* solaris */
#elif defined(_BIG_ENDIAN)
#define __BYTE_ORDER __BIG_ENDIAN
#else
#define __BYTE_ORDER __LITTLE_ENDIAN
#endif
+6 -2
View File
@@ -766,6 +766,7 @@ typedef enum {
SWITCH_RTP_FLAG_NACK,
SWITCH_RTP_FLAG_TMMBR,
SWITCH_RTP_FLAG_GEN_TS_DELTA,
SWITCH_RTP_FLAG_DETECT_SSRC,
SWITCH_RTP_FLAG_INVALID
} switch_rtp_flag_t;
@@ -1509,6 +1510,7 @@ typedef enum {
CF_3P_MEDIA_REQUESTED,
CF_3P_NOMEDIA_REQUESTED,
CF_3P_NOMEDIA_REQUESTED_BLEG,
CF_IMAGE_SDP,
CF_VIDEO_SDP_RECVD,
/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
/* IF YOU ADD NEW ONES CHECK IF THEY SHOULD PERSIST OR ZERO THEM IN switch_core_session.c switch_core_session_request_xml() */
@@ -1627,7 +1629,8 @@ typedef enum {
SWITCH_CODEC_FLAG_AAL2 = (1 << 6),
SWITCH_CODEC_FLAG_PASSTHROUGH = (1 << 7),
SWITCH_CODEC_FLAG_READY = (1 << 8),
SWITCH_CODEC_FLAG_HAS_PLC = (1 << 15)
SWITCH_CODEC_FLAG_HAS_PLC = (1 << 15),
SWITCH_CODEC_FLAG_VIDEO_PATCHING = (1 << 16)
} switch_codec_flag_enum_t;
typedef uint32_t switch_codec_flag_t;
@@ -1769,7 +1772,8 @@ typedef enum {
SMBF_WRITE_VIDEO_STREAM = (1 << 20),
SMBF_VIDEO_PATCH = (1 << 21),
SMBF_SPY_VIDEO_STREAM = (1 << 22),
SMBF_SPY_VIDEO_STREAM_BLEG = (1 << 23)
SMBF_SPY_VIDEO_STREAM_BLEG = (1 << 23),
SMBF_READ_VIDEO_PATCH = (1 << 24)
} switch_media_bug_flag_enum_t;
typedef uint32_t switch_media_bug_flag_t;
+4 -1
View File
@@ -693,7 +693,10 @@ static switch_status_t consume_h263_bitstream(h264_codec_context_t *context, swi
#endif
}
if (!context->nalus[context->nalu_current_index].len) frame->m = 1;
if (!context->nalus[context->nalu_current_index].len) {
av_packet_unref(&context->encoder_avpacket);
frame->m = 1;
}
#if 0
{
+13
View File
@@ -1239,6 +1239,7 @@ SWITCH_STANDARD_API(av_format_api_function)
struct av_file_context {
switch_memory_pool_t *pool;
switch_mutex_t *mutex;
switch_thread_cond_t *cond;
switch_buffer_t *buf;
switch_buffer_t *audio_buffer;
switch_timer_t video_timer;
@@ -1261,6 +1262,7 @@ struct av_file_context {
record_helper_t eh;
switch_thread_t *file_read_thread;
int file_read_thread_running;
int file_read_thread_started;
switch_time_t video_start_time;
switch_image_t *last_img;
int read_fps;
@@ -1417,7 +1419,11 @@ static void *SWITCH_THREAD_FUNC file_read_thread_run(switch_thread_t *thread, vo
int sync = 0;
int eof = 0;
switch_mutex_lock(context->mutex);
context->file_read_thread_started = 1;
context->file_read_thread_running = 1;
switch_thread_cond_signal(context->cond);
switch_mutex_unlock(context->mutex);
while (context->file_read_thread_running && !context->closed) {
int vid_frames = 0;
@@ -1684,6 +1690,7 @@ static switch_status_t av_file_open(switch_file_handle_t *handle, const char *pa
}
switch_mutex_init(&context->mutex, SWITCH_MUTEX_NESTED, handle->memory_pool);
switch_thread_cond_create(&context->cond, handle->memory_pool);
switch_buffer_create_dynamic(&context->audio_buffer, 512, 512, 0);
if (!context->audio_buffer) {
@@ -2064,6 +2071,12 @@ static switch_status_t av_file_read(switch_file_handle_t *handle, void *data, si
return SWITCH_STATUS_SUCCESS;
}
switch_mutex_lock(context->mutex);
while (!context->file_read_thread_started) {
switch_thread_cond_wait(context->cond, context->mutex);
}
switch_mutex_unlock(context->mutex);
if (!context->file_read_thread_running && switch_buffer_inuse(context->audio_buffer) == 0) {
*len = 0;
return SWITCH_STATUS_FALSE;
@@ -5,15 +5,8 @@
#include "avmd_amplitude.h"
#include "avmd_psi.h"
/*! \brief
* @author Eric des Courtis
* @param b A circular audio sample buffer
* @param i Position in the buffer
* @param f Frequency estimate
* @return The amplitude at position i
*/
extern double avmd_amplitude(circ_buffer_t *b, size_t i, double f)
{
double avmd_amplitude(circ_buffer_t *b, size_t i, double f) {
double result;
result = sqrt(PSI(b, i) / sin(f * f));
return result;
+11 -3
View File
@@ -1,7 +1,10 @@
/*
* @brief Estimation of amplitude using DESA-2 algorithm.
* @author Eric des Courtis
* @par Modifications: Piotr Gregor < piotrek.gregor gmail.com >
*
* Contributor(s):
*
* Eric des Courtis <eric.des.courtis@benbria.com>
* Piotr Gregor <piotrek.gregor gmail.com>:
*/
@@ -12,7 +15,12 @@
#include "avmd_buffer.h"
extern double avmd_amplitude(circ_buffer_t *, size_t i, double f);
#ifdef WIN32
#define __attribute__(x)
#endif
double avmd_amplitude(circ_buffer_t *, size_t i, double f) __attribute__ ((nonnull(1)));
#endif /* __AVMD_AMPLITUDE_H__ */
+15 -5
View File
@@ -19,8 +19,8 @@ int __isnan(double);
#include "avmd_fast_acosf.h"
#endif
extern double avmd_desa2(circ_buffer_t *b, size_t i)
{
double avmd_desa2(circ_buffer_t *b, size_t i, double *amplitude) {
double d;
double n;
double x0;
@@ -30,6 +30,7 @@ extern double avmd_desa2(circ_buffer_t *b, size_t i)
double x4;
double x2sq;
double result;
double PSI_Xn, PSI_Yn, NEEDED;
x0 = GET_SAMPLE((b), (i));
x1 = GET_SAMPLE((b), ((i) + 1));
@@ -39,8 +40,14 @@ extern double avmd_desa2(circ_buffer_t *b, size_t i)
x2sq = x2 * x2;
d = 2.0 * ((x2sq) - (x1 * x3));
if (d == 0.0) return 0.0;
n = ((x2sq) - (x0 * x4)) - ((x1 * x1) - (x0 * x2)) - ((x3 * x3) - (x2 * x4));
if (d == 0.0) {
*amplitude = 0.0;
return 0.0;
}
PSI_Xn = ((x2sq) - (x0 * x4));
NEEDED = ((x1 * x1) - (x0 * x2)) + ((x3 * x3) - (x2 * x4));
n = ((x2sq) - (x0 * x4)) - NEEDED;
PSI_Yn = NEEDED + PSI_Xn;
#ifdef AVMD_FAST_MATH
result = 0.5 * (double)fast_acosf((float)n/d);
@@ -48,7 +55,10 @@ extern double avmd_desa2(circ_buffer_t *b, size_t i)
result = 0.5 * acos(n/d);
#endif
if (ISNAN(result)) result = 0.0;
if (ISNAN(result)) {
result = 0.0;
}
*amplitude = 2.0 * PSI_Xn / sqrt(PSI_Yn);
return result;
+13 -4
View File
@@ -1,7 +1,10 @@
/*
* @brief DESA-2 algorithm implementation.
* @author Eric des Courtis
* @par Modifications: Piotr Gregor < piotrek.gregor gmail.com >
*
* Contributor(s):
*
* Eric des Courtis <eric.des.courtis@benbria.com>
* Piotr Gregor <piotrek.gregor gmail.com>:
*/
@@ -12,8 +15,14 @@
#include <math.h>
#include "avmd_buffer.h"
/* Returns digital frequency estimation. */
extern double avmd_desa2(circ_buffer_t *b, size_t i);
#ifdef WIN32
#define __attribute__(x)
#endif
/* Returns digital frequency estimation and amplitude estimation. */
extern double avmd_desa2(circ_buffer_t *b, size_t i, double *amplitude) __attribute__ ((nonnull(1,3)));
#endif /* __AVMD_DESA2_H__ */
@@ -19,11 +19,10 @@ int __isnan(double);
#include "avmd_fast_acosf.h"
#endif
double
avmd_desa2_tweaked(circ_buffer_t *b, size_t i)
{
double d;
double n;
avmd_desa2_tweaked(circ_buffer_t *b, size_t i, double *amplitude) {
double n, d;
double x0;
double x1;
double x2;
@@ -31,6 +30,7 @@ avmd_desa2_tweaked(circ_buffer_t *b, size_t i)
double x4;
double x2sq;
double result;
double PSI_Xn, PSI_Yn, NEEDED;
x0 = GET_SAMPLE((b), (i));
x1 = GET_SAMPLE((b), ((i) + 1));
@@ -39,8 +39,10 @@ avmd_desa2_tweaked(circ_buffer_t *b, size_t i)
x4 = GET_SAMPLE((b), ((i) + 4));
x2sq = x2 * x2;
d = 2.0 * ((x2sq) - (x1 * x3));
n = ((x2sq) - (x0 * x4)) - ((x1 * x1)
- (x0 * x2)) - ((x3 * x3) - (x2 * x4));
PSI_Xn = ((x2sq) - (x0 * x4));
NEEDED = ((x1 * x1) - (x0 * x2)) + ((x3 * x3) - (x2 * x4));
n = ((x2sq) - (x0 * x4)) - NEEDED;
PSI_Yn = NEEDED + PSI_Xn;
/* instead of
#ifdef FASTMATH
@@ -52,11 +54,14 @@ avmd_desa2_tweaked(circ_buffer_t *b, size_t i)
result = n/d;
if (ISINF(result)) {
if (n < 0.0)
*amplitude = 0.0;
if (n < 0.0) {
return -10.0;
else
} else {
return 10.0;
}
}
*amplitude = 2.0 * PSI_Xn / sqrt(PSI_Yn);
return result;
}
@@ -21,6 +21,11 @@
#include <switch.h>
#ifdef WIN32
#define __attribute__(x)
#endif
/* Instead of returning digital frequency estimation using
* result = 0.5 * acos(n/d),
* which involves expensive computation of arc cosine on
@@ -33,9 +38,10 @@
* to corresponding frequencies is nonlinear.
* The actual frequency estimation can be retrieved later
* from this partial result using
* 0.5 * acos(n/d)
* 0.5 * acos(returned_value)
* Amplitude estimation is returned by address.
*/
double avmd_desa2_tweaked(circ_buffer_t *b, size_t i);
double avmd_desa2_tweaked(circ_buffer_t *b, size_t i, double *amplitude) __attribute__ ((nonnull(1,3)));
#endif /* __AVMD_DESA2_TWEAKED_H__ */
+3 -1
View File
@@ -4,6 +4,8 @@
#include "avmd_buffer.h"
#define PSI(b, i) (GET_SAMPLE((b), ((i) + 1))*GET_SAMPLE((b), ((i) + 1))-GET_SAMPLE((b), ((i) + 2))*GET_SAMPLE((b), ((i) + 0)))
#define PSI(b, i) (GET_SAMPLE((b), ((i) + 1)) * GET_SAMPLE((b), ((i) + 1)) - GET_SAMPLE((b), ((i) + 2)) * GET_SAMPLE((b), ((i) + 0)))
#endif /* __AVMD_PSI_H__ */
@@ -8,12 +8,14 @@
<!-- Global settings -->
<!-- define/undefine this to enable/disable printing of avmd
<!-- define/undefine this to enable/disable logging of avmd
intermediate computations to log -->
<param name="debug" value="0"/>
<!-- define/undef this to enable/disable reporting of beep
detection status after session ended -->
<!-- define/undef this to enable/disable verbose logging (and reporting to the console)
of detection status and other diagnostics like parameters avmd session has been started with,
change of configuration parameters, beep detection status after session ended
(stop event is fired independently of this setting and beep status included there) -->
<param name="report_status" value="1"/>
<!-- define/undefine this to enable/disable faster computation
@@ -33,12 +35,15 @@
<param name="require_continuous_streak" value="1"/>
<!-- required number of consecutive elements in the SMA buffer
without reset -->
without reset. This parameter helps to avoid false beeps, bigger this value is
smaller the probability of getting false detection -->
<param name="sample_n_continuous_streak" value="15"/>
<!-- define number of samples to skip starting from the beginning
of the frame and after reset -->
<param name="sample_n_to_skip" value="6"/>
of the frame and/or after reset has happened. This serves the purpose of skipping first few
estimations on each frame, as these estimations may be inaccurate. This parameter also helps
to give more robust detections when it's value is increased (up to scertain limit of about 60). -->
<param name="sample_n_to_skip" value="15"/>
<!-- define/undefine this to enable/disable simplified estimation
of frequency based on approximation of sin(x) with (x)
+120 -42
View File
@@ -35,8 +35,10 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
#ifdef WIN32
#include <float.h>
#include <inttypes.h>
#define ISNAN(x) (!!(_isnan(x)))
#define ISINF(x) (isinf(x))
#else
@@ -175,11 +177,13 @@ typedef struct {
circ_buffer_t b;
sma_buffer_t sma_b;
sma_buffer_t sqa_b;
sma_buffer_t sma_amp_b;
sma_buffer_t sqa_amp_b;
size_t pos;
double f;
/* freq_table_t ft; */
avmd_state_t state;
switch_time_t start_time;
switch_time_t start_time, stop_time, detection_start_time, detection_stop_time;
size_t samples_streak; /* number of DESA samples in single streak without reset needed to validate SMA estimator */
size_t sample_count;
} avmd_session_t;
@@ -199,7 +203,8 @@ static switch_status_t avmd_register_all_events(void);
static void avmd_unregister_all_events(void);
static void
avmd_fire_event(enum avmd_event type, switch_core_session_t *fs_s, double freq, double v, avmd_beep_state_t beep_status, uint8_t info);
avmd_fire_event(enum avmd_event type, switch_core_session_t *fs_s, double freq, double v_freq, double amp, double v_amp, avmd_beep_state_t beep_status, uint8_t info,
switch_time_t detection_start_time, switch_time_t detection_stop_time, switch_time_t start_time, switch_time_t stop_time);
/* API [set default], reset to factory settings */
static void avmd_set_xml_default_configuration(switch_mutex_t *mutex);
@@ -256,6 +261,8 @@ init_avmd_session_data(avmd_session_t *avmd_session, switch_core_session_t *fs_s
memcpy(&avmd_session->settings, &avmd_globals.settings, sizeof(struct avmd_settings));
switch_mutex_init(&avmd_session->mutex, SWITCH_MUTEX_DEFAULT, switch_core_session_get_pool(fs_session));
avmd_session->sample_count = 0;
avmd_session->detection_start_time = 0;
avmd_session->detection_stop_time = 0;
buf_sz = BEEP_LEN((uint32_t)avmd_session->rate) / (uint32_t)SINE_LEN(avmd_session->rate);
if (buf_sz < 1) {
@@ -276,6 +283,20 @@ init_avmd_session_data(avmd_session_t *avmd_session, switch_core_session_t *fs_s
goto end;
}
memset(avmd_session->sqa_b.data, 0, sizeof(BUFF_TYPE) * buf_sz);
INIT_SMA_BUFFER(&avmd_session->sma_amp_b, buf_sz, fs_session);
if (avmd_session->sma_amp_b.data == NULL) {
status = SWITCH_STATUS_FALSE;
goto end;
}
memset(avmd_session->sma_amp_b.data, 0, sizeof(BUFF_TYPE) * buf_sz);
INIT_SMA_BUFFER(&avmd_session->sqa_amp_b, buf_sz, fs_session);
if (avmd_session->sqa_amp_b.data == NULL) {
status = SWITCH_STATUS_FALSE;
goto end;
}
memset(avmd_session->sqa_amp_b.data, 0, sizeof(BUFF_TYPE) * buf_sz);
end:
if (mutex != NULL)
{
@@ -407,10 +428,11 @@ avmd_unregister_all_events(void)
}
static void
avmd_fire_event(enum avmd_event type, switch_core_session_t *fs_s, double freq, double v, avmd_beep_state_t beep_status, uint8_t info)
{
avmd_fire_event(enum avmd_event type, switch_core_session_t *fs_s, double freq, double v_freq, double amp, double v_amp, avmd_beep_state_t beep_status, uint8_t info,
switch_time_t detection_start_time, switch_time_t detection_stop_time, switch_time_t start_time, switch_time_t stop_time) {
int res;
switch_event_t *event;
switch_time_t detection_time, total_time;
switch_status_t status;
switch_event_t *event_copy;
char buf[AVMD_CHAR_BUF_LEN];
@@ -421,26 +443,53 @@ avmd_fire_event(enum avmd_event type, switch_core_session_t *fs_s, double freq,
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(fs_s));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "avmd");
switch (type)
{
switch (type) {
case AVMD_EVENT_BEEP:
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Beep-Status", "DETECTED");
res = snprintf(buf, AVMD_CHAR_BUF_LEN, "%f", freq);
if (res < 0 || res > AVMD_CHAR_BUF_LEN - 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fs_s), SWITCH_LOG_ERROR, "Frequency truncated [%s], [%d] attempted!\n", buf, res);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "frequency", "ERROR (TRUNCATED)");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Frequency", "ERROR (TRUNCATED)");
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "frequency", buf);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Frequency", buf);
res = snprintf(buf, AVMD_CHAR_BUF_LEN, "%f", v);
res = snprintf(buf, AVMD_CHAR_BUF_LEN, "%f", v_freq);
if (res < 0 || res > AVMD_CHAR_BUF_LEN - 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fs_s), SWITCH_LOG_ERROR, "Error, truncated [%s], [%d] attempeted!\n", buf, res);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "variance", "ERROR (TRUNCATED)");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Frequency-variance", "ERROR (TRUNCATED)");
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "variance", buf);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Frequency-variance", buf);
res = snprintf(buf, AVMD_CHAR_BUF_LEN, "%f", amp);
if (res < 0 || res > AVMD_CHAR_BUF_LEN - 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fs_s), SWITCH_LOG_ERROR, "Amplitude truncated [%s], [%d] attempted!\n", buf, res);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Amplitude", "ERROR (TRUNCATED)");
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Amplitude", buf);
res = snprintf(buf, AVMD_CHAR_BUF_LEN, "%f", v_amp);
if (res < 0 || res > AVMD_CHAR_BUF_LEN - 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fs_s), SWITCH_LOG_ERROR, "Error, truncated [%s], [%d] attempeted!\n", buf, res);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Amplitude-variance", "ERROR (TRUNCATED)");
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Amplitude-variance", buf);
detection_time = detection_stop_time - detection_start_time;
res = snprintf(buf, AVMD_CHAR_BUF_LEN, "%" PRId64 "", detection_time);
if (res < 0 || res > AVMD_CHAR_BUF_LEN - 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fs_s), SWITCH_LOG_ERROR, "Detection time truncated [%s], [%d] attempted!\n", buf, res);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detection-time", "ERROR (TRUNCATED)");
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detection-time", buf);
break;
case AVMD_EVENT_SESSION_START:
res = snprintf(buf, AVMD_CHAR_BUF_LEN, "%" PRId64 "", start_time);
if (res < 0 || res > AVMD_CHAR_BUF_LEN - 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fs_s), SWITCH_LOG_ERROR, "Start time truncated [%s], [%d] attempted!\n", buf, res);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Start-time", "ERROR (TRUNCATED)");
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Start-time", buf);
break;
case AVMD_EVENT_SESSION_STOP:
@@ -449,6 +498,13 @@ avmd_fire_event(enum avmd_event type, switch_core_session_t *fs_s, double freq,
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fs_s), SWITCH_LOG_ERROR, "Error, avmd session object not found in media bug!\n");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "stop-status", "ERROR (AVMD SESSION OBJECT NOT FOUND IN MEDIA BUG)");
}
total_time = stop_time - start_time;
res = snprintf(buf, AVMD_CHAR_BUF_LEN, "%" PRId64 "", total_time);
if (res < 0 || res > AVMD_CHAR_BUF_LEN - 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fs_s), SWITCH_LOG_ERROR, "Total time truncated [%s], [%d] attempted!\n", buf, res);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Total-time", "ERROR (TRUNCATED)");
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Total-time", buf);
break;
default:
@@ -507,7 +563,7 @@ static void avmd_set_xml_default_configuration(switch_mutex_t *mutex)
avmd_globals.settings.fast_math = 0;
avmd_globals.settings.require_continuous_streak = 1;
avmd_globals.settings.sample_n_continuous_streak = 15;
avmd_globals.settings.sample_n_to_skip = 6;
avmd_globals.settings.sample_n_to_skip = 15;
avmd_globals.settings.simplified_estimation = 1;
avmd_globals.settings.inbound_channnel = 0;
avmd_globals.settings.outbound_channnel = 1;
@@ -1055,7 +1111,7 @@ SWITCH_STANDARD_APP(avmd_start_app)
goto end;
}
switch_channel_set_private(channel, "_avmd_", bug); /* Set the avmd tag to detect an existing avmd media bug */
avmd_fire_event(AVMD_EVENT_SESSION_START, session, 0, 0, 0, 0);
avmd_fire_event(AVMD_EVENT_SESSION_START, session, 0, 0, 0, 0, 0, 0, 0, 0, avmd_session->start_time, 0);
if (avmd_session->settings.report_status == 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Avmd on channel [%s] started!\n", switch_channel_get_name(channel));
}
@@ -1070,7 +1126,8 @@ SWITCH_STANDARD_APP(avmd_stop_app)
switch_media_bug_t *bug;
switch_channel_t *channel;
avmd_session_t *avmd_session;
uint8_t report_status = 0, avmd_found = 1;
switch_time_t start_time, stop_time, total_time;
uint8_t report_status = 0;
avmd_beep_state_t beep_status = BEEP_NOTDETECTED;
if (session == NULL) {
@@ -1101,26 +1158,25 @@ SWITCH_STANDARD_APP(avmd_stop_app)
avmd_session = switch_core_media_bug_get_user_data(bug);
if (avmd_session == NULL) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Stop failed - no avmd session object"
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Stop failed - no avmd session object, stop event not fired"
" on this channel [%s]!\n", switch_channel_get_name(channel));
avmd_found = 0;
} else {
switch_mutex_lock(avmd_session->mutex);
report_status = avmd_session->settings.report_status;
beep_status = avmd_session->state.beep_state;
avmd_session->stop_time = switch_micro_time_now();
start_time = avmd_session->start_time;
stop_time = avmd_session->stop_time;
total_time = stop_time - start_time;
switch_mutex_unlock(avmd_session->mutex);
avmd_fire_event(AVMD_EVENT_SESSION_STOP, session, 0, 0, 0, 0, beep_status, 1, 0, 0, start_time, stop_time);
if (report_status == 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Avmd on channel [%s] stopped, beep status: [%s], total running time [%" PRId64 "] [us]\n",
switch_channel_get_name(channel), beep_status == BEEP_DETECTED ? "DETECTED" : "NOTDETECTED", total_time);
}
}
switch_channel_set_private(channel, "_avmd_", NULL);
switch_core_media_bug_remove(session, &bug);
if (avmd_found == 1) {
avmd_fire_event(AVMD_EVENT_SESSION_STOP, session, 0, 0, beep_status, 1);
} else {
avmd_fire_event(AVMD_EVENT_SESSION_STOP, session, 0, 0, beep_status, 0);
}
if (report_status == 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Avmd on channel [%s] stopped, beep status: [%s]\n",
switch_channel_get_name(channel), beep_status == BEEP_DETECTED ? "DETECTED" : "NOTDETECTED");
}
return;
}
@@ -1376,15 +1432,19 @@ SWITCH_STANDARD_API(avmd_api_main)
if (bug != NULL) {
/* If we have a stop remove audio bug */
if (strcasecmp(command, "stop") == 0) {
avmd_session = (avmd_session_t*) switch_core_media_bug_get_user_data(bug);
if (avmd_session == NULL) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fs_session), SWITCH_LOG_ERROR, "Stop failed - no avmd session object"
" on this channel [%s]!\n", switch_channel_get_name(channel));
goto end;
}
uuid_dup = switch_core_strdup(switch_core_session_get_pool(fs_session), uuid);
switch_channel_set_private(channel, "_avmd_", NULL);
switch_core_media_bug_remove(fs_session, &bug);
avmd_fire_event(AVMD_EVENT_SESSION_STOP, fs_session, 0, 0, 0, 0);
avmd_fire_event(AVMD_EVENT_SESSION_STOP, fs_session, 0, 0, 0, 0, 0, 0, 0, 0, avmd_session->start_time, avmd_session->stop_time);
if (avmd_globals.settings.report_status == 1) {
stream->write_function(stream, "+OK\n [%s] [%s] stopped\n\n",
uuid_dup, switch_channel_get_name(channel));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fs_session), SWITCH_LOG_INFO,
"Avmd on channel [%s] stopped!\n", switch_channel_get_name(channel));
stream->write_function(stream, "+OK\n [%s] [%s] stopped\n\n", uuid_dup, switch_channel_get_name(channel));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fs_session), SWITCH_LOG_INFO, "Avmd on channel [%s] stopped!\n", switch_channel_get_name(channel));
}
goto end;
}
@@ -1500,7 +1560,7 @@ SWITCH_STANDARD_API(avmd_api_main)
switch_channel_set_private(channel, "_avmd_", bug); /* Set the vmd tag to detect an existing vmd media bug */
avmd_fire_event(AVMD_EVENT_SESSION_START, fs_session, 0, 0, 0, 0);
avmd_fire_event(AVMD_EVENT_SESSION_START, fs_session, 0, 0, 0, 0, 0, 0, 0, 0, avmd_session->start_time, 0);
if (avmd_globals.settings.report_status == 1) {
stream->write_function(stream, "+OK\n [%s] [%s] started!\n\n",
uuid, switch_channel_get_name(channel));
@@ -1527,11 +1587,12 @@ end:
*/
static void avmd_process(avmd_session_t *s, switch_frame_t *frame) {
switch_channel_t *channel;
switch_time_t detection_time;
circ_buffer_t *b;
size_t pos;
double omega;
double omega, amplitude;
double f;
double v;
double v, v_amp = 0.0;
double sma_digital_freq;
uint32_t sine_len_i;
int sample_to_skip_n = s->settings.sample_n_to_skip;
@@ -1541,6 +1602,9 @@ static void avmd_process(avmd_session_t *s, switch_frame_t *frame) {
/* If beep has already been detected skip the CPU heavy stuff */
if (s->state.beep_state == BEEP_DETECTED) return;
if (s->detection_start_time == 0) {
s->detection_start_time = switch_micro_time_now(); /* start detection timer */
}
/* Precompute values used heavily in the inner loop */
sine_len_i = (uint32_t) SINE_LEN(s->rate);
@@ -1559,7 +1623,7 @@ static void avmd_process(avmd_session_t *s, switch_frame_t *frame) {
/*for (pos = session->pos; pos < (GET_CURRENT_POS(b) - P); pos++) { */
if ((sample_n % sine_len_i) == 0) {
/* Get a desa2 frequency estimate every sine len */
omega = avmd_desa2_tweaked(b, pos + sample_n);
omega = avmd_desa2_tweaked(b, pos + sample_n, &amplitude);
if (omega < -0.999999 || omega > 0.999999) {
if (s->settings.debug == 1) {
@@ -1569,6 +1633,8 @@ static void avmd_process(avmd_session_t *s, switch_frame_t *frame) {
if (s->settings.require_continuous_streak == 1) {
RESET_SMA_BUFFER(&s->sma_b);
RESET_SMA_BUFFER(&s->sqa_b);
RESET_SMA_BUFFER(&s->sma_amp_b);
RESET_SMA_BUFFER(&s->sqa_amp_b);
s->samples_streak = s->settings.sample_n_continuous_streak;
sample_to_skip_n = s->settings.sample_n_to_skip;
}
@@ -1603,12 +1669,15 @@ static void avmd_process(avmd_session_t *s, switch_frame_t *frame) {
APPEND_SMA_VAL(&s->sma_b, omega); /* append */
APPEND_SMA_VAL(&s->sqa_b, omega * omega);
APPEND_SMA_VAL(&s->sma_amp_b, amplitude); /* append */
APPEND_SMA_VAL(&s->sqa_amp_b, amplitude * amplitude);
if (s->settings.require_continuous_streak == 1) {
if (s->samples_streak > 0) {
--s->samples_streak;
}
}
v = s->sqa_b.sma - (s->sma_b.sma * s->sma_b.sma); /* calculate variance (biased estimator) */
v = s->sqa_b.sma - (s->sma_b.sma * s->sma_b.sma); /* calculate variance of omega(biased estimator) */
v_amp = s->sqa_amp_b.sma - (s->sma_amp_b.sma * s->sma_amp_b.sma); /* calculate variance of amplitude (biased estimator) */
if (s->settings.debug == 1) {
#if !defined(WIN32) && defined(AVMD_FAST_MATH)
f = 0.5 * (double) fast_acosf((float)omega);
@@ -1619,11 +1688,16 @@ static void avmd_process(avmd_session_t *s, switch_frame_t *frame) {
#endif /* !WIN32 && AVMD_FAST_MATH */
if (s->settings.require_continuous_streak == 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(s->session), SWITCH_LOG_DEBUG, "<<< AVMD v[%.10f]\tomega[%f]\tf[%f] [%f]Hz\t\tsma[%f][%f]Hz\t\tsqa[%f]\t"
"streak[%zu] pos[%zu] sample_n[%zu] lpos[%zu] s[%zu]>>>\n", v, omega, f, TO_HZ(s->rate, f), s->sma_b.sma, TO_HZ(s->rate, sma_digital_freq), s->sqa_b.sma, s->samples_streak,
s->sma_b.pos, sample_n, s->sma_b.lpos, pos);
"amplitude[%f]\tv_amp[%f]\t"
"streak[%zu] pos[%zu] sample_n[%zu] lpos[%zu] s[%zu]>>>\n", v, omega, f, TO_HZ(s->rate, f), s->sma_b.sma, TO_HZ(s->rate, sma_digital_freq), s->sqa_b.sma,
amplitude, v_amp,
s->samples_streak, s->sma_b.pos, sample_n, s->sma_b.lpos, pos);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(s->session), SWITCH_LOG_DEBUG, "<<< AVMD v[%.10f]\tomega[%f]\tf[%f] [%f]Hz\t\tsma[%f][%f]Hz\t\tsqa[%f]\tpos[%zu]"
" sample_n[%zu] lpos[%zu] s[%zu]>>>\n", v, omega, f, TO_HZ(s->rate, f), s->sma_b.sma, TO_HZ(s->rate, sma_digital_freq), s->sqa_b.sma, s->sma_b.pos, sample_n, s->sma_b.lpos, pos);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(s->session), SWITCH_LOG_DEBUG, "<<< AVMD v[%.10f]\tomega[%f]\tf[%f] [%f]Hz\t\tsma[%f][%f]Hz\t\tsqa[%f]\t"
"amplitude[%f]\tv_amp[%f]\t"
"pos[%zu] sample_n[%zu] lpos[%zu] s[%zu]>>>\n", v, omega, f, TO_HZ(s->rate, f), s->sma_b.sma, TO_HZ(s->rate, sma_digital_freq), s->sqa_b.sma,
amplitude, v_amp,
s->sma_b.pos, sample_n, s->sma_b.lpos, pos);
}
}
}
@@ -1639,15 +1713,19 @@ static void avmd_process(avmd_session_t *s, switch_frame_t *frame) {
sma_digital_freq = 0.5 * acos(s->sma_b.sma);
#endif /* !WIN32 && AVMD_FAST_MATH */
switch_channel_set_variable_printf(channel, "avmd_total_time", "[%d]", (int)(switch_micro_time_now() - s->start_time) / 1000);
s->detection_stop_time = switch_micro_time_now(); /* stop detection timer */
detection_time = s->detection_stop_time - s->detection_start_time; /* detection time length */
switch_channel_set_variable_printf(channel, "avmd_total_time", "[%" PRId64 "]", detection_time / 1000);
switch_channel_execute_on(channel, "execute_on_avmd_beep");
avmd_fire_event(AVMD_EVENT_BEEP, s->session, TO_HZ(s->rate, sma_digital_freq), v, 0, 0);
avmd_fire_event(AVMD_EVENT_BEEP, s->session, TO_HZ(s->rate, sma_digital_freq), v, s->sma_amp_b.sma, v_amp, 0, 0, s->detection_start_time, s->detection_stop_time, 0, 0);
if (s->settings.report_status == 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(s->session), SWITCH_LOG_INFO, "<<< AVMD - Beep Detected: f = [%f], variance = [%f] >>>\n", TO_HZ(s->rate, sma_digital_freq), v);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(s->session), SWITCH_LOG_INFO, "<<< AVMD - Beep Detected: f = [%f] variance = [%f], amplitude = [%f] variance = [%f], detection time [%" PRId64 "] [us] >>>\n", TO_HZ(s->rate, sma_digital_freq), v, s->sma_amp_b.sma, v_amp, detection_time);
}
switch_channel_set_variable(channel, "avmd_detect", "TRUE");
RESET_SMA_BUFFER(&s->sma_b);
RESET_SMA_BUFFER(&s->sqa_b);
RESET_SMA_BUFFER(&s->sma_amp_b);
RESET_SMA_BUFFER(&s->sqa_amp_b);
s->state.beep_state = BEEP_DETECTED;
goto done;
}
@@ -1556,6 +1556,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_time_t t_agent_answered = 0;
switch_time_t t_member_called = atoi(h->member_joined_epoch);
switch_event_t *event = NULL;
int bridged = 1;
switch_mutex_lock(globals.mutex);
globals.threads++;
@@ -1786,21 +1787,6 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-DNIS", member_dnis);
switch_event_fire(&event);
}
/* for xml_cdr needs */
switch_channel_set_variable(member_channel, "cc_agent", h->agent_name);
switch_channel_set_variable_printf(member_channel, "cc_queue_answered_epoch", "%" SWITCH_TIME_T_FMT, local_epoch_time_now(NULL));
/* Set UUID of the Agent channel */
sql = switch_mprintf("UPDATE agents SET uuid = '%q', last_bridge_start = '%" SWITCH_TIME_T_FMT "', calls_answered = calls_answered + 1, no_answer_count = 0"
" WHERE name = '%q' AND system = '%q'",
agent_uuid, local_epoch_time_now(NULL),
h->agent_name, h->agent_system);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
/* Change the agents Status in the tiers */
cc_tier_update("state", cc_tier_state2str(CC_TIER_STATE_ACTIVE_INBOUND), h->queue_name, h->agent_name);
cc_agent_update("state", cc_agent_state2str(CC_AGENT_STATE_IN_A_QUEUE_CALL), h->agent_name);
/* Record session if record-template is provided */
if (h->record_template) {
@@ -1825,11 +1811,56 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
if (switch_true(switch_channel_get_variable(member_channel, SWITCH_BYPASS_MEDIA_AFTER_BRIDGE_VARIABLE))) {
switch_channel_set_flag(member_channel, CF_BYPASS_MEDIA_AFTER_BRIDGE);
}
switch_ivr_uuid_bridge(h->member_session_uuid, switch_core_session_get_uuid(agent_session));
switch_channel_wait_for_flag(agent_channel, CF_BRIDGED, SWITCH_TRUE, 1000, NULL);
if (switch_ivr_uuid_bridge(h->member_session_uuid, switch_core_session_get_uuid(agent_session)) != SWITCH_STATUS_SUCCESS) {
bridged = 0;
}
if (bridged && (switch_channel_wait_for_flag(agent_channel, CF_BRIDGED, SWITCH_TRUE, 3000, NULL) != SWITCH_STATUS_SUCCESS)) {
bridged = 0;
}
if (!bridged && !switch_channel_up(member_channel)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Failed to bridge, member \"%s\" <%s> has gone just before we called agent %s\n",
h->member_cid_name, h->member_cid_number, h->agent_name);
switch_channel_set_variable(agent_channel, "cc_agent_bridged", "false");
switch_channel_set_variable(member_channel, "cc_agent_bridged", "false");
if ((o_announce = switch_channel_get_variable(member_channel, "cc_bridge_failed_outbound_announce"))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Playing bridge failed audio to agent %s, audio: %s\n", h->agent_name, o_announce);
playback_array(agent_session, o_announce);
}
if (!strcasecmp(h->agent_type, CC_AGENT_TYPE_CALLBACK)) {
switch_channel_hangup(agent_channel, SWITCH_CAUSE_ORIGINATOR_CANCEL);
}
} else {
bridged = 1;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Member \"%s\" %s is bridged to agent %s\n",
h->member_cid_name, h->member_cid_number, h->agent_name);
switch_channel_set_variable(member_channel, "cc_agent_bridged", "true");
switch_channel_set_variable(agent_channel, "cc_agent_bridged", "true");
switch_channel_set_variable(member_channel, "cc_agent_uuid", agent_uuid);
}
if (bridged) {
/* for xml_cdr needs */
switch_channel_set_variable(member_channel, "cc_agent", h->agent_name);
switch_channel_set_variable_printf(member_channel, "cc_queue_answered_epoch", "%" SWITCH_TIME_T_FMT, local_epoch_time_now(NULL));
/* Set UUID of the Agent channel */
sql = switch_mprintf("UPDATE agents SET uuid = '%q', last_bridge_start = '%" SWITCH_TIME_T_FMT "', calls_answered = calls_answered + 1, no_answer_count = 0"
" WHERE name = '%q' AND system = '%q'",
agent_uuid, local_epoch_time_now(NULL),
h->agent_name, h->agent_system);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
/* Change the agents Status in the tiers */
cc_tier_update("state", cc_tier_state2str(CC_TIER_STATE_ACTIVE_INBOUND), h->queue_name, h->agent_name);
cc_agent_update("state", cc_agent_state2str(CC_AGENT_STATE_IN_A_QUEUE_CALL), h->agent_name);
}
/* Wait until the agent hangup. This will quit also if the agent transfer the call */
while(switch_channel_up(agent_channel) && globals.running) {
while(bridged && switch_channel_up(agent_channel) && globals.running) {
if (!strcasecmp(h->agent_type, CC_AGENT_TYPE_UUID_STANDBY)) {
if (!switch_channel_test_flag(agent_channel, CF_BRIDGED)) {
break;
@@ -1839,7 +1870,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
}
tiers_state = CC_TIER_STATE_READY;
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
if (bridged && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(agent_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", h->queue_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "bridge-agent-end");
@@ -1847,6 +1878,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-System", h->agent_system);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-UUID", agent_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-Bridged", bridged ? "true" : "false");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Called-Time", "%" SWITCH_TIME_T_FMT, t_agent_called);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answered-Time", "%" SWITCH_TIME_T_FMT, t_agent_answered);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Member-Joined-Time", "%" SWITCH_TIME_T_FMT, t_member_called);
@@ -1857,15 +1889,17 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Number", h->member_cid_number);
switch_event_fire(&event);
}
/* for xml_cdr needs */
switch_channel_set_variable_printf(member_channel, "cc_queue_terminated_epoch", "%" SWITCH_TIME_T_FMT, local_epoch_time_now(NULL));
if (bridged) {
/* for xml_cdr needs */
switch_channel_set_variable_printf(member_channel, "cc_queue_terminated_epoch", "%" SWITCH_TIME_T_FMT, local_epoch_time_now(NULL));
/* Update Agents Items */
/* Do not remove uuid of the agent if we are a standby agent */
sql = switch_mprintf("UPDATE agents SET %s last_bridge_end = %" SWITCH_TIME_T_FMT ", talk_time = talk_time + (%" SWITCH_TIME_T_FMT "-last_bridge_start) WHERE name = '%q' AND system = '%q';"
, (strcasecmp(h->agent_type, CC_AGENT_TYPE_UUID_STANDBY)?"uuid = '',":""), local_epoch_time_now(NULL), local_epoch_time_now(NULL), h->agent_name, h->agent_system);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
/* Update Agents Items */
/* Do not remove uuid of the agent if we are a standby agent */
sql = switch_mprintf("UPDATE agents SET %s last_bridge_end = %" SWITCH_TIME_T_FMT ", talk_time = talk_time + (%" SWITCH_TIME_T_FMT "-last_bridge_start) WHERE name = '%q' AND system = '%q';"
, (strcasecmp(h->agent_type, CC_AGENT_TYPE_UUID_STANDBY)?"uuid = '',":""), local_epoch_time_now(NULL), local_epoch_time_now(NULL), h->agent_name, h->agent_system);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
}
/* Remove the member entry from the db (Could become optional to support latter processing) */
sql = switch_mprintf("DELETE FROM members WHERE system = 'single_box' AND uuid = '%q'", h->member_uuid);
@@ -6900,6 +6900,38 @@ SWITCH_STANDARD_JSON_API(json_execute_function)
return status;
}
SWITCH_STANDARD_API(event_channel_broadcast_api_function)
{
cJSON *jdata = NULL;
const char *channel;
if (!cmd) {
stream->write_function(stream, "-ERR parsing channel\n", SWITCH_VA_NONE);
return SWITCH_STATUS_SUCCESS;
}
if (!(jdata = cJSON_Parse(cmd))) {
stream->write_function(stream, "-ERR parsing json\n");
}
if (jdata) {
if (!(channel = cJSON_GetObjectCstr(jdata, "eventChannel"))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NO EVENT CHANNEL SPECIFIED\n");
} else {
switch_event_channel_broadcast(channel, &jdata, modname, NO_EVENT_CHANNEL_ID);
stream->write_function(stream, "+OK message sent\n", SWITCH_VA_NONE);
}
if (jdata) {
cJSON_Delete(jdata);
}
}
return SWITCH_STATUS_SUCCESS;
}
SWITCH_STANDARD_JSON_API(json_api_function)
{
cJSON *data, *cmd, *arg, *reply;
@@ -7090,6 +7122,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
SWITCH_ADD_API(commands_api_interface, "db_cache", "Manage db cache", db_cache_function, "status");
SWITCH_ADD_API(commands_api_interface, "domain_exists", "Check if a domain exists", domain_exists_function, "<domain>");
SWITCH_ADD_API(commands_api_interface, "echo", "Echo", echo_function, "<data>");
SWITCH_ADD_API(commands_api_interface, "event_channel_broadcast", "Broadcast", event_channel_broadcast_api_function, "<channel> <json>");
SWITCH_ADD_API(commands_api_interface, "escape", "Escape a string", escape_function, "<data>");
SWITCH_ADD_API(commands_api_interface, "eval", "eval (noop)", eval_function, "[uuid:<uuid> ]<expression>");
SWITCH_ADD_API(commands_api_interface, "expand", "Execute an api with variable expansion", expand_function, "[uuid:<uuid> ]<cmd> <args>");
@@ -1564,6 +1564,8 @@ switch_status_t conference_api_sub_clear_vid_floor(conference_obj_t *conference,
//conference_video_set_floor_holder(conference, NULL);
switch_mutex_unlock(conference->mutex);
stream->write_function(stream, "OK floor Cleared\n", SWITCH_VA_NONE);
return SWITCH_STATUS_SUCCESS;
}
@@ -1624,20 +1626,22 @@ switch_status_t conference_api_sub_vid_logo_img(conference_member_t *member, swi
goto end;
}
if (!strcasecmp(text, "allclear")) {
switch_channel_set_variable(member->channel, "video_logo_path", NULL);
member->video_logo = NULL;
} else if (!strcasecmp(text, "clear")) {
member->video_logo = NULL;
} else {
member->video_logo = switch_core_strdup(member->pool, text);
}
if (!zstr(text)) {
if (!strcasecmp(text, "allclear")) {
switch_channel_set_variable(member->channel, "video_logo_path", NULL);
member->video_logo = NULL;
} else if (!strcasecmp(text, "clear")) {
member->video_logo = NULL;
} else {
member->video_logo = switch_core_strdup(member->pool, text);
}
conference_video_layer_set_logo(member, layer, text);
conference_video_layer_set_logo(member, layer, text);
}
end:
stream->write_function(stream, "+OK\n");
stream->write_function(stream, "%s\n", member->video_logo ? member->video_logo : "_undef_");
conference_video_release_layer(&layer);
@@ -2506,11 +2510,6 @@ switch_status_t conference_api_sub_record(conference_obj_t *conference, switch_s
return SWITCH_STATUS_GENERR;
}
if (conference->conference_video_mode == CONF_VIDEO_MODE_PASSTHROUGH) {
stream->write_function(stream, "-ERR Video Passthru enabled, recording not permitted.\n");
return SWITCH_STATUS_SUCCESS;
}
if (argv[3]) {
if (argv[3]) {
@@ -2529,6 +2528,10 @@ switch_status_t conference_api_sub_record(conference_obj_t *conference, switch_s
if (id == 0 && conference->canvases[0]) id = 1;
if (id > conference->canvas_count) {
id = 1;
}
if (id > 0) {
stream->write_function(stream, "Record file %s canvas %d\n", argv[2], id);
} else {
@@ -707,6 +707,7 @@ void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, void *ob
if (switch_channel_test_flag(channel, CF_VIDEO) && !conference_utils_member_test_flag(member, MFLAG_ACK_VIDEO)) {
conference_utils_member_set_flag_locked(member, MFLAG_ACK_VIDEO);
switch_img_free(&member->avatar_png_img);
conference_video_check_avatar(member, SWITCH_FALSE);
switch_core_session_video_reinit(member->session);
conference_video_set_floor_holder(member->conference, member, SWITCH_FALSE);
@@ -1121,6 +1122,7 @@ void conference_loop_output(conference_member_t *member)
const char *prefix = switch_channel_get_variable(channel, "conference_auto_outcall_prefix");
const char *maxwait = switch_channel_get_variable(channel, "conference_auto_outcall_maxwait");
const char *delimiter_val = switch_channel_get_variable(channel, "conference_auto_outcall_delimiter");
const char *skip_member_beep = switch_channel_get_variable(channel, "conference_auto_outcall_skip_member_beep");
int to = 60;
int wait_sec = 2;
int loops = 0;
@@ -1184,7 +1186,8 @@ void conference_loop_output(conference_member_t *member)
goto end;
}
conference_member_play_file(member, "tone_stream://%(500,0,640)", 0, SWITCH_TRUE);
if (!skip_member_beep || !switch_true(skip_member_beep))
conference_member_play_file(member, "tone_stream://%(500,0,640)", 0, SWITCH_TRUE);
}
if (!conference_utils_test_flag(member->conference, CFLAG_ANSWERED)) {
@@ -60,11 +60,6 @@ void conference_record_launch_thread(conference_obj_t *conference, char *path, i
return;
}
if (conference->conference_video_mode == CONF_VIDEO_MODE_PASSTHROUGH) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Video Passthru enabled, recording not permitted.\n");
return;
}
rec->conference = conference;
rec->path = switch_core_strdup(pool, path);
rec->pool = pool;
@@ -926,7 +926,7 @@ switch_status_t conference_video_attach_video_layer(conference_member_t *member,
return SWITCH_STATUS_FALSE;
}
if (switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY && !member->avatar_png_img) {
if ((switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY || switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE) && !member->avatar_png_img) {
return SWITCH_STATUS_FALSE;
}
@@ -1317,7 +1317,7 @@ void conference_video_write_canvas_image_to_codec_group(conference_obj_t *confer
switch_core_session_request_video_refresh(imember->session);
}
if (switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_RECVONLY) {
if (switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_RECVONLY || switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE) {
switch_core_session_rwunlock(imember->session);
continue;
}
@@ -1354,6 +1354,10 @@ video_layout_t *conference_video_find_best_layout(conference_obj_t *conference,
}
}
if (!lg) {
return NULL;
}
for (vlnode = lg->layouts; vlnode; vlnode = vlnode->next) {
if (vlnode->vlayout->layers >= (int)count) {
break;
@@ -1599,6 +1603,71 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_write_thread_run(switch_thread_
return NULL;
}
void conference_video_member_video_mute_banner(mcu_canvas_t *canvas, mcu_layer_t *layer, conference_member_t *member)
{
const char *text = "VIDEO MUTED";
char *dup = NULL;
const char *var, *tmp = NULL;
const char *fg = "";
const char *bg = "";
const char *font_face = "";
const char *font_scale = "";
const char *font_scale_percentage = "";
char *parsed = NULL;
switch_event_t *params = NULL;
switch_image_t *text_img;
char text_str[256] = "";
if ((var = switch_channel_get_variable_dup(member->channel, "video_mute_banner", SWITCH_FALSE, -1))) {
text = var;
} else if (member->conference->video_mute_banner) {
text = member->conference->video_mute_banner;
}
if (*text == '{') {
dup = strdup(text);
text = dup;
if (switch_event_create_brackets((char *)text, '{', '}', ',', &params, &parsed, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS || !parsed) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
} else {
text = parsed;
}
}
if ((tmp = strchr(text, '}'))) {
text = tmp + 1;
}
if (params) {
if ((var = switch_event_get_header(params, "fg"))) {
fg = var;
}
if ((var = switch_event_get_header(params, "bg"))) {
bg = var;
}
if ((var = switch_event_get_header(params, "font_face"))) {
font_face = var;
}
if ((var = switch_event_get_header(params, "font_scale"))) {
font_scale = var;
font_scale_percentage = "%";
}
}
switch_snprintf(text_str, sizeof(text_str), "%s:%s:%s:%s%s:%s", fg, bg, font_face, font_scale, font_scale_percentage, text);
text_img = switch_img_write_text_img(layer->screen_w, layer->screen_h, SWITCH_TRUE, text_str);
switch_img_patch(canvas->img, text_img, layer->x_pos, layer->y_pos);
switch_img_free(&text_img);
if (params) switch_event_destroy(&params);
switch_safe_free(dup);
}
void conference_video_check_recording(conference_obj_t *conference, mcu_canvas_t *canvas, switch_frame_t *frame)
{
conference_member_t *imember;
@@ -1643,7 +1712,10 @@ void conference_video_check_avatar(conference_member_t *member, switch_bool_t fo
canvas = conference_video_get_canvas_locked(member);
if (conference_utils_test_flag(member->conference, CFLAG_VIDEO_REQUIRED_FOR_CANVAS) &&
(!switch_channel_test_flag(member->channel, CF_VIDEO_READY) || switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY)) {
(!switch_channel_test_flag(member->channel, CF_VIDEO_READY) ||
(switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY ||
switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE))) {
if (canvas) {
conference_video_release_canvas(&canvas);
}
@@ -1656,7 +1728,8 @@ void conference_video_check_avatar(conference_member_t *member, switch_bool_t fo
member->avatar_patched = 0;
if (!force && switch_channel_test_flag(member->channel, CF_VIDEO_READY) && switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_SENDONLY) {
if (!force && switch_channel_test_flag(member->channel, CF_VIDEO_READY) &&
switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_SENDONLY && switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_INACTIVE) {
conference_utils_member_set_flag_locked(member, MFLAG_ACK_VIDEO);
} else {
if (member->conference->no_video_avatar) {
@@ -1795,7 +1868,8 @@ switch_status_t conference_video_find_layer(conference_obj_t *conference, mcu_ca
if (!layer &&
(canvas->layers_used < canvas->total_layers ||
(avatar_layers && !member->avatar_png_img) || conference_utils_member_test_flag(member, MFLAG_MOD)) &&
(member->avatar_png_img || switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_SENDONLY)) {
(member->avatar_png_img || (switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_SENDONLY &&
switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_INACTIVE))) {
/* find an empty layer */
for (i = 0; i < canvas->total_layers; i++) {
mcu_layer_t *xlayer = &canvas->layers[i];
@@ -1856,6 +1930,10 @@ void conference_video_pop_next_image(conference_member_t *member, switch_image_t
int size = 0;
void *pop;
if (member->avatar_png_img && switch_channel_test_flag(member->channel, CF_VIDEO_READY) && conference_utils_member_test_flag(member, MFLAG_ACK_VIDEO)) {
switch_img_free(&member->avatar_png_img);
}
if (!member->avatar_png_img && switch_channel_test_flag(member->channel, CF_VIDEO_READY)) {
do {
if (switch_queue_trypop(member->video_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) {
@@ -1868,7 +1946,11 @@ void conference_video_pop_next_image(conference_member_t *member, switch_image_t
size = switch_queue_size(member->video_queue);
} while(size > 0);
if (conference_utils_member_test_flag(member, MFLAG_CAN_BE_SEEN) && member->video_layer_id > -1 && switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_SENDONLY) {
if (conference_utils_member_test_flag(member, MFLAG_CAN_BE_SEEN) &&
member->video_layer_id > -1 &&
switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_SENDONLY &&
switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_INACTIVE
) {
if (img) {
member->good_img++;
if ((member->good_img % (int)(member->conference->video_fps.fps * 10)) == 0) {
@@ -2227,7 +2309,7 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
if (imember->channel && switch_channel_ready(imember->channel) && switch_channel_test_flag(imember->channel, CF_VIDEO_READY) &&
!conference_utils_member_test_flag(imember, MFLAG_SECOND_SCREEN) &&
conference_utils_member_test_flag(imember, MFLAG_RUNNING) && (!no_muted || seen) && (!no_av || (no_av && !imember->avatar_png_img))
&& imember->canvas_id == canvas->canvas_id && imember->video_media_flow != SWITCH_MEDIA_FLOW_SENDONLY) {
&& imember->canvas_id == canvas->canvas_id && imember->video_media_flow != SWITCH_MEDIA_FLOW_SENDONLY && imember->video_media_flow != SWITCH_MEDIA_FLOW_INACTIVE) {
video_count++;
}
@@ -2470,7 +2552,7 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
switch_img_free(&img);
}
if (!layer && (!conference_utils_test_flag(imember->conference, CFLAG_VIDEO_REQUIRED_FOR_CANVAS) || ((switch_channel_test_flag(imember->channel, CF_VIDEO_READY) && switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_SENDONLY)))) {
if (!layer && (!conference_utils_test_flag(imember->conference, CFLAG_VIDEO_REQUIRED_FOR_CANVAS) || ((switch_channel_test_flag(imember->channel, CF_VIDEO_READY) && switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_SENDONLY && switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_INACTIVE)))) {
if (conference_video_find_layer(conference, canvas, imember, &layer) == SWITCH_STATUS_SUCCESS) {
imember->layer_timeout = 0;
} else {
@@ -2492,10 +2574,9 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
// switch_img_free(&layer->cur_img);
//}
if (conference_utils_member_test_flag(imember, MFLAG_CAN_BE_SEEN) || switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY || conference_utils_test_flag(imember->conference, CFLAG_VIDEO_MUTE_EXIT_CANVAS)) {
if (conference_utils_member_test_flag(imember, MFLAG_CAN_BE_SEEN) || switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY || switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE || conference_utils_test_flag(imember->conference, CFLAG_VIDEO_MUTE_EXIT_CANVAS)) {
layer->mute_patched = 0;
} else {
switch_image_t *tmp;
if (img && img != imember->avatar_png_img) {
switch_img_free(&img);
@@ -2523,10 +2604,7 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
}
tmp = switch_img_write_text_img(layer->screen_w, layer->screen_h, SWITCH_TRUE, "VIDEO MUTED");
switch_img_patch(canvas->img, tmp, layer->x_pos, layer->y_pos);
switch_img_free(&tmp);
conference_video_member_video_mute_banner(canvas, layer, imember);
layer->mute_patched = 1;
}
}
@@ -2613,7 +2691,9 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
if (total > 0 &&
(!conference_utils_test_flag(imember->conference, CFLAG_VIDEO_MUTE_EXIT_CANVAS) ||
conference_utils_member_test_flag(imember, MFLAG_CAN_BE_SEEN)) &&
imember->session && switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_SENDONLY) {
imember->session && switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_SENDONLY &&
imember->session && switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_INACTIVE) {
total--;
}
@@ -2637,7 +2717,7 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
}
}
if (imember->session && switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_SENDONLY) {
if (imember->session && switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_SENDONLY && switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_INACTIVE) {
conference_video_pop_next_image(imember, &imember->pcanvas_img);
}
@@ -2683,7 +2763,8 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
if (!imember->rec &&
(!imember->session || !switch_channel_test_flag(imember->channel, CF_VIDEO) || !imember->canvas ||
(switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY) ||
(switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY ||
switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE) ||
(switch_core_session_read_lock(imember->session) != SWITCH_STATUS_SUCCESS))) {
continue;
}
@@ -2717,7 +2798,7 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
switch_image_t *use_img = NULL;
if (!omember->session || !switch_channel_test_flag(omember->channel, CF_VIDEO_READY) ||
switch_core_session_media_flow(omember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY) {
switch_core_session_media_flow(omember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY || switch_core_session_media_flow(omember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE) {
continue;
}
@@ -2775,11 +2856,8 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
layer->mute_patched = 0;
} else if (!conference_utils_test_flag(imember->conference, CFLAG_VIDEO_MUTE_EXIT_CANVAS)) {
if (!layer->mute_patched) {
switch_image_t *tmp;
conference_video_scale_and_patch(layer, omember->video_mute_img ? omember->video_mute_img : omember->pcanvas_img, SWITCH_FALSE);
tmp = switch_img_write_text_img(layer->screen_w, layer->screen_h, SWITCH_TRUE, "VIDEO MUTED");
switch_img_patch(imember->canvas->img, tmp, layer->x_pos, layer->y_pos);
switch_img_free(&tmp);
conference_video_member_video_mute_banner(imember->canvas, layer, imember);
layer->mute_patched = 1;
}
@@ -3016,7 +3094,7 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
switch_core_session_request_video_refresh(imember->session);
}
if (switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_RECVONLY) {
if (switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_RECVONLY || switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE) {
switch_core_session_rwunlock(imember->session);
continue;
}
@@ -3365,7 +3443,7 @@ void *SWITCH_THREAD_FUNC conference_video_super_muxing_thread_run(switch_thread_
switch_core_session_request_video_refresh(imember->session);
}
if (switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_RECVONLY) {
if (switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_RECVONLY || switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE) {
switch_core_session_rwunlock(imember->session);
continue;
}
@@ -3450,7 +3528,7 @@ void conference_video_find_floor(conference_member_t *member, switch_bool_t ente
continue;
}
if (switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY && !imember->avatar_png_img) {
if ((switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY || switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE) && !imember->avatar_png_img) {
continue;
}
@@ -3515,7 +3593,7 @@ void conference_video_set_floor_holder(conference_obj_t *conference, conference_
return;
}
if (member && switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY && !member->avatar_png_img) {
if (member && (switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY || switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE) && !member->avatar_png_img) {
return;
}
@@ -3740,7 +3818,7 @@ switch_status_t conference_video_thread_callback(switch_core_session_t *session,
return SWITCH_STATUS_SUCCESS;
}
if (switch_core_session_media_flow(session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY) {
if (switch_core_session_media_flow(session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY || switch_core_session_media_flow(session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE) {
return SWITCH_STATUS_SUCCESS;
}
@@ -3789,6 +3867,7 @@ switch_status_t conference_video_thread_callback(switch_core_session_t *session,
if (switch_queue_trypush(member->video_queue, img_copy) != SWITCH_STATUS_SUCCESS) {
switch_img_free(&img_copy);
}
}
switch_thread_rwlock_unlock(member->conference->rwlock);
@@ -691,35 +691,6 @@ void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, void *ob
}
}
/* Close Unused Handles */
if (conference->fnode) {
conference_file_node_t *fnode, *cur;
switch_memory_pool_t *pool;
fnode = conference->fnode;
while (fnode) {
cur = fnode;
fnode = fnode->next;
if (cur->type != NODE_TYPE_SPEECH) {
conference_file_close(conference, cur);
}
pool = cur->pool;
switch_core_destroy_memory_pool(&pool);
}
conference->fnode = NULL;
}
if (conference->async_fnode) {
switch_memory_pool_t *pool;
conference_file_close(conference, conference->async_fnode);
pool = conference->async_fnode->pool;
conference->async_fnode = NULL;
switch_core_destroy_memory_pool(&pool);
}
switch_mutex_lock(conference->member_mutex);
for (imember = conference->members; imember; imember = imember->next) {
switch_channel_t *channel;
@@ -768,7 +739,6 @@ void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, void *ob
}
switch_mutex_unlock(conference_globals.hash_mutex);
conference_utils_clear_flag(conference, CFLAG_VIDEO_MUXING);
for (x = 0; x <= conference->canvas_count; x++) {
@@ -779,6 +749,34 @@ void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, void *ob
}
}
/* Close Unused Handles */
if (conference->fnode) {
conference_file_node_t *fnode, *cur;
switch_memory_pool_t *pool;
fnode = conference->fnode;
while (fnode) {
cur = fnode;
fnode = fnode->next;
if (cur->type != NODE_TYPE_SPEECH) {
conference_file_close(conference, cur);
}
pool = cur->pool;
switch_core_destroy_memory_pool(&pool);
}
conference->fnode = NULL;
}
if (conference->async_fnode) {
switch_memory_pool_t *pool;
conference_file_close(conference, conference->async_fnode);
pool = conference->async_fnode->pool;
conference->async_fnode = NULL;
switch_core_destroy_memory_pool(&pool);
}
/* Wait till everybody is out */
conference_utils_clear_flag_locked(conference, CFLAG_RUNNING);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write Lock ON\n");
@@ -2252,7 +2250,7 @@ SWITCH_STANDARD_APP(conference_function)
if (conference) {
switch_mutex_lock(conference->mutex);
if (conference_utils_test_flag(conference, CFLAG_DYNAMIC) && conference->count == 0) {
if (conference_utils_test_flag(conference, CFLAG_DYNAMIC) && conference->count == 0 && conference->count_ghosts == 0) {
conference_utils_set_flag_locked(conference, CFLAG_DESTRUCT);
}
switch_mutex_unlock(conference->mutex);
@@ -2401,6 +2399,7 @@ conference_obj_t *conference_new(char *name, conference_xml_cfg_t cfg, switch_co
char *video_letterbox_bgcolor = NULL;
char *video_codec_bandwidth = NULL;
char *no_video_avatar = NULL;
char *video_mute_banner = NULL;
conference_video_mode_t conference_video_mode = CONF_VIDEO_MODE_PASSTHROUGH;
int conference_video_quality = 1;
int auto_kps_debounce = 30000;
@@ -2588,6 +2587,8 @@ conference_obj_t *conference_new(char *name, conference_xml_cfg_t cfg, switch_co
video_codec_bandwidth = val;
} else if (!strcasecmp(var, "video-no-video-avatar") && !zstr(val)) {
no_video_avatar = val;
} else if (!strcasecmp(var, "video-mute-banner") && !zstr(val)) {
video_mute_banner = val;
} else if (!strcasecmp(var, "exit-sound") && !zstr(val)) {
exit_sound = val;
} else if (!strcasecmp(var, "alone-sound") && !zstr(val)) {
@@ -2760,10 +2761,10 @@ conference_obj_t *conference_new(char *name, conference_xml_cfg_t cfg, switch_co
}
}
if (scale_h264_canvas_width < 320 || scale_h264_canvas_width < 180) {
if (scale_h264_canvas_width < 320 || scale_h264_canvas_height < 180) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid scale-h264-canvas-size, falling back to 320x180\n");
scale_h264_canvas_width = 320;
scale_h264_canvas_width = 180;
scale_h264_canvas_height = 180;
}
} else if (!strcasecmp(var, "scale-h264-canvas-fps-divisor") && !zstr(val)) {
scale_h264_canvas_fps_divisor = atoi(val);
@@ -2889,6 +2890,10 @@ conference_obj_t *conference_new(char *name, conference_xml_cfg_t cfg, switch_co
video_letterbox_bgcolor = "#000000";
}
if (video_mute_banner) {
conference->video_mute_banner = switch_core_strdup(conference->pool, video_mute_banner);
}
if (no_video_avatar) {
conference->no_video_avatar = switch_core_strdup(conference->pool, no_video_avatar);
}
@@ -564,6 +564,7 @@ typedef struct conference_obj {
char *video_border_color;
char *video_super_canvas_bgcolor;
char *video_letterbox_bgcolor;
char *video_mute_banner;
char *no_video_avatar;
conference_video_mode_t conference_video_mode;
int video_quality;
+3 -3
View File
@@ -720,7 +720,7 @@ static switch_status_t video_thread_callback(switch_core_session_t *session, swi
switch_assert(context->rawImage->width * 3 == context->rawImage->widthStep);
}
switch_img_to_raw(frame->img, context->rawImage->imageData, context->rawImage->widthStep * context->h, SWITCH_IMG_FMT_RGB24);
switch_img_to_raw(frame->img, context->rawImage->imageData, context->rawImage->widthStep, SWITCH_IMG_FMT_RGB24);
detectAndDraw(context);
if (context->detected.simo_count > 20) {
@@ -1167,7 +1167,7 @@ SWITCH_STANDARD_APP(cv_bug_start_function)
int x, n;
char *argv[25] = { 0 };
int argc;
switch_media_bug_flag_t flags = SMBF_READ_VIDEO_PING;
switch_media_bug_flag_t flags = SMBF_READ_VIDEO_PING | SMBF_READ_VIDEO_PATCH;
const char *function = "mod_cv";
if ((bug = (switch_media_bug_t *) switch_channel_get_private(channel, "_cv_bug_"))) {
@@ -1228,7 +1228,7 @@ SWITCH_STANDARD_API(cv_bug_api_function)
char *nested_cascade_path = NULL;
char *lbuf = NULL;
int x, n, i;
switch_media_bug_flag_t flags = SMBF_READ_VIDEO_PING;
switch_media_bug_flag_t flags = SMBF_READ_VIDEO_PING | SMBF_READ_VIDEO_PATCH;
const char *function = "mod_cv";
if (zstr(cmd)) {
@@ -4356,6 +4356,62 @@ SWITCH_STANDARD_APP(wait_for_silence_function)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", WAIT_FOR_SILENCE_SYNTAX);
}
#define DETECT_AUDIO_SYNTAX "<threshold> <audio_hits> <timeout_ms> [<file>]"
SWITCH_STANDARD_APP(detect_audio_function)
{
char *argv[5] = { 0 };
uint32_t thresh, audio_hits, timeout_ms = 0;
int argc;
char *lbuf = NULL;
if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data))
&& (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) >= 3) {
thresh = atoi(argv[0]);
audio_hits = atoi(argv[1]);
timeout_ms = atoi(argv[2]);
if (argv[3]) {
timeout_ms = switch_atoui(argv[3]);
}
if (thresh > 0 && audio_hits > 0) {
switch_ivr_detect_audio(session, thresh, audio_hits, timeout_ms, argv[4]);
return;
}
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", DETECT_AUDIO_SYNTAX);
}
#define DETECT_SILENCE_SYNTAX "<threshold> <silence_hits> <timeout_ms> [<file>]"
SWITCH_STANDARD_APP(detect_silence_function)
{
char *argv[5] = { 0 };
uint32_t thresh, silence_hits, timeout_ms = 0;
int argc;
char *lbuf = NULL;
if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data))
&& (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) >= 3) {
thresh = atoi(argv[0]);
silence_hits = atoi(argv[1]);
timeout_ms = atoi(argv[2]);
if (argv[3]) {
timeout_ms = switch_atoui(argv[3]);
}
if (thresh > 0 && silence_hits > 0) {
switch_ivr_detect_silence(session, thresh, silence_hits, timeout_ms, argv[4]);
return;
}
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", DETECT_SILENCE_SYNTAX);
}
static switch_status_t event_chat_send(switch_event_t *message_event)
{
@@ -6270,6 +6326,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SAF_SUPPORT_NOMEDIA | SAF_ZOMBIE_EXEC);
SWITCH_ADD_APP(app_interface, "say", "say", "say", say_function, SAY_SYNTAX, SAF_NONE);
SWITCH_ADD_APP(app_interface, "detect_audio", "detect_audio", "detect_audio", detect_audio_function, DETECT_AUDIO_SYNTAX,
SAF_NONE);
SWITCH_ADD_APP(app_interface, "detect_silence", "detect_silence", "detect_silence", detect_silence_function, DETECT_SILENCE_SYNTAX,
SAF_NONE);
SWITCH_ADD_APP(app_interface, "wait_for_silence", "wait_for_silence", "wait_for_silence", wait_for_silence_function, WAIT_FOR_SILENCE_SYNTAX,
SAF_NONE);
SWITCH_ADD_APP(app_interface, "session_loglevel", "session_loglevel", "session_loglevel", session_loglevel_function, SESSION_LOGLEVEL_SYNTAX,
-2
View File
@@ -141,8 +141,6 @@ static switch_status_t load_config(void)
globals.nameserver[inameserver] = (char *) val;
inameserver++;
}
} else if (!strcasecmp(var, "log-level-trace")) {
}
}
}
+1
View File
@@ -2756,6 +2756,7 @@ SWITCH_STANDARD_APP(fifo_function)
switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
switch_channel_set_variable(channel, "fifo_status", "WAITING");
switch_channel_set_variable(channel, "fifo_timestamp", date);
switch_channel_set_variable(channel, "fifo_push_timestamp", date);
switch_channel_set_variable(channel, "fifo_serviced_uuid", NULL);
switch_channel_set_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_BRIDGE_TAG);
@@ -376,7 +376,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_hiredis_load)
SWITCH_ADD_LIMIT(limit_interface, "hiredis", hiredis_limit_incr, hiredis_limit_release, hiredis_limit_usage,
hiredis_limit_reset, hiredis_limit_status, hiredis_limit_interval_reset);
SWITCH_ADD_APP(app_interface, "hiredis_raw", "hiredis_raw", "hiredis_raw", raw_app, "", SAF_NONE);
SWITCH_ADD_APP(app_interface, "hiredis_raw", "hiredis_raw", "hiredis_raw", raw_app, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
SWITCH_ADD_API(api_interface, "hiredis_raw", "hiredis_raw", raw_api, "");
return SWITCH_STATUS_SUCCESS;
+28 -3
View File
@@ -1288,7 +1288,6 @@ static size_t file_callback(void *ptr, size_t size, size_t nmemb, void *data)
{
register unsigned int realsize = (unsigned int) (size * nmemb);
client_t *client = data;
char *zero = "\0";
client->bytes += realsize;
@@ -1299,7 +1298,6 @@ static size_t file_callback(void *ptr, size_t size, size_t nmemb, void *data)
}
switch_buffer_write(client->buffer, ptr, realsize);
switch_buffer_write(client->buffer, zero, 1);
return realsize;
}
@@ -2313,6 +2311,9 @@ SWITCH_STANDARD_APP(httapi_function)
const char *ct = switch_event_get_header(client->headers, "content-type");
if (switch_stristr("text/xml", ct)) {
char *zero = "\0";
switch_buffer_write(client->buffer, zero, 1);
status = parse_xml(client);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received unsupported content-type %s\n", ct);
@@ -2967,12 +2968,18 @@ static switch_status_t file_open(switch_file_handle_t *handle, const char *path,
context->cache_file,
handle->channels,
handle->samplerate,
SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL)) != SWITCH_STATUS_SUCCESS) {
handle->flags, NULL)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid cache file %s opening url %s Discarding file.\n", context->cache_file, path);
unlink(context->cache_file);
unlink(context->meta_file);
return status;
}
if (switch_test_flag(&context->fh, SWITCH_FILE_FLAG_VIDEO)) {
switch_set_flag(handle, SWITCH_FILE_FLAG_VIDEO);
} else {
switch_set_flag(handle, SWITCH_FILE_FLAG_VIDEO);
}
}
handle->private_info = context;
@@ -3057,6 +3064,20 @@ static switch_status_t http_file_file_close(switch_file_handle_t *handle)
}
static switch_status_t http_file_read_video(switch_file_handle_t *handle, switch_frame_t *frame, switch_video_read_flag_t flags)
{
http_file_context_t *context = handle->private_info;
return switch_core_file_read_video(&context->fh, frame, flags);
}
static switch_status_t http_file_write_video(switch_file_handle_t *handle, switch_frame_t *frame)
{
http_file_context_t *context = handle->private_info;
return switch_core_file_write_video(&context->fh, frame);
}
static switch_status_t http_file_write(switch_file_handle_t *handle, void *data, size_t *len)
{
http_file_context_t *context = handle->private_info;
@@ -3121,6 +3142,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_httapi_load)
http_file_interface->file_read = http_file_file_read;
http_file_interface->file_write = http_file_write;
http_file_interface->file_seek = http_file_file_seek;
http_file_interface->file_read_video = http_file_read_video;
http_file_interface->file_write_video = http_file_write_video;
https_file_supported_formats[0] = "https";
@@ -3132,6 +3155,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_httapi_load)
https_file_interface->file_read = http_file_file_read;
https_file_interface->file_write = http_file_write;
https_file_interface->file_seek = http_file_file_seek;
https_file_interface->file_read_video = http_file_read_video;
https_file_interface->file_write_video = http_file_write_video;
switch_snprintf(globals.cache_path, sizeof(globals.cache_path), "%s%shttp_file_cache", SWITCH_GLOBAL_dirs.storage_dir, SWITCH_PATH_SEPARATOR);
switch_dir_make_recursive(globals.cache_path, SWITCH_DEFAULT_DIR_PERMS, pool);
@@ -1740,6 +1740,12 @@ static switch_status_t http_cache_file_open(switch_file_handle_t *handle, const
switch_clear_flag_locked(handle, SWITCH_FILE_NATIVE);
}
if (switch_test_flag(&context->fh, SWITCH_FILE_FLAG_VIDEO)) {
switch_set_flag_locked(handle, SWITCH_FILE_FLAG_VIDEO);
} else {
switch_clear_flag_locked(handle, SWITCH_FILE_FLAG_VIDEO);
}
return status;
}
@@ -1791,6 +1797,30 @@ static switch_status_t http_file_write(switch_file_handle_t *handle, void *data,
return switch_core_file_write(&context->fh, data, len);
}
/**
* Read from HTTP video file
* @param handle
* @param frame
* @return
*/
static switch_status_t http_file_read_video(switch_file_handle_t *handle, switch_frame_t *frame, switch_video_read_flag_t flags)
{
struct http_context *context = (struct http_context *)handle->private_info;
return switch_core_file_read_video(&context->fh, frame, flags);
}
/**
* Write to HTTP video file
* @param handle
* @param frame
* @return
*/
static switch_status_t http_file_write_video(switch_file_handle_t *handle, switch_frame_t *frame)
{
struct http_context *context = (struct http_context *)handle->private_info;
return switch_core_file_write_video(&context->fh, frame);
}
/**
* Close HTTP file
* @param handle
@@ -1851,6 +1881,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_http_cache_load)
file_interface->file_close = http_file_close;
file_interface->file_read = http_file_read;
file_interface->file_write = http_file_write;
file_interface->file_read_video = http_file_read_video;
file_interface->file_write_video = http_file_write_video;
if (gcache.enable_file_formats) {
file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
@@ -1860,6 +1892,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_http_cache_load)
file_interface->file_close = http_file_close;
file_interface->file_read = http_file_read;
file_interface->file_write = http_file_write;
file_interface->file_read_video = http_file_read_video;
file_interface->file_write_video = http_file_write_video;
file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
file_interface->interface_name = modname;
@@ -1868,6 +1902,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_http_cache_load)
file_interface->file_close = http_file_close;
file_interface->file_read = http_file_read;
file_interface->file_write = http_file_write;
file_interface->file_read_video = http_file_read_video;
file_interface->file_write_video = http_file_write_video;
}
/* create the queue from configuration */
+14 -5
View File
@@ -251,23 +251,30 @@ SWITCH_STANDARD_API(mod_mongo_find_n_function)
mongoc_cursor_t *cursor = mongoc_collection_find(col, query_options, 0, n, 0, query, fields, NULL);
if (cursor && !mongoc_cursor_error(cursor, &error)) {
/* get results from cursor */
switch_stream_handle_t result_stream = { 0 };
const bson_t *result;
stream->write_function(stream, "-OK\n[");
SWITCH_STANDARD_STREAM(result_stream);
if (mongoc_cursor_more(cursor) && mongoc_cursor_next(cursor, &result)) {
char *json_result;
json_result = bson_as_json(result, NULL);
stream->write_function(stream, "%s", json_result);
result_stream.write_function(&result_stream, "%s", json_result);
bson_free(json_result);
}
while (mongoc_cursor_more(cursor) && mongoc_cursor_next(cursor, &result)) {
char *json_result;
json_result = bson_as_json(result, NULL);
stream->write_function(stream, ",%s", json_result);
result_stream.write_function(&result_stream, ",%s", json_result);
bson_free(json_result);
}
stream->write_function(stream, "]\n");
if (!mongoc_cursor_error(cursor, &error)) {
stream->write_function(stream, "-OK\n[%s]", zstr((char *)result_stream.data) ? "" :(char *)result_stream.data);
} else {
stream->write_function(stream, "-ERR\nquery failed: %s", error.message);
}
switch_safe_free(result_stream.data);
} else {
stream->write_function(stream, "-ERR\nquery failed!\n");
stream->write_function(stream, "-ERR\nquery failed: %s", error.message);
}
if (cursor) {
mongoc_cursor_destroy(cursor);
@@ -342,6 +349,8 @@ SWITCH_STANDARD_API(mod_mongo_find_one_function)
json_result = bson_as_json(result, NULL);
stream->write_function(stream, "-OK\n%s\n", json_result);
bson_free(json_result);
} else if (mongoc_cursor_error(cursor, &error)) {
stream->write_function(stream, "-ERR\nquery failed: %s\n", error.message);
} else {
/* empty set */
stream->write_function(stream, "-OK\n{}\n");
@@ -0,0 +1,17 @@
include $(top_srcdir)/build/modmake.rulesam
MODNAME=mod_sms_flowroute
if HAVE_H2O
mod_LTLIBRARIES = mod_sms_flowroute.la
mod_sms_flowroute_la_SOURCES = mod_sms_flowroute.c
mod_sms_flowroute_la_CFLAGS = $(AM_CFLAGS) $(H2O_CFLAGS) $(BROTLIENC_CFLAGS) $(BROTLIDEC_CFLAGS)
mod_sms_flowroute_la_LIBADD = $(switch_builddir)/libfreeswitch.la
mod_sms_flowroute_la_LDFLAGS = -avoid-version -module -no-undefined -shared $(H2O_LIBS) $(BROTLIENC_LIBS) $(BROTLIDEC_LIBS) $(SWITCH_AM_LDFLAGS)
else
install: error
all: error
error:
$(error You must install libh2o and libh2o-dev to build this module)
endif
@@ -0,0 +1,30 @@
For inbound, these are known leaks on per module load(not per message). These will likely require additions to libh2o to add a destroy function.
=================================================================
==4164==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 1104 byte(s) in 26 object(s) allocated from:
#0 0x4c1e28 in __interceptor_malloc (/usr/local/freeswitch_sms_flowroute/bin/freeswitch+0x4c1e28)
#1 0x7f868d71acbd in wcsdup /build/glibc-h_iKOs/glibc-2.19/wcsmbs/wcsdup.c:30
Direct leak of 184 byte(s) in 1 object(s) allocated from:
#0 0x4c1e28 in __interceptor_malloc (/usr/local/freeswitch_sms_flowroute/bin/freeswitch+0x4c1e28)
#1 0x7f867cdcbaee in h2o_mem_alloc /usr/src/h2o/include/h2o/memory.h:298
#2 0x7f867cdcbaee in create_socket /usr/src/h2o/lib/common/socket/evloop.c.h:361
Indirect leak of 184 byte(s) in 1 object(s) allocated from:
#0 0x4c1e28 in __interceptor_malloc (/usr/local/freeswitch_sms_flowroute/bin/freeswitch+0x4c1e28)
#1 0x7f867cdcbaee in h2o_mem_alloc /usr/src/h2o/include/h2o/memory.h:298
#2 0x7f867cdcbaee in create_socket /usr/src/h2o/lib/common/socket/evloop.c.h:361
Indirect leak of 88 byte(s) in 1 object(s) allocated from:
#0 0x4c1e28 in __interceptor_malloc (/usr/local/freeswitch_sms_flowroute/bin/freeswitch+0x4c1e28)
#1 0x7f867cdc9e12 in h2o_mem_alloc /usr/src/h2o/include/h2o/memory.h:298
#2 0x7f867cdc9e12 in h2o_multithread_create_queue /usr/src/h2o/lib/common/multithread.c:106
SUMMARY: AddressSanitizer: 1560 byte(s) leaked in 29 allocation(s).
@@ -0,0 +1,669 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2015, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* William King <william.king@quentustech.com>
*
* mod_sms_flowroute.c SMS support for Flowroute SMS
*
*/
#include "mod_sms_flowroute.h"
SWITCH_MODULE_LOAD_FUNCTION(mod_sms_flowroute_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sms_flowroute_shutdown);
SWITCH_MODULE_DEFINITION(mod_sms_flowroute, mod_sms_flowroute_load, mod_sms_flowroute_shutdown, NULL);
mod_sms_flowroute_globals_t mod_sms_flowroute_globals;
static void on_accept(h2o_socket_t *listener, const char *error)
{
mod_sms_flowroute_profile_t *profile = listener->data;
h2o_socket_t *sock = NULL;
if ( error != NULL ){
return;
}
if ((sock = h2o_evloop_socket_accept(listener)) == NULL) {
return;
}
h2o_accept(profile->h2o_accept_context, sock);
}
static void mod_sms_flowroute_profile_event_thread_on_timeout(h2o_timeout_entry_t *entry)
{
/* required to have this callback, to enable any per interval checks or cleanup. */
}
static void *SWITCH_THREAD_FUNC mod_sms_flowroute_profile_event_thread(switch_thread_t *thread, void *obj)
{
mod_sms_flowroute_profile_t *profile = obj;
struct sockaddr_in addr;
int fd, reuseaddr_flag = 1, err = 0;
h2o_socket_t *sock;
h2o_timeout_t timeout = {0};
h2o_timeout_entry_t timeout_entry = {0};
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(profile->port);
err = (fd = socket(AF_INET, SOCK_STREAM, 0));
if (err == -1 ) {
fprintf(stderr, "unable to open socket [%d]\n", err);
return 0;
}
err = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_flag, sizeof(reuseaddr_flag));
if (err != 0) {
fprintf(stderr, "Unable to set socket options [%d]\n", err);
return 0;
}
err = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
if (err != 0 ) {
fprintf(stderr, "Unable to bind to socket [%d]\n", err);
perror("bind");
return 0;
}
err = listen(fd, SOMAXCONN);
if ( err != 0) {
fprintf(stderr, "Unable to listen on socket [%d]\n", err);
return 0;
}
sock = h2o_evloop_socket_create(profile->h2o_context.loop, fd, H2O_SOCKET_FLAG_DONT_READ);
sock->data = (void *) profile;
h2o_socket_read_start(sock, on_accept);
while ( profile->running ) {
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Profile[%s] event thread loop\n", profile->name);
h2o_timeout_init(profile->h2o_context.loop, &timeout, 1000); /* 1 second loop */
timeout_entry.cb = mod_sms_flowroute_profile_event_thread_on_timeout;
h2o_timeout_link(profile->h2o_context.loop, &timeout, &timeout_entry);
h2o_evloop_run(profile->h2o_context.loop);
h2o_timeout_unlink(&timeout_entry);
h2o_timeout_dispose(profile->h2o_context.loop, &timeout);
}
h2o_socket_close(sock);
return 0;
}
switch_status_t mod_sms_flowroute_profile_destroy(mod_sms_flowroute_profile_t **old_profile)
{
mod_sms_flowroute_profile_t *profile = NULL;
switch_status_t status;
if ( !old_profile || !*old_profile ) {
return SWITCH_STATUS_SUCCESS;
}
profile = *old_profile;
switch_core_hash_delete(mod_sms_flowroute_globals.profile_hash, profile->name);
profile->running = 0;
if (profile->profile_thread) {
switch_thread_join(&status, profile->profile_thread);
}
switch_safe_free(profile->h2o_accept_context);
switch_safe_free(profile->h2o_context.loop);
h2o_context_dispose(&(profile->h2o_context));
h2o_config_dispose(&(profile->h2o_globalconf));
switch_core_destroy_memory_pool(&(profile->pool));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Profile[%s] destroyed\n", profile->name);
*old_profile = NULL;
return SWITCH_STATUS_SUCCESS;
}
static int mod_sms_flowroute_profile_request_handler(h2o_handler_t *handler, h2o_req_t *request)
{
static h2o_generator_t generator = {NULL, NULL};
h2o_iovec_t body = h2o_strdup(&request->pool, "ACCEPTED\n", SIZE_MAX);
char *content = strndup(request->entity.base, request->entity.len);
cJSON *parsed = NULL;
switch_event_t *evt = NULL;
/* If there were a better way to cJSON_Parse, but with a str and len, this could remove a strndup */
parsed = cJSON_Parse(content);
if ( !parsed ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Invalid request received[%.*s]", (int) request->entity.len, request->entity.base);
goto done;
}
switch_event_create(&evt, SWITCH_EVENT_MESSAGE);
switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM, "to", cJSON_GetObjectCstr(parsed, "to"));
switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM, "body", cJSON_GetObjectCstr(parsed, "body"));
switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM, "from", cJSON_GetObjectCstr(parsed, "from"));
switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM, "record_id", cJSON_GetObjectCstr(parsed, "id"));
switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM, "context", "default");
switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM, "proto", "sms_flowroute");
switch_core_chat_send("GLOBAL_SMS", evt);
switch_event_destroy(&evt);
request->res.status = 200;
request->res.reason = "OK";
h2o_add_header(&request->pool, &request->res.headers, H2O_TOKEN_CONTENT_TYPE, H2O_STRLIT("text/plain; charset=utf-8"));
h2o_start_response(request, &generator);
h2o_send(request, &body, 1, 1);
done:
cJSON_Delete(parsed);
switch_safe_free(content);
return 0;
}
switch_status_t mod_sms_flowroute_profile_create(mod_sms_flowroute_profile_t **new_profile, char *name, int debug, int port,
char *access_key, char *secret_key, char *host)
{
mod_sms_flowroute_profile_t *profile = NULL;
switch_memory_pool_t *pool = NULL;
switch_threadattr_t *thd_attr;
char auth[256] = {0};
unsigned int auth_size = 0;
switch_core_new_memory_pool(&pool);
profile = switch_core_alloc(pool, sizeof(mod_sms_flowroute_profile_t));
profile->pool = pool;
profile->debug = debug;
profile->running = 1;
profile->name = name ? switch_core_strdup(profile->pool, name) : "default";
profile->access_key = access_key ? switch_core_strdup(profile->pool, access_key) : "access_key";
profile->secret_key = secret_key ? switch_core_strdup(profile->pool, secret_key) : "secret_key";
profile->host = host ? switch_core_strdup(profile->pool, host) : "https://api.flowroute.com/v2/messages";
profile->port = port ? port : 8000;
auth_size = snprintf(auth, 256, "%s:%s", profile->access_key, profile->secret_key);
switch_b64_encode((unsigned char *)auth, auth_size, profile->auth_b64, 512);
profile->auth_b64_size = strlen((const char *)profile->auth_b64);
if ( h2o_url_parse(profile->host, SIZE_MAX, &profile->url_parsed) != 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Profile[%s] error processing url[%s]\n", profile->name, profile->host);
goto err;
}
h2o_config_init(&(profile->h2o_globalconf));
profile->h2o_hostconf = h2o_config_register_host(&(profile->h2o_globalconf), h2o_iovec_init(H2O_STRLIT("mod_sms_flowroute")), 2048);
/* Register h2o handlers here */
profile->h2o_pathconf = h2o_config_register_path(profile->h2o_hostconf, "/", 0);
profile->h2o_handler = h2o_create_handler(profile->h2o_pathconf, sizeof(h2o_handler_t));
profile->h2o_handler->on_req = mod_sms_flowroute_profile_request_handler;
h2o_context_init(&(profile->h2o_context), h2o_evloop_create(), &(profile->h2o_globalconf));
profile->queue = h2o_multithread_create_queue(profile->h2o_context.loop);
profile->h2o_accept_context = calloc(1, sizeof(h2o_accept_ctx_t));
profile->h2o_accept_context->ctx = &(profile->h2o_context);
profile->h2o_accept_context->hosts = profile->h2o_globalconf.hosts;
switch_threadattr_create(&thd_attr, pool);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
switch_thread_create(&(profile->profile_thread), thd_attr, mod_sms_flowroute_profile_event_thread, (void *) profile, pool);
switch_core_hash_insert(mod_sms_flowroute_globals.profile_hash, name, (void *) profile);
*new_profile = profile;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Profile[%s] created\n", profile->name);
return SWITCH_STATUS_SUCCESS;
err:
return SWITCH_STATUS_GENERR;
}
static int on_body(h2o_http1client_t *client, const char *errstr)
{
h2o_http1client_ctx_t *ctx = client->ctx;
mod_sms_flowroute_message_t *msg = H2O_STRUCT_FROM_MEMBER(mod_sms_flowroute_message_t, ctx, ctx);
if (errstr != NULL && errstr != h2o_http1client_error_is_eos) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SMS Send error on_body[%s]\n", errstr);
goto err;
}
fwrite(client->sock->input->bytes, 1, client->sock->input->size, stdout);
h2o_buffer_consume(&client->sock->input, client->sock->input->size);
if (errstr == h2o_http1client_error_is_eos) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "SMS Send EOS\n");
}
msg->status = 0;
switch_mutex_unlock(msg->mutex);
return 0;
err:
msg->status = 3;
switch_mutex_unlock(msg->mutex);
return -1;
}
static h2o_http1client_body_cb on_head(h2o_http1client_t *client, const char *errstr, int minor_version, int status, h2o_iovec_t msg_iovec,
h2o_http1client_header_t *headers, size_t num_headers)
{
size_t i;
switch_log_level_t loglevel = SWITCH_LOG_DEBUG;
h2o_http1client_ctx_t *ctx = client->ctx;
mod_sms_flowroute_message_t *msg = H2O_STRUCT_FROM_MEMBER(mod_sms_flowroute_message_t, ctx, ctx);
if (errstr != NULL && errstr != h2o_http1client_error_is_eos) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SMS Send error on_head[%s]\n", errstr);
goto err;
}
if ( status != 200 ) {
loglevel = SWITCH_LOG_ERROR;
}
switch_log_printf(SWITCH_CHANNEL_LOG, loglevel, "HTTP/1.%d %d %.*s\n", minor_version, status, (int)msg_iovec.len, msg_iovec.base);
for (i = 0; i != num_headers; ++i) {
switch_log_printf(SWITCH_CHANNEL_LOG, loglevel, "%.*s: %.*s\n",
(int)headers[i].name_len, headers[i].name, (int)headers[i].value_len, headers[i].value);
}
if (errstr == h2o_http1client_error_is_eos) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SMS Send error on_head no body received[%s]\n", errstr);
goto err;
}
return on_body;
err:
msg->status = 2;
switch_mutex_unlock(msg->mutex);
return NULL;
}
static h2o_http1client_head_cb on_connect(h2o_http1client_t *client, const char *errstr, h2o_iovec_t **reqbufs, size_t *reqbufcnt,
int *method_is_head)
{
h2o_http1client_ctx_t *ctx = client->ctx;
mod_sms_flowroute_message_t *msg = H2O_STRUCT_FROM_MEMBER(mod_sms_flowroute_message_t, ctx, ctx);
if (errstr != NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SMS Send error on_connect[%s]\n", errstr);
goto err;
}
*reqbufs = (h2o_iovec_t *)client->data;
*reqbufcnt = 1;
*method_is_head = 0;
return on_head;
err:
msg->status = 1;
switch_mutex_unlock(msg->mutex);
return NULL;
}
switch_status_t mod_sms_flowroute_profile_send_message(mod_sms_flowroute_profile_t *profile, switch_event_t *event)
{
mod_sms_flowroute_message_t *msg = NULL;
char *to = NULL, *from = NULL, *text = NULL;
switch_status_t status = SWITCH_STATUS_GENERR;
int wait_loops = 10; /* 10 seconds */
cJSON *body = NULL;
msg = calloc(1, sizeof(mod_sms_flowroute_message_t));
msg->req.base = calloc(1, 2048);
msg->ctx.getaddr_receiver = &msg->getaddr_receiver;
msg->ctx.io_timeout = &msg->io_timeout;
msg->ctx.loop = profile->h2o_context.loop;
msg->profile = profile;
msg->status = -1;
h2o_timeout_init(msg->ctx.loop, &msg->io_timeout, 5000); /* 5 seconds */
h2o_multithread_register_receiver(profile->queue, msg->ctx.getaddr_receiver, h2o_hostinfo_getaddr_receiver);
msg->ctx.ssl_ctx = SSL_CTX_new(TLSv1_2_client_method());
SSL_CTX_load_verify_locations(msg->ctx.ssl_ctx, NULL, "/etc/ssl/certs/");
SSL_CTX_set_verify(msg->ctx.ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
switch_mutex_init(&msg->mutex, SWITCH_MUTEX_UNNESTED, profile->pool);
switch_mutex_lock(msg->mutex);
body = cJSON_CreateObject();
to = switch_event_get_header(event, "to");
if ( !to ) {
to = switch_event_get_header(event, "destination_addr");
}
from = switch_event_get_header(event, "from");
if ( !from ) {
from = switch_event_get_header(event, "source_addr");
}
cJSON_AddItemToObject(body, "to", cJSON_CreateString(to));
cJSON_AddItemToObject(body, "from", cJSON_CreateString(from));
cJSON_AddItemToObject(body, "body", cJSON_CreateString((const char *) switch_event_get_body(event)));
text = cJSON_Print(body);
cJSON_Delete(body);
msg->req.len = snprintf(msg->req.base, 2048, "POST %.*s HTTP/1.1\r\n"
"Authorization: Basic %.*s\r\n"
"Host: %.*s\r\n"
"Accept: */*\r\n"
"Content-Type: application/json\r\n"
"Content-Length: %d\r\n"
"\r\n%s",
(int) profile->url_parsed.path.len, profile->url_parsed.path.base,
profile->auth_b64_size, profile->auth_b64,
(int) profile->url_parsed.authority.len, profile->url_parsed.authority.base,
(int)strlen(text), text);
if ( profile->debug ) {
char *msg_txt = NULL;
switch_event_serialize(event, &msg_txt, SWITCH_FALSE);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Profile[%s] sending message from event\n%s\n", profile->name, msg_txt);
switch_safe_free(msg_txt);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Profile[%s] sending message json:\n%s\n", profile->name, text);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "REQUEST\n\n%.*s\n\n", (int) msg->req.len, msg->req.base);
}
h2o_http1client_connect(NULL, &msg->req, &(msg->ctx), profile->url_parsed.host, h2o_url_get_port(&profile->url_parsed), 1, on_connect);
do {
switch_yield(1000000);
wait_loops--;
status = switch_mutex_trylock(msg->mutex);
} while ( wait_loops > 0 && status != SWITCH_STATUS_SUCCESS);
if ( status != SWITCH_STATUS_SUCCESS ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Profile[%s] send_message thread timed out on send\n", profile->name);
goto err;
}
if ( msg->status > 0 ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Profile[%s] send_message resulted in failure status %d\n", profile->name, msg->status);
goto err;
}
h2o_timeout_dispose(msg->ctx.loop, msg->ctx.io_timeout);
switch_mutex_destroy(msg->mutex);
switch_safe_free(msg->req.base);
switch_safe_free(msg);
return SWITCH_STATUS_SUCCESS;
err:
if ( msg && msg->mutex ) {
switch_mutex_destroy(msg->mutex);
}
h2o_timeout_dispose(msg->ctx.loop, msg->ctx.io_timeout);
switch_safe_free(msg->req.base);
switch_safe_free(msg);
return SWITCH_STATUS_GENERR;
}
switch_status_t mod_sms_flowroute_interface_chat_send(switch_event_t *event)
{
mod_sms_flowroute_profile_t *profile = NULL;
char *profile_name = switch_event_get_header(event, "sms_flowroute_profile");
if (zstr(profile_name)) {
profile_name = "default";
}
profile = switch_core_hash_find(mod_sms_flowroute_globals.profile_hash, profile_name);
if (!profile) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "NO SUCH SMS_FLOWROUTE PROFILE[%s].", profile_name);
return SWITCH_STATUS_GENERR;
}
mod_sms_flowroute_profile_send_message(profile, event);
return SWITCH_STATUS_SUCCESS;
}
/* static switch_status_t name (switch_event_t *message, const char *data) */
SWITCH_STANDARD_CHAT_APP(mod_sms_flowroute_chat_send_function)
{
mod_sms_flowroute_profile_t *profile = NULL;
profile = switch_core_hash_find(mod_sms_flowroute_globals.profile_hash, data);
if ( !profile ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "NO SUCH SMS_FLOWROUTE PROFILE[%s].", data);
return SWITCH_STATUS_GENERR;
}
mod_sms_flowroute_profile_send_message(profile, message);
return SWITCH_STATUS_SUCCESS;
}
/* static void name (switch_core_session_t *session, const char *data) */
SWITCH_STANDARD_APP(mod_sms_flowroute_app_send_function)
{
switch_event_header_t *chan_var = NULL;
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_event_t *message = NULL;
if (switch_event_create(&message, SWITCH_EVENT_MESSAGE) != SWITCH_STATUS_SUCCESS) {
return;
}
/* Copy over recognized channel vars. Then call the chat send function */
/* Cycle through all of the channel headers, and ones with 'sms_flowroute_' prefix copy over without the prefix */
for ( chan_var = switch_channel_variable_first(channel); chan_var; chan_var = chan_var->next) {
if ( !strncmp(chan_var->name, "sms_flowroute_", 14) ) {
switch_event_add_header_string(message, SWITCH_STACK_BOTTOM, chan_var->name + 14, chan_var->value);
}
}
/* Unlock the channel variables */
switch_channel_variable_last(channel);
mod_sms_flowroute_chat_send_function(message, data);
return;
}
/* static switch_status_t name (_In_opt_z_ const char *cmd, _In_opt_ switch_core_session_t *session, _In_ switch_stream_handle_t *stream) */
SWITCH_STANDARD_API(mod_sms_flowroute_debug_api)
{
mod_sms_flowroute_globals.debug = switch_true(cmd);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "debug is %s\n", (mod_sms_flowroute_globals.debug ? "on" : "off") );
return SWITCH_STATUS_SUCCESS;
}
/* static switch_status_t name (_In_opt_z_ const char *cmd, _In_opt_ switch_core_session_t *session, _In_ switch_stream_handle_t *stream) */
SWITCH_STANDARD_API(mod_sms_flowroute_send_api)
{
mod_sms_flowroute_profile_t *profile = NULL;
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_event_t *message = NULL;
char *argv[1024] = { 0 };
int argc = 0;
char *cmd_dup = strdup(cmd);
if (!(argc = switch_separate_string(cmd_dup, '|', argv, (sizeof(argv) / sizeof(argv[0])))) || argc != 4 ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid format. Must be | separated like: profile|destination|source|message\n");
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
profile = switch_core_hash_find(mod_sms_flowroute_globals.profile_hash, argv[0]);
if ( !profile ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "NO SUCH SMS_FLOWROUTE PROFILE[%s].", argv[0]);
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
if (switch_event_create(&message, SWITCH_EVENT_MESSAGE) != SWITCH_STATUS_SUCCESS) {
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
switch_event_add_header_string(message, SWITCH_STACK_BOTTOM, "destination_addr", argv[1]);
switch_event_add_header_string(message, SWITCH_STACK_BOTTOM, "source_addr", argv[2]);
switch_event_set_body(message, argv[3]);
if (mod_sms_flowroute_profile_send_message(profile, message) != SWITCH_STATUS_SUCCESS) {
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
done:
switch_safe_free(cmd_dup);
return status;
}
switch_status_t mod_sms_flowroute_do_config()
{
char *conf = "sms_flowroute.conf";
switch_xml_t xml, cfg, profiles, profile, params, param;
if (!(xml = switch_xml_open_cfg(conf, &cfg, NULL))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", conf);
goto err;
}
if ( (profiles = switch_xml_child(cfg, "profiles")) != NULL) {
for (profile = switch_xml_child(profiles, "profile"); profile; profile = profile->next) {
mod_sms_flowroute_profile_t *new_profile = NULL;
int debug = 0, port = 0;
char *access_key = NULL, *secret_key = NULL, *host = NULL;
char *name = (char *)switch_xml_attr_soft(profile, "name");
// Load params
if ( (params = switch_xml_child(profile, "params")) != NULL) {
for (param = switch_xml_child(params, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
if ( ! strncmp(var, "debug", 5) ) {
debug = atoi(switch_xml_attr_soft(param, "value"));
} else if ( ! strncmp(var, "port", 4) ) {
port = atoi(switch_xml_attr_soft(param, "value"));
} else if ( ! strncmp(var, "access-key", 10) ) {
access_key = (char *) switch_xml_attr_soft(param, "value");
} else if ( ! strncmp(var, "secret-key", 10) ) {
secret_key = (char *) switch_xml_attr_soft(param, "value");
} else if ( ! strncmp(var, "host", 4) ) {
host = (char *) switch_xml_attr_soft(param, "value");
}
}
}
if ( mod_sms_flowroute_profile_create(&new_profile, name, debug, port, access_key, secret_key, host) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Created profile[%s]\n", name);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create profile[%s]\n", name);
}
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Profiles config is missing\n");
goto err;
}
switch_xml_free(xml);
return SWITCH_STATUS_SUCCESS;
err:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Configuration failed\n");
if(xml){
switch_xml_free(xml);
}
return SWITCH_STATUS_GENERR;
}
/* switch_status_t name (switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */
SWITCH_MODULE_LOAD_FUNCTION(mod_sms_flowroute_load)
{
switch_api_interface_t *mod_sms_flowroute_api_interface;
switch_chat_interface_t *mod_sms_flowroute_chat_interface;
switch_chat_application_interface_t *mod_sms_flowroute_chat_app_interface;
switch_application_interface_t *mod_sms_flowroute_app_interface;
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
memset(&mod_sms_flowroute_globals, 0, sizeof(mod_sms_flowroute_globals_t));
mod_sms_flowroute_globals.pool = pool;
mod_sms_flowroute_globals.debug = 0;
switch_core_hash_init(&(mod_sms_flowroute_globals.profile_hash));
if ( mod_sms_flowroute_do_config() != SWITCH_STATUS_SUCCESS ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to load due to bad configs\n");
return SWITCH_STATUS_TERM;
}
/* SSL_load_error_strings();
SSL_library_init();
OpenSSL_add_all_algorithms();*/
SWITCH_ADD_CHAT(mod_sms_flowroute_chat_interface, "sms_flowroute", mod_sms_flowroute_interface_chat_send);
SWITCH_ADD_API(mod_sms_flowroute_api_interface, "sms_flowroute_send", "mod_sms_flowroute send", mod_sms_flowroute_send_api, NULL);
SWITCH_ADD_API(mod_sms_flowroute_api_interface, "sms_flowroute_debug", "mod_sms_flowroute toggle debug", mod_sms_flowroute_debug_api, NULL);
SWITCH_ADD_CHAT_APP(mod_sms_flowroute_chat_app_interface, "sms_flowroute_send", "send message to profile", "send message to profile",
mod_sms_flowroute_chat_send_function, "", SCAF_NONE);
SWITCH_ADD_APP(mod_sms_flowroute_app_interface, "sms_flowroute_send", NULL, NULL, mod_sms_flowroute_app_send_function,
"sms_flowroute_send", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sms_flowroute_shutdown)
{
switch_hash_index_t *hi;
mod_sms_flowroute_profile_t *profile = NULL;
while ((hi = switch_core_hash_first(mod_sms_flowroute_globals.profile_hash))) {
switch_core_hash_this(hi, NULL, NULL, (void **)&profile);
mod_sms_flowroute_profile_destroy(&profile);
switch_safe_free(hi);
}
switch_core_hash_destroy(&(mod_sms_flowroute_globals.profile_hash));
return SWITCH_STATUS_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/
@@ -0,0 +1,93 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Based on mod_skel by
* Anthony Minessale II <anthm@freeswitch.org>
*
* Contributor(s):
*
* William King <william.king@quentustech.com>
*
* mod_sms_flowroute.c SMS support for Flowroute SMS
*
*/
#ifndef MOD_SMS_FLOWROUTE_H
#define MOD_SMS_FLOWROUTE_H
#define H2O_USE_LIBUV 0
#define H2O_USE_BROTLI 1
#include <switch.h>
#include "h2o.h"
#include "h2o/http1client.h"
typedef struct {
char *name;
int port;
int debug;
int running;
char *host;
char *access_key;
char *secret_key;
unsigned char auth_b64[512];
int auth_b64_size;
h2o_url_t url_parsed;
h2o_socketpool_t *sockpool;
h2o_globalconf_t h2o_globalconf;
h2o_hostconf_t *h2o_hostconf;
h2o_pathconf_t *h2o_pathconf;
h2o_handler_t *h2o_handler;
h2o_context_t h2o_context;
h2o_accept_ctx_t *h2o_accept_context;
h2o_multithread_queue_t *queue;
switch_thread_t *profile_thread;
switch_memory_pool_t *pool;
} mod_sms_flowroute_profile_t;
typedef struct {
h2o_http1client_ctx_t ctx;
mod_sms_flowroute_profile_t *profile;
switch_mutex_t *mutex;
h2o_iovec_t req;
int status;
h2o_multithread_receiver_t getaddr_receiver;
h2o_timeout_t io_timeout;
} mod_sms_flowroute_message_t;
typedef struct mod_sms_flowroute_globals_s {
switch_memory_pool_t *pool;
switch_hash_t *profile_hash;
int debug;
} mod_sms_flowroute_globals_t;
extern mod_sms_flowroute_globals_t mod_sms_flowroute_globals;
#endif /* MOD_SMS_FLOWROUTE_H */
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2016, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -849,17 +849,22 @@ static switch_bool_t callprogress_detector_process_buffer(switch_media_bug_t *bu
tone_detector_process_buffer(detector, frame->data, frame->samples, &detected_tone);
if (detected_tone) {
switch_event_t *event = NULL;
switch_channel_t *channel = NULL;
switch_channel_t *channel = switch_core_session_get_channel(session);
const char *execute_on_tone_var = switch_core_session_sprintf(session, "execute_on_spandsp_tone_detect_%s", detected_tone);
const char *api_on_tone_var = switch_core_session_sprintf(session, "api_on_spandsp_tone_detect_%s", detected_tone);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "DETECTED TONE: %s\n", detected_tone);
switch_channel_execute_on(channel, execute_on_tone_var);
switch_channel_api_on(channel, api_on_tone_var);
if (switch_event_create(&event, SWITCH_EVENT_DETECTED_TONE) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detected-Tone", detected_tone);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(session));
channel = switch_core_session_get_channel(session);
if (channel) switch_channel_event_set_data(channel, event);
switch_channel_event_set_data(channel, event);
switch_event_fire(&event);
}
if (switch_true(switch_channel_get_variable(channel, "spandsp_tone_detect_stop_on_tone"))) {
/* all done */
return SWITCH_FALSE;
}
}
break;
}
+3 -3
View File
@@ -168,7 +168,7 @@ static switch_status_t process_event(switch_event_t *event)
char *username[5] = { NULL };
char *domain[5] = { NULL };
char key[512];
char *uuid = NULL, *my_uuid = NULL;
char *my_uuid = NULL;
int i;
int found = 0;
@@ -203,7 +203,7 @@ static switch_status_t process_event(switch_event_t *event)
}
}
for (i = 0; i < 4; i++) {
for (i = 0; i < 5; i++) {
if (username[i] && domain[i]) {
spy_t *spy = NULL;
@@ -215,7 +215,7 @@ static switch_status_t process_event(switch_event_t *event)
switch_channel_t *channel = switch_core_session_get_channel(session);
my_uuid = switch_event_get_header(event, "Unique-ID");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "UserSpy retrieved uuid %s for key %s, activating eavesdrop\n", uuid, key);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "UserSpy retrieved uuid %s for key %s, activating eavesdrop\n", my_uuid, key);
switch_channel_set_variable(channel, "spy_uuid", my_uuid);
found++;
@@ -776,6 +776,7 @@ static switch_status_t find_non_loopback_bridge(switch_core_session_t *session,
const char *a_uuid = NULL;
switch_core_session_t *sp = NULL;
*br_session = NULL;
*br_uuid = NULL;
@@ -787,7 +788,9 @@ static switch_status_t find_non_loopback_bridge(switch_core_session_t *session,
switch_channel_t *spchan = switch_core_session_get_channel(sp);
switch_channel_wait_for_state_or_greater(spchan, channel, CS_ROUTING);
if (switch_false(switch_channel_get_variable(spchan, "loopback_bowout"))) break;
tech_pvt = switch_core_session_get_private(sp);
if (tech_pvt->other_channel) {
@@ -495,6 +495,30 @@
really need to change this.
-->
<!-- <param name="renegotiate-codec-on-hold" value="true"/> -->
<!-- Turn on proxy hold when proxy media and proxy mode are disabled
By default it is not set
-->
<!-- <param name="proxy-hold" value="true"/> -->
<!-- Choose the proxy notify events. Default is not set
all - every in-dialogs call sip notify will be proxy to the core pbx or b2bua
<param name="proxy-notify-events" value="all"/>
<eventlist> - only event list sip notify will be proxy to the core pbx or b2bua
this option provide users to specific events to be proxy through
e.g talk,conference
<param name="proxy-notify-events" value="talk,conference"/>
-->
<!-- Choose the proxy info content type. Default is not set.
all - every in-dialogs call sip infos will be proxy to the core pbx or b2bua
<param name="proxy-info-content-types" value="all"/>
<info_content_type_list> - only content type list of sip info will be proxy to the core pbx
or b2bua this option provide users to specific infos to be proxy through
e.g application/pause-recording,application/resume-recording
<param name="proxy-info-content-types" value="application/pause-recording,application/resume-recording"/>
-->
</settings>
</profile>
</profiles>
+143 -130
View File
@@ -50,6 +50,7 @@ switch_endpoint_interface_t *sofia_endpoint_interface;
#define STRLEN 15
void mod_sofia_shutdown_cleanup();
static switch_status_t sofia_on_init(switch_core_session_t *session);
static switch_status_t sofia_on_exchange_media(switch_core_session_t *session);
@@ -1212,7 +1213,6 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
case SWITCH_MESSAGE_INDICATE_MEDIA_RENEG:
{
if (msg->string_arg) {
sofia_set_media_flag(tech_pvt->profile, SCMF_RENEG_ON_REINVITE);
sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA);
}
@@ -1378,25 +1378,21 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
break;
case SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ:
if (!switch_channel_test_flag(channel, CF_AVPF)) {
//const char *ua = switch_channel_get_variable(tech_pvt->channel, "sip_user_agent");
//if (ua && switch_stristr("polycom", ua)) {
//const char *pl = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<media_control>\n<vc_primitive>\n<to_encoder>\n<picture_fast_update>\n</picture_fast_update>\n</to_encoder>\n</vc_primitive>\n</media_control>";
const char *pl = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<media_control><vc_primitive><to_encoder><picture_fast_update /></to_encoder></vc_primitive></media_control>\n";
switch_time_t now = switch_micro_time_now();
if (!switch_channel_test_flag(channel, CF_AVPF) && switch_true(switch_core_get_variable("sofia_send_info_vid_refresh"))) {
const char *pl = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<media_control><vc_primitive><to_encoder><picture_fast_update /></to_encoder></vc_primitive></media_control>\n";
switch_time_t now = switch_micro_time_now();
if (!tech_pvt->last_vid_info || (now - tech_pvt->last_vid_info) > 500000) {
if (!tech_pvt->last_vid_info || (now - tech_pvt->last_vid_info) > 500000) {
tech_pvt->last_vid_info = now;
if (!zstr(msg->string_arg)) {
pl = msg->string_arg;
}
nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("application/media_control+xml"), SIPTAG_PAYLOAD_STR(pl), TAG_END());
tech_pvt->last_vid_info = now;
if (!zstr(msg->string_arg)) {
pl = msg->string_arg;
}
//}
nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("application/media_control+xml"), SIPTAG_PAYLOAD_STR(pl), TAG_END());
}
}
break;
case SWITCH_MESSAGE_INDICATE_BROADCAST:
@@ -5758,109 +5754,112 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
switch_management_interface_t *management_interface;
switch_application_interface_t *app_interface;
struct in_addr in;
switch_status_t status;
if (switch_event_reserve_subclass(MY_EVENT_NOTIFY_REFER) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_NOTIFY_REFER);
return SWITCH_STATUS_TERM;
}
if (switch_event_reserve_subclass(MY_EVENT_NOTIFY_WATCHED_HEADER) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_NOTIFY_WATCHED_HEADER);
return SWITCH_STATUS_TERM;
}
if (switch_event_reserve_subclass(MY_EVENT_UNREGISTER) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_UNREGISTER);
return SWITCH_STATUS_TERM;
}
if (switch_event_reserve_subclass(MY_EVENT_PROFILE_START) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_PROFILE_START);
return SWITCH_STATUS_TERM;
}
if (switch_event_reserve_subclass(MY_EVENT_REINVITE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_REINVITE);
return SWITCH_STATUS_TERM;
}
if (switch_event_reserve_subclass(MY_EVENT_REPLACED) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_REPLACED);
return SWITCH_STATUS_TERM;
}
if (switch_event_reserve_subclass(MY_EVENT_TRANSFEROR) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_TRANSFEROR);
return SWITCH_STATUS_TERM;
}
if (switch_event_reserve_subclass(MY_EVENT_TRANSFEREE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_TRANSFEREE);
return SWITCH_STATUS_TERM;
}
if (switch_event_reserve_subclass(MY_EVENT_ERROR) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_ERROR);
return SWITCH_STATUS_TERM;
}
if (switch_event_reserve_subclass(MY_EVENT_INTERCEPTED) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_INTERCEPTED);
return SWITCH_STATUS_TERM;
}
if (switch_event_reserve_subclass(MY_EVENT_GATEWAY_STATE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_GATEWAY_STATE);
return SWITCH_STATUS_TERM;
}
if (switch_event_reserve_subclass(MY_EVENT_SIP_USER_STATE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_SIP_USER_STATE);
return SWITCH_STATUS_TERM;
}
if (switch_event_reserve_subclass(MY_EVENT_GATEWAY_DEL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_GATEWAY_DEL);
return SWITCH_STATUS_TERM;
}
if (switch_event_reserve_subclass(MY_EVENT_EXPIRE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_EXPIRE);
return SWITCH_STATUS_TERM;
}
if (switch_event_reserve_subclass(MY_EVENT_REGISTER_ATTEMPT) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_REGISTER_ATTEMPT);
return SWITCH_STATUS_TERM;
}
if (switch_event_reserve_subclass(MY_EVENT_REGISTER_FAILURE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_REGISTER_FAILURE);
return SWITCH_STATUS_TERM;
}
if (switch_event_reserve_subclass(MY_EVENT_PRE_REGISTER) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_PRE_REGISTER);
return SWITCH_STATUS_TERM;
}
if (switch_event_reserve_subclass(MY_EVENT_REGISTER) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_REGISTER);
return SWITCH_STATUS_TERM;
}
if (switch_event_reserve_subclass(MY_EVENT_GATEWAY_ADD) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_GATEWAY_ADD);
return SWITCH_STATUS_TERM;
}
memset(&mod_sofia_globals, 0, sizeof(mod_sofia_globals));
mod_sofia_globals.destroy_private.destroy_nh = 1;
mod_sofia_globals.destroy_private.is_static = 1;
mod_sofia_globals.keep_private.is_static = 1;
mod_sofia_globals.pool = pool;
switch_mutex_init(&mod_sofia_globals.mutex, SWITCH_MUTEX_NESTED, mod_sofia_globals.pool);
switch_core_hash_init(&mod_sofia_globals.profile_hash);
switch_core_hash_init(&mod_sofia_globals.gateway_hash);
switch_mutex_init(&mod_sofia_globals.hash_mutex, SWITCH_MUTEX_NESTED, mod_sofia_globals.pool);
if (switch_event_reserve_subclass(MY_EVENT_NOTIFY_REFER) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_NOTIFY_REFER);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_NOTIFY_WATCHED_HEADER) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_NOTIFY_WATCHED_HEADER);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_UNREGISTER) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_UNREGISTER);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_PROFILE_START) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_PROFILE_START);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_REINVITE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_REINVITE);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_REPLACED) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_REPLACED);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_TRANSFEROR) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_TRANSFEROR);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_TRANSFEREE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_TRANSFEREE);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_ERROR) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_ERROR);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_INTERCEPTED) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_INTERCEPTED);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_GATEWAY_STATE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_GATEWAY_STATE);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_SIP_USER_STATE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_SIP_USER_STATE);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_GATEWAY_DEL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_GATEWAY_DEL);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_EXPIRE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_EXPIRE);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_REGISTER_ATTEMPT) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_REGISTER_ATTEMPT);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_REGISTER_FAILURE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_REGISTER_FAILURE);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_PRE_REGISTER) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_PRE_REGISTER);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_REGISTER) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_REGISTER);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_reserve_subclass(MY_EVENT_GATEWAY_ADD) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_GATEWAY_ADD);
switch_goto_status(SWITCH_STATUS_TERM, err);
}
switch_find_local_ip(mod_sofia_globals.guess_ip, sizeof(mod_sofia_globals.guess_ip), &mod_sofia_globals.guess_mask, AF_INET);
in.s_addr = mod_sofia_globals.guess_mask;
@@ -5868,11 +5867,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
strcpy(mod_sofia_globals.hostname, switch_core_get_switchname());
switch_core_hash_init(&mod_sofia_globals.profile_hash);
switch_core_hash_init(&mod_sofia_globals.gateway_hash);
switch_mutex_init(&mod_sofia_globals.hash_mutex, SWITCH_MUTEX_NESTED, mod_sofia_globals.pool);
switch_mutex_lock(mod_sofia_globals.mutex);
mod_sofia_globals.running = 1;
switch_mutex_unlock(mod_sofia_globals.mutex);
@@ -5896,83 +5890,95 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
/* start one message thread */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Starting initial message thread.\n");
sofia_msg_thread_start(0);
if (sofia_init() != SWITCH_STATUS_SUCCESS) {
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
if (config_sofia(SOFIA_CONFIG_LOAD, NULL) != SWITCH_STATUS_SUCCESS) {
mod_sofia_globals.running = 0;
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
sofia_msg_thread_start(0);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Waiting for profiles to start\n");
switch_yield(1500000);
if (switch_event_bind(modname, SWITCH_EVENT_CUSTOM, MULTICAST_EVENT, event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
return SWITCH_STATUS_TERM;
switch_goto_status(SWITCH_STATUS_TERM, err);
}
if (switch_event_bind(modname, SWITCH_EVENT_CONFERENCE_DATA, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
if (switch_event_bind(modname, SWITCH_EVENT_PRESENCE_IN, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
if (switch_event_bind(modname, SWITCH_EVENT_PRESENCE_OUT, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
if (switch_event_bind(modname, SWITCH_EVENT_PRESENCE_PROBE, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
if (switch_event_bind(modname, SWITCH_EVENT_ROSTER, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
if (switch_event_bind(modname, SWITCH_EVENT_MESSAGE_WAITING, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
if (switch_event_bind(modname, SWITCH_EVENT_TRAP, SWITCH_EVENT_SUBCLASS_ANY, general_queue_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
if (switch_event_bind(modname, SWITCH_EVENT_NOTIFY, SWITCH_EVENT_SUBCLASS_ANY, general_queue_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
if (switch_event_bind(modname, SWITCH_EVENT_PHONE_FEATURE, SWITCH_EVENT_SUBCLASS_ANY, general_queue_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
if (switch_event_bind(modname, SWITCH_EVENT_SEND_MESSAGE, SWITCH_EVENT_SUBCLASS_ANY, general_queue_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
if (switch_event_bind(modname, SWITCH_EVENT_SEND_INFO, SWITCH_EVENT_SUBCLASS_ANY, general_queue_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
switch_goto_status(SWITCH_STATUS_GENERR, err);
return SWITCH_STATUS_GENERR;
}
@@ -6035,10 +6041,14 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
err:
mod_sofia_shutdown_cleanup();
return status;
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sofia_shutdown)
{
void mod_sofia_shutdown_cleanup() {
int sanity = 0;
int i;
switch_status_t st;
@@ -6077,8 +6087,10 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sofia_shutdown)
switch_event_unbind_callback(general_queue_event_handler);
switch_event_unbind_callback(event_handler);
switch_queue_push(mod_sofia_globals.presence_queue, NULL);
switch_queue_interrupt_all(mod_sofia_globals.presence_queue);
if (mod_sofia_globals.presence_queue) {
switch_queue_push(mod_sofia_globals.presence_queue, NULL);
switch_queue_interrupt_all(mod_sofia_globals.presence_queue);
}
while (mod_sofia_globals.threads) {
switch_cond_next();
@@ -6087,13 +6099,11 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sofia_shutdown)
}
}
for (i = 0; mod_sofia_globals.msg_queue_thread[i]; i++) {
switch_queue_push(mod_sofia_globals.msg_queue, NULL);
switch_queue_interrupt_all(mod_sofia_globals.msg_queue);
}
for (i = 0; mod_sofia_globals.msg_queue_thread[i]; i++) {
switch_thread_join(&st, mod_sofia_globals.msg_queue_thread[i]);
}
@@ -6102,14 +6112,17 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sofia_shutdown)
switch_thread_join(&st, mod_sofia_globals.presence_thread);
}
//switch_yield(1000000);
su_deinit();
switch_mutex_lock(mod_sofia_globals.hash_mutex);
switch_core_hash_destroy(&mod_sofia_globals.profile_hash);
switch_core_hash_destroy(&mod_sofia_globals.gateway_hash);
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sofia_shutdown)
{
mod_sofia_shutdown_cleanup();
return SWITCH_STATUS_SUCCESS;
}
+7
View File
@@ -293,6 +293,7 @@ typedef enum {
PFLAG_CHANNEL_XML_FETCH_ON_NIGHTMARE_TRANSFER,
PFLAG_FIRE_TRANFER_EVENTS,
PFLAG_BLIND_AUTH_ENFORCE_RESULT,
PFLAG_PROXY_HOLD,
/* No new flags below this line */
PFLAG_MAX
@@ -763,6 +764,8 @@ struct sofia_profile {
ka_type_t keepalive;
int bind_attempts;
int bind_attempt_interval;
char *proxy_notify_events;
char *proxy_info_content_types;
};
@@ -1027,6 +1030,7 @@ void sofia_presence_set_chat_hash(private_object_t *tech_pvt, sip_t const *sip);
switch_status_t sofia_on_hangup(switch_core_session_t *session);
char *sofia_glue_get_url_from_contact(char *buf, uint8_t to_dup);
char *sofia_glue_get_path_from_contact(char *buf);
char *sofia_glue_get_profile_url(sofia_profile_t *profile, char *remote_ip, const sofia_transport_t transport);
void sofia_presence_set_hash_key(char *hash_key, int32_t len, sip_t const *sip);
void sofia_glue_sql_close(sofia_profile_t *profile, time_t prune);
int sofia_glue_init_sql(sofia_profile_t *profile);
@@ -1064,6 +1068,8 @@ void sofia_reg_release_gateway__(const char *file, const char *func, int line, s
#define sofia_use_soa(_t) sofia_test_flag(_t, TFLAG_ENABLE_SOA)
#define sofia_test_extra_headers(val) (((!strncasecmp(val, "X-", 2) && strncasecmp(val, "X-FS-", 5)) || !strncasecmp(val, "P-", 2) || !strncasecmp(val, "On", 2)) ? 1 : 0)
#define check_decode(_var, _session) do { \
assert(_session); \
if (!zstr(_var)) { \
@@ -1160,6 +1166,7 @@ switch_status_t sofia_glue_send_notify(sofia_profile_t *profile, const char *use
char *sofia_glue_get_extra_headers(switch_channel_t *channel, const char *prefix);
void sofia_glue_set_extra_headers(switch_core_session_t *session, sip_t const *sip, const char *prefix);
char *sofia_glue_get_extra_headers_from_event(switch_event_t *event, const char *prefix);
char *sofia_glue_get_non_extra_unknown_headers(sip_t const *sip);
void sofia_update_callee_id(switch_core_session_t *session, sofia_profile_t *profile, sip_t const *sip, switch_bool_t send);
void sofia_send_callee_id(switch_core_session_t *session, const char *name, const char *number);
int sofia_sla_supported(sip_t const *sip);
+237 -126
View File
@@ -679,6 +679,29 @@ void sofia_handle_sip_i_notify(switch_core_session_t *session, int status,
/* if no session, assume it could be an incoming notify from a gateway subscription */
if (session) {
if (!zstr(profile->proxy_notify_events) && (!strcasecmp(profile->proxy_notify_events, "all") || strstr(profile->proxy_notify_events, sip->sip_event->o_type))) {
switch_core_session_t *other_session;
if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
const char *full_to = NULL;
char *pl = NULL;
char *unknown = NULL;
full_to = switch_str_nil(switch_channel_get_variable(switch_core_session_get_channel(other_session), "sip_full_to"));
if (sip->sip_payload && sip->sip_payload->pl_data) {
pl = switch_core_session_strdup(other_session, (char*)sip->sip_payload->pl_data);
}
unknown = sofia_glue_get_non_extra_unknown_headers(sip);
nua_notify(other_tech_pvt->nh, NUTAG_NEWSUB(1), NUTAG_SUBSTATE(nua_substate_active),
TAG_IF((full_to), SIPTAG_TO_STR(full_to)), SIPTAG_SUBSCRIPTION_STATE_STR("active"),
SIPTAG_EVENT_STR(sip->sip_event->o_type), TAG_IF(!zstr(unknown), SIPTAG_HEADER_STR(unknown)),
TAG_IF(!zstr(pl), SIPTAG_PAYLOAD_STR(pl)), TAG_END());
switch_safe_free(unknown);
switch_core_session_rwunlock(other_session);
}
nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
goto end;
}
/* make sure we have a proper "talk" event */
if (strcasecmp(sip->sip_event->o_type, "talk")) {
goto error;
@@ -1567,20 +1590,25 @@ static void our_sofia_event_callback(nua_event_t event,
if (channel && sip) {
const char *r_sdp = NULL;
if (sofia_test_flag(tech_pvt, TFLAG_PASS_ACK) && sip->sip_payload && sip->sip_payload->pl_data) {
r_sdp = sip->sip_payload->pl_data;
if (sip->sip_payload && sip->sip_payload->pl_data) {
if (sofia_test_flag(tech_pvt, TFLAG_PASS_ACK)) {
r_sdp = sip->sip_payload->pl_data;
if (tech_pvt->mparams.last_sdp_str) {
tech_pvt->mparams.prev_sdp_str = tech_pvt->mparams.last_sdp_str;
}
tech_pvt->mparams.last_sdp_str = NULL;
if (tech_pvt->mparams.last_sdp_str) {
tech_pvt->mparams.prev_sdp_str = tech_pvt->mparams.last_sdp_str;
}
tech_pvt->mparams.last_sdp_str = NULL;
if (!zstr(tech_pvt->mparams.prev_sdp_str) && strcmp(tech_pvt->mparams.prev_sdp_str, sip->sip_payload->pl_data)) {
if (!zstr(tech_pvt->mparams.prev_sdp_str) && strcmp(tech_pvt->mparams.prev_sdp_str, sip->sip_payload->pl_data)) {
switch_channel_set_variable(channel, "sip_reinvite_sdp", sip->sip_payload->pl_data);
tech_pvt->mparams.last_sdp_str = switch_core_session_strdup(session, sip->sip_payload->pl_data);
} else {
tech_pvt->mparams.last_sdp_str = tech_pvt->mparams.prev_sdp_str;
}
} else {
switch_channel_set_variable(channel, "sip_reinvite_sdp", sip->sip_payload->pl_data);
tech_pvt->mparams.last_sdp_str = switch_core_session_strdup(session, sip->sip_payload->pl_data);
} else {
tech_pvt->mparams.last_sdp_str = tech_pvt->mparams.prev_sdp_str;
}
}
@@ -4307,7 +4335,6 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
sofia_set_pflag(profile, PFLAG_ENABLE_CHAT);
profile->auto_restart = 1;
sofia_set_media_flag(profile, SCMF_AUTOFIX_TIMING);
sofia_set_media_flag(profile, SCMF_RENEG_ON_REINVITE);
sofia_set_media_flag(profile, SCMF_RTP_AUTOFLUSH_DURING_BRIDGE);
profile->contact_user = SOFIA_DEFAULT_CONTACT_USER;
sofia_set_pflag(profile, PFLAG_PASS_CALLEE_ID);
@@ -4364,17 +4391,15 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s [%s]\n", var, val);
if (!strcasecmp(var, "debug")) {
if (!strcasecmp(var, "debug") && val) {
profile->debug = atoi(val);
} else if (!strcasecmp(var, "parse-invite-tel-params")) {
profile->parse_invite_tel_params = switch_true(val);
} else if (!strcasecmp(var, "keepalive-method")) {
if (!zstr(val)) {
if (!strcasecmp(val, "info")) {
profile->keepalive = KA_INFO;
} else {
profile->keepalive = KA_MESSAGE;
}
} else if (!strcasecmp(var, "keepalive-method") && !zstr(val)) {
if (!strcasecmp(val, "info")) {
profile->keepalive = KA_INFO;
} else {
profile->keepalive = KA_MESSAGE;
}
} else if (!strcasecmp(var, "bind-attempts") && val) {
int ba = atoi(val) - 1;
@@ -4455,17 +4480,17 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else {
profile->mndlb &= ~SM_NDLB_NEVER_PATCH_REINVITE;
}
} else if (!strcasecmp(var, "registration-thread-frequency")) {
} else if (!strcasecmp(var, "registration-thread-frequency") && !zstr(val)) {
profile->ireg_seconds = atoi(val);
if (profile->ireg_seconds < 0) {
profile->ireg_seconds = IREG_SECONDS;
}
} else if (!strcasecmp(var, "ping-mean-interval")) {
} else if (!strcasecmp(var, "ping-mean-interval") && !zstr(val)) {
profile->iping_seconds = atoi(val);
if (profile->iping_seconds < 0) {
profile->iping_seconds = IPING_SECONDS;
}
} else if (!strcasecmp(var, "ping-thread-frequency")) {
} else if (!strcasecmp(var, "ping-thread-frequency") && !zstr(val)) {
profile->iping_freq = atoi(val);
if (profile->iping_freq < 0) {
profile->iping_freq = IPING_FREQUENCY;
@@ -4540,7 +4565,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else {
sofia_clear_pflag(profile, PFLAG_LIBERAL_DTMF);
}
} else if (!strcasecmp(var, "rtp-digit-delay")) {
} else if (!strcasecmp(var, "rtp-digit-delay") && !zstr(val)) {
int delay = atoi(val);
if (delay < 0) {
delay = 0;
@@ -4548,11 +4573,10 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
profile->rtp_digit_delay = (uint32_t) delay;
} else if (!strcasecmp(var, "watchdog-enabled")) {
profile->watchdog_enabled = switch_true(val);
} else if (!strcasecmp(var, "watchdog-step-timeout")) {
} else if (!strcasecmp(var, "watchdog-step-timeout") && !zstr(val)) {
profile->step_timeout = atoi(val);
} else if (!strcasecmp(var, "watchdog-event-timeout")) {
} else if (!strcasecmp(var, "watchdog-event-timeout") && !zstr(val)) {
profile->event_timeout = atoi(val);
} else if (!strcasecmp(var, "in-dialog-chat")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_IN_DIALOG_CHAT);
@@ -4589,18 +4613,6 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else {
sofia_clear_pflag(profile, PFLAG_IGNORE_183NOSDP);
}
} else if (!strcasecmp(var, "renegotiate-codec-on-hold")) {
if (switch_true(val)) {
sofia_set_media_flag(profile, SCMF_RENEG_ON_HOLD);
} else {
sofia_clear_media_flag(profile, SCMF_RENEG_ON_HOLD);
}
} else if (!strcasecmp(var, "renegotiate-codec-on-reinvite")) {
if (switch_true(val)) {
sofia_set_media_flag(profile, SCMF_RENEG_ON_REINVITE);
} else {
sofia_clear_media_flag(profile, SCMF_RENEG_ON_REINVITE);
}
} else if (!strcasecmp(var, "presence-probe-on-register")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER);
@@ -4608,9 +4620,9 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
sofia_clear_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER);
}
} else if (!strcasecmp(var, "send-presence-on-register")) {
if (switch_true(val) || !strcasecmp(val, "all")) {
if (val && (switch_true(val) || !strcasecmp(val, "all"))) {
sofia_set_pflag(profile, PFLAG_PRESENCE_ON_REGISTER);
} else if (!strcasecmp(val, "first-only")) {
} else if (val && !strcasecmp(val, "first-only")) {
sofia_clear_pflag(profile, PFLAG_PRESENCE_ON_REGISTER);
sofia_set_pflag(profile, PFLAG_PRESENCE_ON_FIRST_REGISTER);
} else {
@@ -4623,22 +4635,21 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else {
sofia_clear_pflag(profile, PFLAG_CID_IN_1XX);
}
} else if (!strcasecmp(var, "disable-hold")) {
if (switch_true(val)) {
sofia_set_media_flag(profile, SCMF_DISABLE_HOLD);
} else {
sofia_clear_media_flag(profile, SCMF_DISABLE_HOLD);
}
} else if (!strcasecmp(var, "auto-jitterbuffer-msec")) {
} else if (!strcasecmp(var, "auto-jitterbuffer-msec") && !zstr(val)) {
int msec = atoi(val);
if (msec > 19) {
profile->jb_msec = switch_core_strdup(profile->pool, val);
}
} else if (!strcasecmp(var, "dtmf-type")) {
if (!strcasecmp(val, "rfc2833")) {
if (val && !strcasecmp(val, "rfc2833")) {
profile->dtmf_type = DTMF_2833;
} else if (!strcasecmp(val, "info")) {
} else if (val && !strcasecmp(val, "info")) {
profile->dtmf_type = DTMF_INFO;
} else {
profile->dtmf_type = DTMF_NONE;
@@ -4711,12 +4722,12 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else {
sofia_clear_flag(profile, TFLAG_ZRTP_PASSTHRU);
}
} else if (!strcasecmp(var, "force-subscription-expires")) {
} else if (!strcasecmp(var, "force-subscription-expires") && !zstr(val)) {
int tmp = atoi(val);
if (tmp > 0) {
profile->force_subscription_expires = tmp;
}
} else if (!strcasecmp(var, "force-publish-expires")) {
} else if (!strcasecmp(var, "force-publish-expires") && !zstr(val)) {
int tmp = atoi(val);
if (tmp > 0) {
profile->force_publish_expires = tmp;
@@ -4724,7 +4735,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else if (!strcasecmp(var, "send-message-query-on-register")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER);
} else if (!strcasecmp(val, "first-only")) {
} else if (val && !strcasecmp(val, "first-only")) {
sofia_clear_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER);
sofia_set_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER);
} else {
@@ -4779,20 +4790,20 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
}
} else if (!strcasecmp(var, "user-agent-filter")) {
profile->user_agent_filter = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "max-registrations-per-extension")) {
} else if (!strcasecmp(var, "max-registrations-per-extension") && !zstr(val)) {
profile->max_registrations_perext = atoi(val);
} else if (!strcasecmp(var, "rfc2833-pt")) {
} else if (!strcasecmp(var, "rfc2833-pt") && !zstr(val)) {
profile->te = (switch_payload_t) atoi(val);
} else if (!strcasecmp(var, "cng-pt") && !sofia_test_media_flag(profile, SCMF_SUPPRESS_CNG)) {
} else if (!strcasecmp(var, "cng-pt") && !sofia_test_media_flag(profile, SCMF_SUPPRESS_CNG) && !zstr(val)) {
profile->cng_pt = (switch_payload_t) atoi(val);
} else if (!strcasecmp(var, "sip-port")) {
} else if (!strcasecmp(var, "sip-port") && !zstr(val)) {
if (!strcasecmp(val, "auto")) {
sofia_set_pflag(profile, PFLAG_AUTO_ASSIGN_PORT);
} else {
profile->sip_port = (switch_port_t) atoi(val);
if (!profile->extsipport) profile->extsipport = profile->sip_port;
}
} else if (!strcasecmp(var, "vad")) {
} else if (!strcasecmp(var, "vad") && !zstr(val)) {
if (!strcasecmp(val, "in")) {
profile->vflags |= VAD_IN;
} else if (!strcasecmp(val, "out")) {
@@ -4829,7 +4840,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid ext-rtp-ip\n");
}
} else if (!strcasecmp(var, "rtp-ip")) {
} else if (!strcasecmp(var, "rtp-ip") && val) {
char *ip = mod_sofia_globals.guess_ip;
char buf[64];
@@ -4864,7 +4875,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Max IPs configured for profile %s.\n", profile->name);
}
}
} else if (!strcasecmp(var, "sip-ip")) {
} else if (!strcasecmp(var, "sip-ip") && val) {
char *ip = mod_sofia_globals.guess_ip;
char buf[64];
@@ -4922,7 +4933,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid ext-sip-ip\n");
}
} else if (!strcasecmp(var, "local-network-acl")) {
if (!strcasecmp(var, "none")) {
if (val && !strcasecmp(val, "none")) {
profile->local_network = NULL;
} else {
profile->local_network = switch_core_strdup(profile->pool, val);
@@ -4941,7 +4952,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
profile->timer_name = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "hold-music")) {
profile->hold_music = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "outbound-proxy")) {
} else if (!strcasecmp(var, "outbound-proxy") && val) {
if (strncasecmp(val, "sip:", 4) && strncasecmp(val, "sips:", 5)) {
profile->outbound_proxy = switch_core_sprintf(profile->pool, "sip:%s", val);
} else {
@@ -4951,22 +4962,22 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
profile->rtcp_audio_interval_msec = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "rtcp-video-interval-msec")) {
profile->rtcp_video_interval_msec = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "session-timeout")) {
} else if (!strcasecmp(var, "session-timeout") && !zstr(val)) {
int v_session_timeout = atoi(val);
if (v_session_timeout >= 0) {
profile->session_timeout = v_session_timeout;
}
} else if (!strcasecmp(var, "max-proceeding")) {
} else if (!strcasecmp(var, "max-proceeding") && !zstr(val)) {
int v_max_proceeding = atoi(val);
if (v_max_proceeding >= 0) {
profile->max_proceeding = v_max_proceeding;
}
} else if (!strcasecmp(var, "rtp-timeout-sec")) {
} else if (!strcasecmp(var, "rtp-timeout-sec") && !zstr(val)) {
int v = atoi(val);
if (v >= 0) {
profile->rtp_timeout_sec = v;
}
} else if (!strcasecmp(var, "rtp-hold-timeout-sec")) {
} else if (!strcasecmp(var, "rtp-hold-timeout-sec") && !zstr(val)) {
int v = atoi(val);
if (v >= 0) {
profile->rtp_hold_timeout_sec = v;
@@ -4983,7 +4994,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else {
profile->mflags |= MFLAG_REGISTER;
}
} else if (!strcasecmp(var, "media-option")) {
} else if (!strcasecmp(var, "media-option") && !zstr(val)) {
if (!strcasecmp(val, "resume-media-on-hold")) {
profile->media_options |= MEDIA_OPT_MEDIA_ON_HOLD;
} else if (!strcasecmp(val, "bypass-media-after-att-xfer")) {
@@ -5001,10 +5012,10 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else if (!strcasecmp(var, "pnp-provision-url")) {
profile->pnp_prov_url = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "manage-presence")) {
if (!strcasecmp(val, "passive")) {
if (val && !strcasecmp(val, "passive")) {
profile->pres_type = PRES_TYPE_PASSIVE;
} else if (!strcasecmp(val, "pnp")) {
} else if (val && !strcasecmp(val, "pnp")) {
profile->pres_type = PRES_TYPE_PNP;
} else if (switch_true(val)) {
profile->pres_type = PRES_TYPE_FULL;
@@ -5012,9 +5023,9 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
profile->pres_type = 0;
}
} else if (!strcasecmp(var, "presence-hold-state")) {
if (!strcasecmp(val, "confirmed")) {
if (val && !strcasecmp(val, "confirmed")) {
profile->pres_held_type = PRES_HELD_CONFIRMED;
} else if (!strcasecmp(val, "terminated")) {
} else if (val && !strcasecmp(val, "terminated")) {
profile->pres_held_type = PRES_HELD_TERMINATED;
} else {
profile->pres_held_type = 0;
@@ -5031,7 +5042,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
profile->pres_type = PRES_TYPE_FULL;
sofia_set_pflag(profile, PFLAG_MULTIREG);
} else if (!strcasecmp(val, "sylantro")) {
} else if (val && !strcasecmp(val, "sylantro")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Sylantro support has been removed.\n"
"It was incomplete anyway, and we fully support the broadsoft SCA shared line spec.");
@@ -5063,9 +5074,9 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else {
sofia_clear_pflag(profile, PFLAG_UNREG_OPTIONS_FAIL);
}
} else if (!strcasecmp(var, "sip-user-ping-max")) {
} else if (!strcasecmp(var, "sip-user-ping-max") && !zstr(val)) {
profile->sip_user_ping_max = atoi(val);
} else if (!strcasecmp(var, "sip-user-ping-min")) {
} else if (!strcasecmp(var, "sip-user-ping-min") && !zstr(val)) {
profile->sip_user_ping_min = atoi(val);
} else if (!strcasecmp(var, "require-secure-rtp")) {
if (switch_true(val)) {
@@ -5079,9 +5090,9 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
if (found) continue;
if (!strcasecmp(var, "multiple-registrations")) {
if (!strcasecmp(val, "call-id")) {
if (val && !strcasecmp(val, "call-id")) {
sofia_set_pflag(profile, PFLAG_MULTIREG);
} else if (!strcasecmp(val, "contact") || switch_true(val)) {
} else if (val && (!strcasecmp(val, "contact") || switch_true(val))) {
sofia_set_pflag(profile, PFLAG_MULTIREG);
sofia_set_pflag(profile, PFLAG_MULTIREG_CONTACT);
} else if (!switch_true(val)) {
@@ -5146,7 +5157,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else if (!strcasecmp(var, "contact-user")) {
profile->contact_user = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "nat-options-ping")) {
if (!strcasecmp(val, "udp-only")) {
if (val && !strcasecmp(val, "udp-only")) {
sofia_set_pflag(profile, PFLAG_UDP_NAT_OPTIONS_PING);
} else if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_NAT_OPTIONS_PING);
@@ -5161,9 +5172,9 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
sofia_clear_pflag(profile, PFLAG_ALL_REG_OPTIONS_PING);
}
} else if (!strcasecmp(var, "inbound-codec-negotiation")) {
if (!strcasecmp(val, "greedy")) {
if (val && !strcasecmp(val, "greedy")) {
sofia_set_media_flag(profile, SCMF_CODEC_GREEDY);
} else if (!strcasecmp(val, "scrooge")) {
} else if (val && !strcasecmp(val, "scrooge")) {
sofia_set_media_flag(profile, SCMF_CODEC_GREEDY);
sofia_set_media_flag(profile, SCMF_CODEC_SCROOGE);
} else {
@@ -5206,9 +5217,9 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else {
sofia_clear_pflag(profile, PFLAG_EXTENDED_INFO_PARSING);
}
} else if (!strcasecmp(var, "nonce-ttl")) {
} else if (!strcasecmp(var, "nonce-ttl") && !zstr(val)) {
profile->nonce_ttl = atoi(val);
} else if (!strcasecmp(var, "max-auth-validity")) {
} else if (!strcasecmp(var, "max-auth-validity") && !zstr(val)) {
profile->max_auth_validity = atoi(val);
} else if (!strcasecmp(var, "accept-blind-reg")) {
if (switch_true(val)) {
@@ -5264,7 +5275,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else {
sofia_clear_pflag(profile, PFLAG_ENABLE_RFC5626);
}
} else if (!strcasecmp(var, "minimum-session-expires")) {
} else if (!strcasecmp(var, "minimum-session-expires") && !zstr(val)) {
profile->minimum_session_expires = atoi(val);
/* per RFC 4028: minimum_session_expires must be > 90 */
if (profile->minimum_session_expires < 90) {
@@ -5301,7 +5312,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
sofia_clear_pflag(profile, PFLAG_PARSE_ALL_INVITE_HEADERS);
}
} else if (!strcasecmp(var, "bitpacking")) {
if (!strcasecmp(val, "aal2")) {
if (val && !strcasecmp(val, "aal2")) {
profile->codec_flags = SWITCH_CODEC_FLAG_AAL2;
} else {
profile->codec_flags = 0;
@@ -5310,7 +5321,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
profile->sdp_username = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "context")) {
profile->context = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "apply-nat-acl")) {
} else if (!strcasecmp(var, "apply-nat-acl") && !zstr(val)) {
if (!strcasecmp(val,"none")) {
profile->nat_acl_count = 0;
} else if (profile->nat_acl_count < SOFIA_MAX_ACL) {
@@ -5322,7 +5333,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Max acl records of %d reached\n", SOFIA_MAX_ACL);
}
} else if (!strcasecmp(var, "apply-inbound-acl")) {
} else if (!strcasecmp(var, "apply-inbound-acl") && !zstr(val)) {
if (!strcasecmp(val,"none")) {
profile->acl_count = 0;
} else if (profile->acl_count < SOFIA_MAX_ACL) {
@@ -5348,7 +5359,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Max acl records of %d reached\n", SOFIA_MAX_ACL);
}
} else if (!strcasecmp(var, "apply-proxy-acl")) {
} else if (!strcasecmp(var, "apply-proxy-acl") && !zstr(val)) {
if (!strcasecmp(val,"none")) {
profile->proxy_acl_count = 0;
} else if (profile->proxy_acl_count < SOFIA_MAX_ACL) {
@@ -5356,7 +5367,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Max acl records of %d reached\n", SOFIA_MAX_ACL);
}
} else if (!strcasecmp(var, "apply-register-acl")) {
} else if (!strcasecmp(var, "apply-register-acl") && !zstr(val)) {
if (!strcasecmp(val,"none")) {
profile->reg_acl_count = 0;
} else if (profile->reg_acl_count < SOFIA_MAX_ACL) {
@@ -5365,7 +5376,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Max acl records of %d reached\n", SOFIA_MAX_ACL);
}
} else if (!strcasecmp(var, "apply-candidate-acl")) {
} else if (!strcasecmp(var, "apply-candidate-acl") && !zstr(val)) {
if (!strcasecmp(val,"none")) {
profile->cand_acl_count = 0;
} else if (profile->cand_acl_count < SWITCH_MAX_CAND_ACL) {
@@ -5387,7 +5398,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
}
} else if (!strcasecmp(var, "dialplan")) {
profile->dialplan = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "max-calls")) {
} else if (!strcasecmp(var, "max-calls") && !zstr(val)) {
profile->max_calls = atoi(val);
} else if (!strcasecmp(var, "codec-prefs")) {
profile->inbound_codec_string = switch_core_strdup(profile->pool, val);
@@ -5398,7 +5409,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
profile->outbound_codec_string = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "challenge-realm")) {
profile->challenge_realm = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "dtmf-duration")) {
} else if (!strcasecmp(var, "dtmf-duration") && !zstr(val)) {
uint32_t dur = atoi(val);
if (dur >= switch_core_min_dtmf_duration(0) && dur <= switch_core_max_dtmf_duration(0)) {
profile->dtmf_duration = dur;
@@ -5451,7 +5462,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
sofia_clear_pflag(profile, PFLAG_TLS);
}
} else if (!strcasecmp(var, "tls-bind-params")) {
if (switch_stristr("transport=tls", val)) {
if (val && switch_stristr("transport=tls", val)) {
profile->tls_bind_params = switch_core_strdup(profile->pool, val);
} else {
profile->tls_bind_params = switch_core_sprintf(profile->pool, "%s;transport=tls", val);
@@ -5460,11 +5471,11 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
profile->tls_only = switch_true(val);
} else if (!strcasecmp(var, "tls-verify-date")) {
profile->tls_verify_date = switch_true(val);
} else if (!strcasecmp(var, "tls-verify-depth")) {
} else if (!strcasecmp(var, "tls-verify-depth") && !zstr(val)) {
profile->tls_verify_depth = atoi(val);
} else if (!strcasecmp(var, "tls-verify-policy")) {
profile->tls_verify_policy = sofia_glue_str2tls_verify_policy(val);
} else if (!strcasecmp(var, "tls-sip-port")) {
} else if (!strcasecmp(var, "tls-sip-port") && !zstr(val)) {
if (!strcasecmp(val, "auto")) {
sofia_set_pflag(profile, PFLAG_AUTO_ASSIGN_TLS_PORT);
} else {
@@ -5501,79 +5512,79 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
profile->tls_version |= SOFIA_TLS_VERSION_TLSv1_2;
ps=pe+1;
}
} else if (!strcasecmp(var, "tls-timeout")) {
} else if (!strcasecmp(var, "tls-timeout") && !zstr(val)) {
int v = atoi(val);
profile->tls_timeout = v > 0 ? (unsigned int)v : 300;
} else if (!strcasecmp(var, "timer-T1")) {
} else if (!strcasecmp(var, "timer-T1") && !zstr(val)) {
int v = atoi(val);
if (v > 0) {
profile->timer_t1 = v;
} else {
profile->timer_t1 = 500;
}
} else if (!strcasecmp(var, "timer-T1X64")) {
} else if (!strcasecmp(var, "timer-T1X64") && !zstr(val)) {
int v = atoi(val);
if (v > 0) {
profile->timer_t1x64 = v;
} else {
profile->timer_t1x64 = 32000;
}
} else if (!strcasecmp(var, "timer-T2")) {
} else if (!strcasecmp(var, "timer-T2") && !zstr(val)) {
int v = atoi(val);
if (v > 0) {
profile->timer_t2 = v;
} else {
profile->timer_t2 = 4000;
}
} else if (!strcasecmp(var, "timer-T4")) {
} else if (!strcasecmp(var, "timer-T4") && !zstr(val)) {
int v = atoi(val);
if (v > 0) {
profile->timer_t4 = v;
} else {
profile->timer_t4 = 4000;
}
} else if (!strcasecmp(var, "sip-options-respond-503-on-busy")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY);
} else {
sofia_clear_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY);
}
} else if (!strcasecmp(var, "sip-expires-late-margin")) {
} else if (!strcasecmp(var, "sip-options-respond-503-on-busy")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY);
} else {
sofia_clear_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY);
}
} else if (!strcasecmp(var, "sip-expires-late-margin") && !zstr(val)) {
int32_t sip_expires_late_margin = atoi(val);
if (sip_expires_late_margin >= 0) {
profile->sip_expires_late_margin = sip_expires_late_margin;
} else {
profile->sip_expires_late_margin = 60;
}
} else if (!strcasecmp(var, "sip-force-expires-min")) {
} else if (!strcasecmp(var, "sip-force-expires-min") && !zstr(val)) {
int32_t sip_force_expires_min = atoi(val);
if (sip_force_expires_min >= 0) {
profile->sip_force_expires_min = sip_force_expires_min;
} else {
profile->sip_force_expires_min = 0;
}
} else if (!strcasecmp(var, "sip-force-expires-max")) {
} else if (!strcasecmp(var, "sip-force-expires-max") && !zstr(val)) {
int32_t sip_force_expires_max = atoi(val);
if (sip_force_expires_max >= 0) {
profile->sip_force_expires_max = sip_force_expires_max;
} else {
profile->sip_force_expires_max = 0;
}
} else if (!strcasecmp(var, "sip-force-expires")) {
} else if (!strcasecmp(var, "sip-force-expires") && !zstr(val)) {
int32_t sip_force_expires = atoi(val);
if (sip_force_expires >= 0) {
profile->sip_force_expires = sip_force_expires;
} else {
profile->sip_force_expires = 0;
}
} else if (!strcasecmp(var, "sip-expires-max-deviation")) {
} else if (!strcasecmp(var, "sip-expires-max-deviation") && !zstr(val)) {
int32_t sip_expires_max_deviation = atoi(val);
if (sip_expires_max_deviation >= 0) {
profile->sip_expires_max_deviation = sip_expires_max_deviation;
} else {
profile->sip_expires_max_deviation = 0;
}
} else if (!strcasecmp(var, "sip-subscription-max-deviation")) {
} else if (!strcasecmp(var, "sip-subscription-max-deviation") && !zstr(val)) {
int32_t sip_subscription_max_deviation = atoi(val);
if (sip_subscription_max_deviation >= 0) {
profile->sip_subscription_max_deviation = sip_subscription_max_deviation;
@@ -5588,7 +5599,9 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
sofia_clear_pflag(profile, PFLAG_NO_CONNECTION_REUSE);
}
} else if (!strcasecmp(var, "p-asserted-id-parse")) {
if (!strncasecmp(val, "default", 7)) {
if (!val) {
profile->paid_type = PAID_DEFAULT;
} else if (!strncasecmp(val, "default", 7)) {
profile->paid_type = PAID_DEFAULT;
} else if (!strncasecmp(val, "user-only", 9)) {
profile->paid_type = PAID_USER;
@@ -5611,12 +5624,22 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else {
sofia_clear_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS);
}
} else if (!strcasecmp(var, "enforce-blind-auth-result")) {
if(switch_true(val)) {
sofia_set_pflag(profile, PFLAG_BLIND_AUTH_ENFORCE_RESULT);
} else {
sofia_clear_pflag(profile, PFLAG_BLIND_AUTH_ENFORCE_RESULT);
}
} else if (!strcasecmp(var, "enforce-blind-auth-result")) {
if(switch_true(val)) {
sofia_set_pflag(profile, PFLAG_BLIND_AUTH_ENFORCE_RESULT);
} else {
sofia_clear_pflag(profile, PFLAG_BLIND_AUTH_ENFORCE_RESULT);
}
} else if (!strcasecmp(var, "proxy-hold")) {
if(switch_true(val)) {
sofia_set_pflag(profile, PFLAG_PROXY_HOLD);
} else {
sofia_clear_pflag(profile, PFLAG_PROXY_HOLD);
}
} else if (!strcasecmp(var, "proxy-notify-events")) {
profile->proxy_notify_events = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "proxy-info-content-types")) {
profile->proxy_info_content_types = switch_core_strdup(profile->pool, val);
}
}
@@ -6495,6 +6518,12 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
switch_core_media_proxy_remote_addr(session, NULL);
}
if (status == 415) {
int new_status = 488;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Overriding %d %s with %d\n", status, phrase, new_status);
status = new_status;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing %d %s to other leg\n%s\n", status, phrase, switch_str_nil(r_sdp));
if (switch_core_session_compare(session, other_session)) {
@@ -6854,7 +6883,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
if (tech_pvt->mparams.last_sdp_response) {
r_sdp = tech_pvt->mparams.last_sdp_response;
}
} else if (ss_state == nua_callstate_received) {
} else if (ss_state == nua_callstate_received || ss_state == nua_callstate_ready) {
if (tech_pvt->mparams.last_sdp_str) {
r_sdp = tech_pvt->mparams.last_sdp_str;
}
@@ -7398,9 +7427,11 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
} else {
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED_NOSDP");
switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0);
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
sofia_set_flag_locked(tech_pvt, TFLAG_3PCC);
switch_core_media_prepare_codecs(session, 1);
switch_channel_set_state(channel, CS_HIBERNATE);
switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 0);
sofia_set_flag_locked(tech_pvt, TFLAG_3PCC);
if (sofia_use_soa(tech_pvt)) {
nua_respond(tech_pvt->nh, SIP_200_OK,
SIPTAG_CONTACT_STR(tech_pvt->profile->url),
@@ -7457,15 +7488,13 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
nua_respond(tech_pvt->nh, SIP_200_OK, TAG_END());
goto done;
/* } else if (0 && r_sdp && !sofia_use_soa(tech_pvt)) {
nua_respond(tech_pvt->nh, SIP_200_OK,
NUTAG_MEDIA_ENABLE(0),
SIPTAG_CONTACT_STR(tech_pvt->profile->url),
SIPTAG_CONTENT_TYPE_STR("application/sdp"), SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str), TAG_END());
*/
goto done;
} else {
ss_state = nua_callstate_completed;
goto state_process;
@@ -7659,6 +7688,64 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
}
goto done;
} else {
if (sofia_test_pflag(profile, PFLAG_PROXY_HOLD)) {
switch_channel_set_flag(tech_pvt->channel, CF_REINVITE);
if (tech_pvt->mparams.num_codecs){
match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_REQUEST);
}
if (!match) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Reinvite Codec Error!\n");
nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE, TAG_END());
goto done;
}
if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
switch_core_session_message_t *msg;
msg = switch_core_session_alloc(other_session, sizeof(*msg));
if (switch_stristr("sendonly", r_sdp) || switch_stristr("0.0.0.0", r_sdp)) {
const char *hold_msg = "hold";
msg->message_id = SWITCH_MESSAGE_INDICATE_HOLD;
if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) {
const char *info = switch_channel_get_variable(channel, "presence_call_info");
if (info) {
if (switch_stristr("private", info)) {
hold_msg = "hold-private";
}
}
}
sofia_set_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
switch_channel_set_flag(channel, CF_LEG_HOLDING);
switch_channel_presence(tech_pvt->channel, "unknown", hold_msg, NULL);
} else {
msg->message_id = SWITCH_MESSAGE_INDICATE_UNHOLD;
sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
switch_channel_clear_flag(channel, CF_LEG_HOLDING);
switch_channel_presence(tech_pvt->channel, "unknown", "unhold", NULL);
}
msg->from = __FILE__;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Indicating Hold to other leg.\n%s\n", r_sdp);
switch_core_session_queue_message(other_session, msg);
switch_core_session_rwunlock(other_session);
}
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
if (sofia_use_soa(tech_pvt)){
nua_respond(tech_pvt->nh, SIP_200_OK,
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
SOATAG_REUSE_REJECTED(1),
SOATAG_AUDIO_AUX("cn telephone-event"),
TAG_IF(sofia_test_pflag(profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)), TAG_END());
} else {
nua_respond(tech_pvt->nh, SIP_200_OK,
NUTAG_MEDIA_ENABLE(0),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SIPTAG_CONTENT_TYPE_STR("application/sdp"), SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str), TAG_END());
}
goto done;
}
if (switch_channel_test_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_NEGOTIATED)) {
nua_respond(tech_pvt->nh, SIP_200_OK, TAG_END());
goto done;
@@ -8816,6 +8903,7 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t
switch_core_session_t *b_session;
switch_channel_set_variable_printf(channel, "transfer_to", "blind:%s", br ? br : exten);
switch_channel_set_variable_printf(channel, "transfer_destination", "blind:%s", exten);
if (!zstr(br) && (b_session = switch_core_session_locate(br))) {
const char *var;
@@ -9052,8 +9140,37 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t
assert(switch_core_session_get_private(session));
sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_INFO_HEADER_PREFIX);
if (!zstr(profile->proxy_info_content_types) && sip && sip->sip_content_type && sip->sip_content_type->c_type && sip->sip_content_type->c_subtype &&
(!strcasecmp(profile->proxy_info_content_types,"all") || strstr(profile->proxy_info_content_types,sip->sip_content_type->c_type))) {
switch_core_session_t *other_session;
if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
char *pl = NULL;
char *ct = NULL;
char *extra_headers = NULL;
char *unknown = NULL;
private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
ct = switch_core_session_strdup(other_session, (char*)sip->sip_content_type->c_type);
if (sip->sip_payload && sip->sip_payload->pl_data) {
pl = switch_core_session_strdup(other_session,(char*)sip->sip_payload->pl_data);
}
unknown = sofia_glue_get_non_extra_unknown_headers(sip);
extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_INFO_HEADER_PREFIX);
nua_info(other_tech_pvt->nh,
SIPTAG_CONTENT_TYPE_STR(ct),
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
TAG_IF(!zstr(unknown), SIPTAG_HEADER_STR(unknown)),
TAG_IF(!zstr(other_tech_pvt->user_via), SIPTAG_VIA_STR(other_tech_pvt->user_via)),
TAG_IF(!zstr(pl), SIPTAG_PAYLOAD_STR(pl)),
TAG_END());
switch_safe_free(extra_headers);
switch_safe_free(unknown);
switch_core_session_rwunlock(other_session);
}
}
if (sip && sip->sip_content_type && sip->sip_content_type->c_type && !strcasecmp(sip->sip_content_type->c_type, "freeswitch/data")) {
char *data = NULL;
@@ -9984,11 +10101,9 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia
user, ipv6 ? "[" : "", host, ipv6 ? "]" : "", port, sofia_glue_transport2str(transport));
if (sofia_glue_check_nat(profile, tech_pvt->mparams.remote_ip)) {
url = (sofia_glue_transport_has_tls(transport)) ? profile->tls_public_url : profile->public_url;
check_nat = 1;
} else {
url = (sofia_glue_transport_has_tls(transport)) ? profile->tls_url : profile->url;
}
url = sofia_glue_get_profile_url(profile, tech_pvt->mparams.remote_ip, transport);
if (!url) {
if (check_nat) {
@@ -10023,11 +10138,7 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia
} else {
const char *url = NULL;
if (sofia_glue_check_nat(profile, tech_pvt->mparams.remote_ip)) {
url = (sofia_glue_transport_has_tls(transport)) ? profile->tls_public_url : profile->public_url;
} else {
url = (sofia_glue_transport_has_tls(transport)) ? profile->tls_url : profile->url;
}
url = sofia_glue_get_profile_url(profile, tech_pvt->mparams.remote_ip, transport);
if (url) {
const char *brackets = NULL;
+56 -10
View File
@@ -644,7 +644,7 @@ void sofia_glue_set_extra_headers(switch_core_session_t *session, sip_t const *s
}
for (un = sip->sip_unknown; un; un = un->un_next) {
if ((!strncasecmp(un->un_name, "X-", 2) && strncasecmp(un->un_name, "X-FS-", 5)) || !strncasecmp(un->un_name, "P-", 2) || !strncasecmp(un->un_name, "On", 2)) {
if (sofia_test_extra_headers(un->un_name)) {
if (!zstr(un->un_value)) {
switch_snprintf(name, sizeof(name), "%s%s", prefix, un->un_name);
switch_channel_set_variable(channel, name, un->un_value);
@@ -685,6 +685,33 @@ char *sofia_glue_get_extra_headers_from_event(switch_event_t *event, const char
return extra_headers;
}
char *sofia_glue_get_non_extra_unknown_headers(sip_t const *sip)
{
char *unknown = NULL;
switch_stream_handle_t stream = { 0 };
sip_unknown_t *un;
if (!sip) {
return NULL;
}
SWITCH_STANDARD_STREAM(stream);
for (un = sip->sip_unknown; un; un = un->un_next) {
if (!sofia_test_extra_headers(un->un_name)) {
if (!zstr(un->un_value)) {
stream.write_function(&stream, "%s: %s\r\n",un->un_name,un->un_value);
}
}
}
if (!zstr((char *) stream.data)) {
unknown = stream.data;
} else {
switch_safe_free(stream.data);
}
return unknown;
}
switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
{
char *alert_info = NULL;
@@ -931,15 +958,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
ipv6 ? "[" : "", ip_addr, ipv6 ? "]" : "", tech_pvt->profile->extsipport);
}
} else {
if (sofia_glue_transport_has_tls(tech_pvt->transport)) {
tech_pvt->invite_contact = tech_pvt->profile->tls_url;
} else {
if (!zstr(tech_pvt->mparams.remote_ip) && sofia_glue_check_nat(tech_pvt->profile, tech_pvt->mparams.remote_ip)) {
tech_pvt->invite_contact = tech_pvt->profile->public_url;
} else {
tech_pvt->invite_contact = tech_pvt->profile->url;
}
}
tech_pvt->invite_contact = sofia_glue_get_profile_url(tech_pvt->profile, tech_pvt->mparams.remote_ip, tech_pvt->transport);
}
}
@@ -3105,6 +3124,33 @@ void sofia_glue_clear_soa(switch_core_session_t *session, switch_bool_t partner)
}
char *sofia_glue_get_profile_url(sofia_profile_t *profile, char *remote_ip, const sofia_transport_t transport)
{
char *url = NULL;
int check_nat = 0;
if (!zstr(remote_ip) && sofia_glue_check_nat(profile, remote_ip)) {
check_nat = 1;
}
if (sofia_glue_transport_has_tls(transport)) {
if (check_nat && profile->tls_public_url) {
url = profile->tls_public_url;
} else {
url = profile->tls_url;
}
} else {
if (check_nat && profile->public_url) {
url = profile->public_url;
} else {
url = profile->url;
}
}
if (!url) url = profile->url;
return url;
}
/* For Emacs:
* Local Variables:
@@ -384,6 +384,7 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event)
sofia_glue_free_destination(dst);
switch_safe_free(dup_dest);
switch_safe_free(user_via);
switch_safe_free(remote_host);
}
+4 -4
View File
@@ -161,7 +161,7 @@ static void close_socket(ws_socket_t *sock)
}
}
void verto_broadcast(const char *event_channel, cJSON *json, const char *key, switch_event_channel_id_t id);
static int ssl_init = 0;
static int verto_init_ssl(verto_profile_t *profile)
@@ -2389,8 +2389,6 @@ static void verto_set_media_options(verto_pvt_t *tech_pvt, verto_profile_t *prof
tech_pvt->mparams->jb_msec = "-1";
switch_media_handle_set_media_flag(tech_pvt->smh, SCMF_SUPPRESS_CNG);
switch_media_handle_set_media_flag(tech_pvt->smh, SCMF_RENEG_ON_REINVITE);
//tech_pvt->mparams->auto_rtp_bugs = profile->auto_rtp_bugs;
tech_pvt->mparams->timer_name = profile->timer_name;
//tech_pvt->mparams->vflags = profile->vflags;
@@ -3819,8 +3817,10 @@ static switch_bool_t verto__broadcast_func(const char *method, cJSON *params, js
}
jevent = cJSON_Duplicate(params, 1);
write_event(event_channel, NULL, jevent);
switch_event_channel_broadcast(event_channel, &jevent, modname, globals.event_channel_id);
if (jsock->profile->mcast_pub.sock != ws_sock_invalid) {
if ((json_text = cJSON_PrintUnformatted(params))) {
@@ -4677,7 +4677,7 @@ static switch_status_t parse_config(const char *cf)
vhost->alias = switch_core_strdup(vhost->pool, val);
} else if (!strcasecmp(var, "root")) {
vhost->root = switch_core_strdup(vhost->pool, val);
} else if (!strcasecmp(var, "script_root")) {
} else if (!strcasecmp(var, "script-root")) {
vhost->script_root = switch_core_strdup(vhost->pool, val);
} else if (!strcasecmp(var, "index")) {
vhost->index = switch_core_strdup(vhost->pool, val);
@@ -94,12 +94,13 @@ switch_status_t mod_amqp_logging_recv(const switch_log_node_t *node, switch_log_
if (switch_queue_trypush(logging->send_queue, msg) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "AMQP logging message queue full. Messages will be dropped!\n");
return SWITCH_STATUS_SUCCESS;
switch_safe_free(hi);
goto done;
}
}
}
done:
switch_safe_free(json);
return SWITCH_STATUS_SUCCESS;
}
@@ -201,6 +201,7 @@ switch_status_t mod_smpp_gateway_connection_read(mod_smpp_gateway_t *gateway, sw
switch_event_t *evt = NULL;
generic_nack_t *gennack = NULL;
char data[2048] = {0}; /* local buffer for unpacked PDU */
int err = 0;
/* Read from socket */
/* TODO: Add/Expand support for partial reads */
@@ -227,8 +228,7 @@ switch_status_t mod_smpp_gateway_connection_read(mod_smpp_gateway_t *gateway, sw
}
if ( smpp34_unpack2((void *)data, local_buffer, read_len + 4) ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "smpp: error decoding the receive buffer:%d:%s\n", smpp34_errno, smpp34_strerror);
switch_goto_status(SWITCH_STATUS_GENERR, done);
err++;
}
if ( mod_smpp_globals.debug || gateway->debug ) {
@@ -237,6 +237,12 @@ switch_status_t mod_smpp_gateway_connection_read(mod_smpp_gateway_t *gateway, sw
gennack = (generic_nack_t *) data;
*command_id = gennack->command_id;
if (err && *command_id != SUBMIT_SM_RESP) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "smpp: error decoding the receive buffer:%d:%s\n", smpp34_errno, smpp34_strerror);
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
switch(*command_id) {
case BIND_TRANSCEIVER_RESP:
if ( gennack->command_status != ESME_ROK ) {
@@ -256,6 +262,21 @@ switch_status_t mod_smpp_gateway_connection_read(mod_smpp_gateway_t *gateway, sw
case ENQUIRE_LINK:
case ENQUIRE_LINK_RESP:
case SUBMIT_SM_RESP:
switch (gennack->command_status) {
case ESME_ROK:
//AOK
break;
case ESME_RINVSRCADR:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Source Addr ID: %u\n", *command_id);
break;
case ESME_RINVDSTADR:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Dest Addr ID: %u\n", *command_id);
break;
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Undocumented Error 0X%.8x ID: %u\n", gennack->command_status, *command_id);
break;
}
break;
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unrecognized Command ID: %u\n", *command_id);
+1 -1
View File
@@ -4,5 +4,5 @@ MODNAME=mod_snmp
mod_LTLIBRARIES = mod_snmp.la
mod_snmp_la_SOURCES = mod_snmp.c subagent.c
mod_snmp_la_CFLAGS = $(AM_CFLAGS)
mod_snmp_la_LIBADD = $(switch_builddir)/libfreeswitch.la -lnetsnmpmibs -lnetsnmpagent -lnetsnmp
mod_snmp_la_LIBADD = $(switch_builddir)/libfreeswitch.la $(SNMP_LIBS)
mod_snmp_la_LDFLAGS = -avoid-version -module -no-undefined -shared
@@ -125,6 +125,7 @@ struct local_stream_source {
switch_img_position_t logo_pos;
uint8_t logo_opacity;
uint8_t text_opacity;
switch_mm_t mm;
};
typedef struct local_stream_source local_stream_source_t;
@@ -479,6 +480,10 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
retry:
if (switch_core_file_has_video(use_fh, SWITCH_TRUE)) {
source->mm = use_fh->mm;
}
source->has_video = switch_core_file_has_video(use_fh, SWITCH_TRUE) || source->cover_art || source->banner_txt;
is_open = switch_test_flag(use_fh, SWITCH_FILE_OPEN);
@@ -934,8 +939,9 @@ static switch_status_t local_stream_file_read_video(switch_file_handle_t *handle
switch_status_t status;
switch_time_t now;
unsigned int fps = (unsigned int)ceil(handle->mm.fps);
unsigned int min_qsize = fps;
unsigned int min_qsize = fps / 2;
unsigned int buf_qsize = 5;
if (!(context->ready && context->source->ready)) {
return SWITCH_STATUS_FALSE;
}
@@ -973,7 +979,12 @@ static switch_status_t local_stream_file_read_video(switch_file_handle_t *handle
return SWITCH_STATUS_BREAK;
}
while(context->ready && context->source->ready && (flags & SVR_FLUSH) && switch_queue_size(context->video_q) > min_qsize / 2) {
if (handle->mm.fps >= context->source->mm.source_fps) {
min_qsize = 1;
buf_qsize = 1;
}
while(context->ready && context->source->ready && (flags & SVR_FLUSH) && switch_queue_size(context->video_q) > min_qsize) {
if (switch_queue_trypop(context->video_q, &pop) == SWITCH_STATUS_SUCCESS) {
switch_image_t *img = (switch_image_t *) pop;
switch_img_free(&img);
@@ -984,7 +995,7 @@ static switch_status_t local_stream_file_read_video(switch_file_handle_t *handle
return SWITCH_STATUS_FALSE;
}
while (!(flags & SVR_BLOCK) && switch_queue_size(context->video_q) < 5) {
while (!(flags & SVR_BLOCK) && switch_queue_size(context->video_q) < buf_qsize) {
return SWITCH_STATUS_BREAK;
}
+1 -1
View File
@@ -1659,7 +1659,7 @@ int vlc_write_video_imem_get_callback(void *data, const char *cookie, int64_t *
}
*output = context->video_frame_buffer;
switch_img_to_raw(img, *output, *size, SWITCH_IMG_FMT_YUY2);
switch_img_to_raw(img, *output, 0, SWITCH_IMG_FMT_YUY2);
switch_img_free(&img);
return 0;
}
@@ -72,6 +72,7 @@ public:
JS_COREDB_FUNCTION_DEF(Prepare);
JS_COREDB_FUNCTION_DEF(BindText);
JS_COREDB_FUNCTION_DEF(BindInt);
JS_COREDB_FUNCTION_DEF(Finalize);
JS_COREDB_GET_PROPERTY_DEF(GetProperty);
};
@@ -232,6 +232,14 @@ JS_COREDB_FUNCTION_IMPL(Step)
StepEx(info, SWITCH_CORE_DB_DONE);
}
JS_COREDB_FUNCTION_IMPL(Finalize)
{
if (_stmt) {
switch_core_db_finalize(_stmt);
_stmt = NULL;
}
}
JS_COREDB_FUNCTION_IMPL(Fetch)
{
HandleScope handle_scope(info.GetIsolate());
@@ -415,6 +423,7 @@ static const js_function_t db_methods[] = {
{"prepare", FSCoreDB::Prepare},
{"bindText", FSCoreDB::BindText},
{"bindInt", FSCoreDB::BindInt},
{"finalize", FSCoreDB::Finalize},
{0}
};
+2 -2
View File
@@ -504,8 +504,8 @@ int main(int argc, char *argv[])
char *arg_argv[128] = { 0 };
int alt_dirs = 0, alt_base = 0, log_set = 0, run_set = 0, do_kill = 0;
int priority = 0;
#ifdef __sun
switch_core_flag_t flags = SCF_USE_SQL;
#if (defined(__SVR4) && defined(__sun))
switch_core_flag_t flags = SCF_USE_SQL | SCF_CALIBRATE_CLOCK | SCF_USE_CLOCK_RT;
#else
switch_core_flag_t flags = SCF_USE_SQL | SCF_USE_AUTO_NAT | SCF_USE_NAT_MAPPING | SCF_CALIBRATE_CLOCK | SCF_USE_CLOCK_RT;
#endif
+4
View File
@@ -1373,6 +1373,10 @@ SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_
switch_bool_t ok = SWITCH_FALSE;
char *ipv4 = NULL;
if (!list_name) {
return SWITCH_FALSE;
}
if ((ipv4 = switch_network_ipv4_mapped_ipv6_addr(ip_str))) {
ip_str = ipv4;
ipv6 = NULL;
+281 -295
View File
@@ -1827,6 +1827,8 @@ SWITCH_DECLARE(void) switch_core_media_prepare_codecs(switch_core_session_t *ses
return;
}
ocodec = switch_channel_get_variable(session->channel, SWITCH_ORIGINATOR_CODEC_VARIABLE);
smh->payload_space = 0;
switch_assert(smh->session != NULL);
@@ -1837,11 +1839,10 @@ SWITCH_DECLARE(void) switch_core_media_prepare_codecs(switch_core_session_t *ses
}
val = switch_channel_get_variable_dup(session->channel, "media_mix_inbound_outbound_codecs", SWITCH_FALSE, -1);
if (!val || !switch_true(val)) {
if ((ocodec = switch_channel_get_variable(session->channel, SWITCH_ORIGINATOR_CODEC_VARIABLE))) {
codec_string = ocodec;
goto ready;
}
if ((!val || !switch_true(val) || smh->media_flags[SCMF_DISABLE_TRANSCODING]) && ocodec) {
codec_string = ocodec;
goto ready;
}
if (!(codec_string = switch_channel_get_variable(session->channel, "codec_string"))) {
@@ -1854,13 +1855,7 @@ SWITCH_DECLARE(void) switch_core_media_prepare_codecs(switch_core_session_t *ses
}
if (ocodec) {
if (!codec_string || (smh->media_flags[SCMF_DISABLE_TRANSCODING])) {
codec_string = ocodec;
} else {
if (!(codec_string = switch_core_session_sprintf(smh->session, "%s,%s", ocodec, codec_string))) {
codec_string = ocodec;
}
}
codec_string = switch_core_session_sprintf(smh->session, "%s,%s", ocodec, codec_string);
}
ready:
@@ -1873,83 +1868,6 @@ SWITCH_DECLARE(void) switch_core_media_prepare_codecs(switch_core_session_t *ses
switch_channel_set_variable(session->channel, "rtp_use_codec_string", codec_string);
smh->codec_order_last = switch_separate_string(tmp_codec_string, ',', smh->codec_order, SWITCH_MAX_CODECS);
smh->mparams->num_codecs = switch_loadable_module_get_codecs_sorted(smh->codecs, smh->fmtp, SWITCH_MAX_CODECS, smh->codec_order, smh->codec_order_last);
}
static void adjust_jb(switch_core_session_t *session, int new_ptime_ms)
{
const char *val;
switch_media_handle_t *smh;
switch_rtp_engine_t *a_engine = NULL;
int maxlen = 0;
int32_t jb_msec = 0 ;
int qlen, maxqlen = 50;
switch_assert(session);
if (!(smh = session->media_handle)) {
return;
}
a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
if ((val = switch_channel_get_variable(session->channel, "jitterbuffer_msec")) || (val = smh->mparams->jb_msec)) {
char *p;
if (!jb_msec) {
jb_msec = atoi(val);
if (strchr(val, 'p') && jb_msec > 0) {
jb_msec *= -1;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG3, "Will not adjust JB size, token 'p' not specified\n");
return;
}
if ((p = strchr(val, ':'))) {
p++;
maxlen = atoi(p);
if (strchr(p, 'p') && maxlen > 0) {
maxlen *= -1;
}
}
}
if (jb_msec < 0 && jb_msec > -1000) {
jb_msec = new_ptime_ms * abs(jb_msec);
}
if (maxlen < 0 && maxlen > -1000) {
maxlen = new_ptime_ms * abs(maxlen);
}
if (jb_msec < 10 || jb_msec > 10000) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,
"Invalid Jitterbuffer spec [%d] must be between 10 and 10000\n", jb_msec);
} else {
qlen = jb_msec / new_ptime_ms;
if (maxlen) {
maxqlen = maxlen / new_ptime_ms;
}
if (maxqlen < qlen) {
maxqlen = qlen * 5;
}
if (switch_rtp_activate_jitter_buffer(a_engine->rtp_session, qlen, maxqlen,
a_engine->read_impl.samples_per_packet, a_engine->read_impl.samples_per_second) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session),
SWITCH_LOG_DEBUG, "Adjusting Jitterbuffer to %dms (%d frames) (%d max frames)\n",
jb_msec, qlen, maxqlen);
switch_channel_set_flag(session->channel, CF_JITTERBUFFER);
if (!switch_false(switch_channel_get_variable(session->channel, "rtp_jitter_buffer_plc"))) {
switch_channel_set_flag(session->channel, CF_JITTERBUFFER_PLC);
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session),
SWITCH_LOG_DEBUG, "Error adjusting Jitterbuffer to %dms (%d frames)\n", jb_msec, qlen);
}
}
}
}
static void check_jb(switch_core_session_t *session, const char *input, int32_t jb_msec, int32_t maxlen, switch_bool_t silent)
@@ -2498,6 +2416,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session
if (engine->last_codec_ms && engine->last_codec_ms == codec_ms) {
engine->mismatch_count++;
} else {
engine->mismatch_count = 0;
}
engine->last_codec_ms = codec_ms;
@@ -2554,9 +2474,17 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session
codec_ms = codec_ms / (int) (engine->read_frame.seq - engine->last_seq);
}
if (codec_ms && codec_ms != engine->cur_payload_map->codec_ms) {
if (engine->last_codec_ms && engine->last_codec_ms == codec_ms) {
engine->mismatch_count++;
}
} else {
engine->mismatch_count = 0;
}
engine->last_codec_ms = codec_ms;
if (codec_ms != engine->cur_payload_map->codec_ms && codec_ms) {
if (engine->mismatch_count > MAX_MISMATCH_FRAMES) {
if (codec_ms > 120) {
/*will show too many times with packet loss*/
@@ -2571,14 +2499,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session
if (codec_ms != engine->cur_payload_map->codec_ms) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
"[%s]: Asynchronous PTIME supported, adjusting JB size. Remote PTIME changed from [%d] to [%d]\n",
"[%s]: Packet size change detected. Remote PTIME changed from [%d] to [%d]\n",
is_vbr?"VBR":"CBR",
(int) engine->cur_payload_map->codec_ms,
(int) codec_ms
);
engine->cur_payload_map->codec_ms = codec_ms;
/* adjust audio JB size, but do not substitute the codec */
adjust_jb(session,codec_ms);
engine->reset_codec = 2;
if (switch_channel_test_flag(session->channel, CF_CONFERENCE)) {
@@ -3576,7 +3502,7 @@ static switch_status_t check_ice(switch_media_handle_t *smh, switch_media_type_t
done_choosing:
if (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]) {
if (!engine->ice_in.is_chosen[0]) {
/* PUNT */
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "%s no suitable candidates found.\n",
switch_channel_get_name(smh->session->channel));
@@ -3780,7 +3706,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
sdp_media_t *m;
sdp_attribute_t *attr;
int ptime = 0, dptime = 0, maxptime = 0, dmaxptime = 0;
int sendonly = 0, recvonly = 0;
int sendonly = 0, recvonly = 0, inactive = 0;
int greedy = 0, x = 0, skip = 0;
switch_channel_t *channel = switch_core_session_get_channel(session);
const char *val;
@@ -3789,7 +3715,6 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
int scrooge = 0;
sdp_parser_t *parser = NULL;
sdp_session_t *sdp;
int reneg = 1;
const switch_codec_implementation_t **codec_array;
int total_codecs;
switch_rtp_engine_t *a_engine, *v_engine;
@@ -3839,7 +3764,9 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
a_engine->new_dtls = 1;
a_engine->new_ice = 1;
a_engine->reject_avp = 0;
switch_media_handle_set_media_flag(smh, SCMF_RECV_SDP);
switch_core_session_parse_crypto_prefs(session);
clear_pmaps(a_engine);
@@ -3951,116 +3878,120 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
got_udptl++;
}
if (got_udptl && m->m_type == sdp_media_image && m->m_port) {
switch_t38_options_t *t38_options = switch_core_media_process_udptl(session, sdp, m);
if (got_udptl && m->m_type == sdp_media_image) {
switch_channel_set_flag(session->channel, CF_IMAGE_SDP);
if (switch_channel_test_app_flag_key("T38", session->channel, CF_APP_T38_NEGOTIATED)) {
if (m->m_port) {
switch_t38_options_t *t38_options = switch_core_media_process_udptl(session, sdp, m);
if (switch_channel_test_app_flag_key("T38", session->channel, CF_APP_T38_NEGOTIATED)) {
match = 1;
goto done;
}
if (switch_true(switch_channel_get_variable(channel, "refuse_t38"))) {
switch_channel_clear_app_flag_key("T38", session->channel, CF_APP_T38);
match = 0;
goto done;
} else {
const char *var = switch_channel_get_variable(channel, "t38_passthru");
int pass = switch_channel_test_flag(smh->session->channel, CF_T38_PASSTHRU);
if (switch_channel_test_app_flag_key("T38", session->channel, CF_APP_T38)) {
if (proceed) *proceed = 0;
}
if (var) {
if (!(pass = switch_true(var))) {
if (!strcasecmp(var, "once")) {
pass = 2;
}
}
}
if ((pass == 2 && switch_channel_test_flag(smh->session->channel, CF_T38_PASSTHRU))
|| !switch_channel_test_flag(session->channel, CF_REINVITE) ||
switch_channel_test_flag(session->channel, CF_PROXY_MODE) ||
switch_channel_test_flag(session->channel, CF_PROXY_MEDIA) ||
!switch_rtp_ready(a_engine->rtp_session)) {
pass = 0;
}
if (pass && switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
switch_core_session_message_t *msg;
char *remote_host = switch_rtp_get_remote_host(a_engine->rtp_session);
switch_port_t remote_port = switch_rtp_get_remote_port(a_engine->rtp_session);
char tmp[32] = "";
if (!switch_channel_test_flag(other_channel, CF_ANSWERED)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session),
SWITCH_LOG_WARNING, "%s Error Passing T.38 to unanswered channel %s\n",
switch_channel_get_name(session->channel), switch_channel_get_name(other_channel));
switch_core_session_rwunlock(other_session);
pass = 0;
match = 0;
goto done;
}
if (switch_true(switch_channel_get_variable(session->channel, "t38_broken_boolean")) &&
switch_true(switch_channel_get_variable(session->channel, "t38_pass_broken_boolean"))) {
switch_channel_set_variable(other_channel, "t38_broken_boolean", "true");
}
a_engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(session, t38_options->remote_ip);
a_engine->cur_payload_map->remote_sdp_port = t38_options->remote_port;
if (remote_host && remote_port && !strcmp(remote_host, a_engine->cur_payload_map->remote_sdp_ip) && remote_port == a_engine->cur_payload_map->remote_sdp_port) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params are unchanged for %s.\n",
switch_channel_get_name(session->channel));
} else {
const char *err = NULL;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params changed for %s from %s:%d to %s:%d\n",
switch_channel_get_name(session->channel),
remote_host, remote_port, a_engine->cur_payload_map->remote_sdp_ip, a_engine->cur_payload_map->remote_sdp_port);
switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->remote_sdp_port);
switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, a_engine->cur_payload_map->remote_sdp_ip);
switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
if (switch_rtp_set_remote_address(a_engine->rtp_session, a_engine->cur_payload_map->remote_sdp_ip,
a_engine->cur_payload_map->remote_sdp_port, 0, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
}
switch_core_media_check_autoadj(session);
}
switch_core_media_copy_t38_options(t38_options, other_session);
switch_channel_set_flag(smh->session->channel, CF_T38_PASSTHRU);
switch_channel_set_flag(other_session->channel, CF_T38_PASSTHRU);
msg = switch_core_session_alloc(other_session, sizeof(*msg));
msg->message_id = SWITCH_MESSAGE_INDICATE_REQUEST_IMAGE_MEDIA;
msg->from = __FILE__;
msg->string_arg = switch_core_session_strdup(other_session, r_sdp);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing T38 req to other leg.\n%s\n", r_sdp);
switch_core_session_queue_message(other_session, msg);
switch_core_session_rwunlock(other_session);
}
}
/* do nothing here, mod_fax will trigger a response (if it's listening =/) */
match = 1;
goto done;
}
if (switch_true(switch_channel_get_variable(channel, "refuse_t38"))) {
switch_channel_clear_app_flag_key("T38", session->channel, CF_APP_T38);
match = 0;
goto done;
} else {
const char *var = switch_channel_get_variable(channel, "t38_passthru");
int pass = switch_channel_test_flag(smh->session->channel, CF_T38_PASSTHRU);
if (switch_channel_test_app_flag_key("T38", session->channel, CF_APP_T38)) {
if (proceed) *proceed = 0;
}
if (var) {
if (!(pass = switch_true(var))) {
if (!strcasecmp(var, "once")) {
pass = 2;
}
}
}
if ((pass == 2 && switch_channel_test_flag(smh->session->channel, CF_T38_PASSTHRU))
|| !switch_channel_test_flag(session->channel, CF_REINVITE) ||
switch_channel_test_flag(session->channel, CF_PROXY_MODE) ||
switch_channel_test_flag(session->channel, CF_PROXY_MEDIA) ||
!switch_rtp_ready(a_engine->rtp_session)) {
pass = 0;
}
if (pass && switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
switch_core_session_message_t *msg;
char *remote_host = switch_rtp_get_remote_host(a_engine->rtp_session);
switch_port_t remote_port = switch_rtp_get_remote_port(a_engine->rtp_session);
char tmp[32] = "";
if (!switch_channel_test_flag(other_channel, CF_ANSWERED)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session),
SWITCH_LOG_WARNING, "%s Error Passing T.38 to unanswered channel %s\n",
switch_channel_get_name(session->channel), switch_channel_get_name(other_channel));
switch_core_session_rwunlock(other_session);
pass = 0;
match = 0;
goto done;
}
if (switch_true(switch_channel_get_variable(session->channel, "t38_broken_boolean")) &&
switch_true(switch_channel_get_variable(session->channel, "t38_pass_broken_boolean"))) {
switch_channel_set_variable(other_channel, "t38_broken_boolean", "true");
}
a_engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(session, t38_options->remote_ip);
a_engine->cur_payload_map->remote_sdp_port = t38_options->remote_port;
if (remote_host && remote_port && !strcmp(remote_host, a_engine->cur_payload_map->remote_sdp_ip) && remote_port == a_engine->cur_payload_map->remote_sdp_port) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params are unchanged for %s.\n",
switch_channel_get_name(session->channel));
} else {
const char *err = NULL;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params changed for %s from %s:%d to %s:%d\n",
switch_channel_get_name(session->channel),
remote_host, remote_port, a_engine->cur_payload_map->remote_sdp_ip, a_engine->cur_payload_map->remote_sdp_port);
switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->remote_sdp_port);
switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, a_engine->cur_payload_map->remote_sdp_ip);
switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
if (switch_rtp_set_remote_address(a_engine->rtp_session, a_engine->cur_payload_map->remote_sdp_ip,
a_engine->cur_payload_map->remote_sdp_port, 0, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
}
switch_core_media_check_autoadj(session);
}
switch_core_media_copy_t38_options(t38_options, other_session);
switch_channel_set_flag(smh->session->channel, CF_T38_PASSTHRU);
switch_channel_set_flag(other_session->channel, CF_T38_PASSTHRU);
msg = switch_core_session_alloc(other_session, sizeof(*msg));
msg->message_id = SWITCH_MESSAGE_INDICATE_REQUEST_IMAGE_MEDIA;
msg->from = __FILE__;
msg->string_arg = switch_core_session_strdup(other_session, r_sdp);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing T38 req to other leg.\n%s\n", r_sdp);
switch_core_session_queue_message(other_session, msg);
switch_core_session_rwunlock(other_session);
}
}
/* do nothing here, mod_fax will trigger a response (if it's listening =/) */
match = 1;
goto done;
} else if (m->m_type == sdp_media_audio && m->m_port && got_audio && got_savp) {
a_engine->reject_avp = 1;
} else if (m->m_type == sdp_media_audio && m->m_port && !got_audio) {
@@ -4074,6 +4005,9 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
if (!sendonly && (m->m_mode == sdp_sendonly || m->m_mode == sdp_inactive)) {
sendonly = 1;
if (m->m_mode == sdp_inactive) {
inactive = 1;
}
}
if (!sendonly && m->m_connections && m->m_connections->c_address && !strcmp(m->m_connections->c_address, "0.0.0.0")) {
@@ -4093,6 +4027,10 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
switch_channel_set_variable(smh->session->channel, "audio_media_flow", "recvonly");
a_engine->smode = SWITCH_MEDIA_FLOW_RECVONLY;
break;
case SWITCH_MEDIA_FLOW_INACTIVE:
switch_channel_set_variable(smh->session->channel, "audio_media_flow", "inactive");
a_engine->smode = SWITCH_MEDIA_FLOW_INACTIVE;
break;
default:
switch_channel_set_variable(smh->session->channel, "audio_media_flow", "sendrecv");
a_engine->smode = SWITCH_MEDIA_FLOW_SENDRECV;
@@ -4112,7 +4050,6 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
sendonly = 1;
switch_channel_set_variable(session->channel, "media_audio_mode", "recvonly");
} else if (sendonly < 2 && !strcasecmp(attr->a_name, "inactive")) {
sendonly = 1;
switch_channel_set_variable(session->channel, "media_audio_mode", "inactive");
} else if (!strcasecmp(attr->a_name, "recvonly")) {
switch_channel_set_variable(session->channel, "media_audio_mode", "sendonly");
@@ -4140,12 +4077,19 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
}
if (sendonly != 1 && recvonly != 1) {
if (sendonly != 1 && recvonly != 1 && inactive != 1) {
switch_channel_set_variable(session->channel, "media_audio_mode", NULL);
}
if (sdp_type == SDP_TYPE_RESPONSE) {
if (sendonly) {
if (inactive) {
// When freeswitch had previously sent inactive in sip request. it should remain inactive otherwise smode should be sendrecv
if (a_engine->smode==SWITCH_MEDIA_FLOW_INACTIVE) {
a_engine->smode = sdp_media_flow(sdp_inactive);
} else {
a_engine->smode = sdp_media_flow(sdp_sendrecv);
}
} else if (sendonly) {
a_engine->smode = sdp_media_flow(sdp_sendonly);
} else if (recvonly) {
a_engine->smode = sdp_media_flow(sdp_recvonly);
@@ -4158,48 +4102,15 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
&& switch_true(val)))
&& !smh->mparams->hold_laps) {
smh->mparams->hold_laps++;
if (switch_core_media_toggle_hold(session, sendonly)) {
reneg = switch_media_handle_test_media_flag(smh, SCMF_RENEG_ON_HOLD);
if ((val = switch_channel_get_variable(session->channel, "rtp_renegotiate_codec_on_hold"))) {
reneg = switch_true(val);
}
}
}
if (reneg) {
reneg = switch_media_handle_test_media_flag(smh, SCMF_RENEG_ON_REINVITE);
if ((val = switch_channel_get_variable(session->channel, "rtp_renegotiate_codec_on_reinvite"))) {
reneg = switch_true(val);
}
}
if (session->bugs) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"Session is connected to a media bug. "
"Re-Negotiation implicitly disabled.\n");
reneg = 0;
}
if (switch_channel_test_flag(session->channel, CF_RECOVERING)) {
reneg = 0;
}
if (sdp_type == SDP_TYPE_RESPONSE && smh->num_negotiated_codecs) {
/* response to re-invite or update, only negotiated codecs are valid */
reneg = 0;
switch_core_media_toggle_hold(session, sendonly);
}
if (!reneg && smh->num_negotiated_codecs) {
codec_array = smh->negotiated_codecs;
total_codecs = smh->num_negotiated_codecs;
} else if (reneg) {
smh->mparams->num_codecs = 0;
switch_core_media_prepare_codecs(session, SWITCH_FALSE);
codec_array = smh->codecs;
total_codecs = smh->mparams->num_codecs;
}
smh->mparams->num_codecs = 0;
smh->num_negotiated_codecs = 0;
switch_core_media_prepare_codecs(session, SWITCH_TRUE);
codec_array = smh->codecs;
total_codecs = smh->mparams->num_codecs;
if (switch_rtp_has_dtls() && dtls_ok(session)) {
@@ -4261,7 +4172,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
}
x = 0;
for (map = m->m_rtpmaps; map; map = map->rm_next) {
int32_t i;
const char *rm_encoding;
@@ -4493,7 +4404,6 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
match = 1;
a_engine->codec_negotiated = 1;
smh->num_negotiated_codecs = 0;
for(j = 0; j < m_idx; j++) {
payload_map_t *pmap = switch_core_media_add_payload_map(session,
@@ -4552,6 +4462,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
pmap->rm_fmtp = switch_core_session_strdup(session, (char *) mmap->rm_fmtp);
pmap->agreed_pt = (switch_payload_t) mmap->rm_pt;
smh->negotiated_codecs[smh->num_negotiated_codecs++] = mimp;
pmap->recv_pt = (switch_payload_t)mmap->rm_pt;
@@ -4585,14 +4496,6 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
#if 0
if (!switch_true(mirror) &&
switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND &&
(!switch_channel_test_flag(session->channel, CF_REINVITE) || switch_media_handle_test_media_flag(smh, SCMF_RENEG_ON_REINVITE))) {
switch_core_media_get_offered_pt(session, matches[0].imp, &a_engine->cur_payload_map->recv_pt);
}
#endif
switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->recv_pt);
switch_channel_set_variable(session->channel, "rtp_audio_recv_pt", tmp);
@@ -4759,6 +4662,10 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
switch_channel_set_variable(smh->session->channel, "video_media_flow", "recvonly");
v_engine->smode = SWITCH_MEDIA_FLOW_RECVONLY;
break;
case SWITCH_MEDIA_FLOW_INACTIVE:
switch_channel_set_variable(smh->session->channel, "video_media_flow", "inactive");
v_engine->smode = SWITCH_MEDIA_FLOW_INACTIVE;
break;
default:
switch_channel_set_variable(smh->session->channel, "video_media_flow", "sendrecv");
v_engine->smode = SWITCH_MEDIA_FLOW_SENDRECV;
@@ -4836,10 +4743,11 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
if (!(rm_encoding = map->rm_encoding)) {
rm_encoding = "";
}
printf("WTF TOT %d\n", total_codecs);
for (i = 0; i < total_codecs; i++) {
const switch_codec_implementation_t *imp = codec_array[i];
if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
continue;
}
@@ -4849,7 +4757,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
continue;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CONSOLE, "Video Codec Compare [%s:%d]/[%s:%d]\n",
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video Codec Compare [%s:%d]/[%s:%d]\n",
rm_encoding, map->rm_pt, imp->iananame, imp->ianacode);
if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
vmatch = (map->rm_pt == imp->ianacode) ? 1 : 0;
@@ -4873,9 +4781,10 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
matches[m_idx].imp = imp;
matches[m_idx].map = map;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CONSOLE, "Video Codec Compare [%s:%d] +++ is saved as a match\n",
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video Codec Compare [%s:%d] +++ is saved as a match\n",
imp->iananame, map->rm_pt);
m_idx++;
m_idx++;
}
vmatch = 0;
@@ -5255,7 +5164,7 @@ static void *SWITCH_THREAD_FUNC video_write_thread(switch_thread_t *thread, void
switch_core_media_gen_key_frame(session);
if (smh->video_write_fh->mm.source_fps) {
if (smh->video_write_fh && smh->video_write_fh->mm.source_fps) {
fps = (int) smh->video_write_fh->mm.source_fps;
} else {
fps = video_globals.fps;
@@ -5758,6 +5667,24 @@ SWITCH_DECLARE(switch_bool_t) switch_core_session_in_video_thread(switch_core_se
}
SWITCH_DECLARE(void) switch_core_media_parse_media_flags(switch_core_session_t *session)
{
const char *var;
switch_media_handle_t *smh;
if (!(smh = session->media_handle)) {
return;
}
if ((var = switch_channel_get_variable(session->channel, "rtp_media_autofix_timing"))) {
if (switch_true(var)) {
switch_media_handle_set_media_flag(smh, SCMF_AUTOFIX_TIMING);
} else {
switch_media_handle_clear_media_flag(smh, SCMF_AUTOFIX_TIMING);
}
}
}
//?
#define RA_PTR_LEN 512
SWITCH_DECLARE(switch_status_t) switch_core_media_proxy_remote_addr(switch_core_session_t *session, const char *sdp_str)
@@ -6134,6 +6061,16 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_choose_port(switch_core_sessio
use_ip = smh->mparams->rtpip;
}
if (zstr(smh->mparams->remote_ip)) { /* no remote_ip, we're originating */
if (!zstr(smh->mparams->extrtpip)) { /* and we've got an ext-rtp-ip, eg, from verto config */
use_ip = smh->mparams->extrtpip; /* let's use it for composing local sdp to send to client */
/*
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,
"%s will use %s instead of %s in SDP, because we're originating and we have an ext-rtp-ip setting\n",
switch_channel_get_name(smh->session->channel), smh->mparams->extrtpip, smh->mparams->rtpip);
*/
}
}
engine->adv_sdp_port = sdp_port;
engine->adv_sdp_ip = smh->mparams->adv_sdp_audio_ip = smh->mparams->extrtpip = switch_core_session_strdup(session, use_ip);
@@ -6392,6 +6329,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
return SWITCH_STATUS_FALSE;
}
switch_core_media_parse_media_flags(session);
if (switch_rtp_ready(a_engine->rtp_session)) {
switch_rtp_reset_media_timer(a_engine->rtp_session);
@@ -6525,9 +6463,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n",
a_engine->cur_payload_map->remote_sdp_ip, a_engine->cur_payload_map->remote_sdp_port);
if (switch_channel_test_flag(session->channel, CF_PROTO_HOLD) && strcmp(a_engine->cur_payload_map->remote_sdp_ip, "0.0.0.0")) {
switch_core_media_toggle_hold(session, 0);
}
//if (switch_channel_test_flag(session->channel, CF_PROTO_HOLD) && strcmp(a_engine->cur_payload_map->remote_sdp_ip, "0.0.0.0")) {
// switch_core_media_toggle_hold(session, 0);
//}
if (!switch_media_handle_test_media_flag(smh, SCMF_DISABLE_RTP_AUTOADJ) &&
@@ -7099,8 +7037,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
if (v_engine->ice_in.cands[v_engine->ice_in.chosen[1]][1].ready) {
if (v_engine->rtcp_mux > 0 && !strcmp(v_engine->ice_in.cands[v_engine->ice_in.chosen[1]][1].con_addr, v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].con_addr)
&& v_engine->ice_in.cands[v_engine->ice_in.chosen[1]][1].con_port == v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].con_port) {
if (v_engine->rtcp_mux > 0 && v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].ready &&
!strcmp(v_engine->ice_in.cands[v_engine->ice_in.chosen[1]][1].con_addr,
v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].con_addr) &&
v_engine->ice_in.cands[v_engine->ice_in.chosen[1]][1].con_port == v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].con_port) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Skipping VIDEO RTCP ICE (Same as VIDEO RTP)\n");
} else {
@@ -7410,7 +7350,7 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen,
}
if (!zstr(a_engine->local_dtls_fingerprint.type) && secure) {
switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=fingerprint:%s %s\na=setup:%s\r\n", a_engine->local_dtls_fingerprint.type,
switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=fingerprint:%s %s\r\na=setup:%s\r\n", a_engine->local_dtls_fingerprint.type,
a_engine->local_dtls_fingerprint.str, get_setup(a_engine, session, sdp_type));
}
@@ -7704,7 +7644,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
int is_outbound = switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND;
const char *vbw;
int bw = 256;
uint8_t fir = 0, nack = 0, pli = 0, tmmbr = 0;
uint8_t fir = 0, nack = 0, pli = 0, tmmbr = 0, has_vid = 0;
switch_assert(session);
@@ -7749,6 +7689,10 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
smh->mparams->rtcp_video_interval_msec = SWITCH_RTCP_VIDEO_INTERVAL_MSEC;
}
if (switch_true(switch_channel_get_variable(session->channel, "add_ice_candidates"))) {
switch_channel_set_flag(session->channel, CF_ICE);
}
if ( switch_rtp_has_dtls() && dtls_ok(session)) {
if (switch_channel_test_flag(session->channel, CF_AVPF) ||
switch_true(switch_channel_get_variable(smh->session->channel, "rtp_use_dtls"))) {
@@ -7940,12 +7884,14 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
sr = "sendonly";
} else if (a_engine->smode == SWITCH_MEDIA_FLOW_RECVONLY) {
sr = "recvonly";
} else if (a_engine->smode == SWITCH_MEDIA_FLOW_INACTIVE) {
sr = "inactive";
} else {
sr = "sendrecv";
}
if ((var_val = switch_channel_get_variable(session->channel, "origination_audio_mode"))) {
if (!strcasecmp(sr, "sendonly") || !strcasecmp(sr, "recvonly") || !strcasecmp(sr, "sendrecv")) {
if (!strcasecmp(sr, "sendonly") || !strcasecmp(sr, "recvonly") || !strcasecmp(sr, "sendrecv") || !strcasecmp(sr, "inactive")) {
sr = var_val;
}
switch_channel_set_variable(session->channel, "origination_audio_mode", NULL);
@@ -8073,7 +8019,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d telephone-event/%d\r\n",
smh->mparams->te, smh->mparams->te_rate);
} else {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d telephone-event/%d\na=fmtp:%d 0-16\r\n",
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d telephone-event/%d\r\na=fmtp:%d 0-16\r\n",
smh->mparams->te, smh->mparams->te_rate, smh->mparams->te);
}
}
@@ -8290,9 +8236,34 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
}
if (switch_channel_test_flag(session->channel, CF_IMAGE_SDP)) {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=image 0 UDPTL T38\r\n", SWITCH_VA_NONE);
}
video:
if (!switch_channel_test_flag(session->channel, CF_VIDEO_POSSIBLE)) {
if (!switch_channel_test_flag(session->channel, CF_VIDEO_POSSIBLE) && switch_media_handle_test_media_flag(smh, SCMF_RECV_SDP)) {
has_vid = 0;
} else {
int i;
for (i = 0; i < smh->mparams->num_codecs; i++) {
const switch_codec_implementation_t *imp = smh->codecs[i];
if (imp->codec_type == SWITCH_CODEC_TYPE_VIDEO) {
has_vid = 1;
break;
}
}
}
if (!has_vid) {
if (switch_channel_test_flag(session->channel, CF_VIDEO_SDP_RECVD)) {
switch_channel_clear_flag(session->channel, CF_VIDEO_SDP_RECVD);
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=video 0 %s 19\r\n",
@@ -8385,6 +8356,24 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
}
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\r\n");
if (!(vbw = switch_channel_get_variable(smh->session->channel, "rtp_video_max_bandwidth"))) {
vbw = switch_channel_get_variable(smh->session->channel, "rtp_video_max_bandwidth_in");
}
if (!vbw) {
vbw = "1mb";
}
bw = switch_parse_bandwidth_string(vbw);
if (bw > 0) {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "b=AS:%d\r\n", bw);
//switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "b=TIAS:%d\r\n", bw);
}
if (v_engine->codec_negotiated) {
const char *of;
@@ -8452,6 +8441,8 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s", "a=sendonly\r\n");
} else if (v_engine->smode == SWITCH_MEDIA_FLOW_RECVONLY) {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s", "a=recvonly\r\n");
} else if (v_engine->smode == SWITCH_MEDIA_FLOW_INACTIVE) {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s", "a=inactive\r\n");
}
} else if (smh->mparams->num_codecs) {
@@ -8537,8 +8528,8 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
if (!zstr(v_engine->local_dtls_fingerprint.type)) {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fingerprint:%s %s\na=setup:%s\r\n", v_engine->local_dtls_fingerprint.type,
v_engine->local_dtls_fingerprint.str, get_setup(v_engine, session, sdp_type));
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fingerprint:%s %s\r\na=setup:%s\r\n",
v_engine->local_dtls_fingerprint.type, v_engine->local_dtls_fingerprint.str, get_setup(v_engine, session, sdp_type));
}
@@ -8551,22 +8542,6 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
}
}
if (!(vbw = switch_channel_get_variable(smh->session->channel, "rtp_video_max_bandwidth"))) {
vbw = switch_channel_get_variable(smh->session->channel, "rtp_video_max_bandwidth_in");
}
if (!vbw) {
vbw = "1mb";
}
bw = switch_parse_bandwidth_string(vbw);
if (bw > 0) {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "b=AS:%d\r\n", bw);
//switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "b=TIAS:%d\r\n", bw);
}
if (sdp_type == SDP_TYPE_REQUEST) {
fir++;
pli++;
@@ -8826,6 +8801,7 @@ SWITCH_DECLARE(void) switch_core_media_set_udptl_image_sdp(switch_core_session_t
a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
switch_channel_clear_flag(session->channel, CF_IMAGE_SDP);
switch_assert(t38_options);
@@ -9837,8 +9813,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_se
switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 1);
}
switch_media_handle_set_media_flag(smh, SCMF_RENEG_ON_REINVITE);
if (msg->numeric_arg && switch_core_session_get_partner(session, &nsession) == SWITCH_STATUS_SUCCESS) {
msg->numeric_arg = 0;
switch_core_session_receive_message(nsession, msg);
@@ -11222,8 +11196,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_encoded_video_frame(sw
switch_io_event_hook_video_write_frame_t *ptr;
switch_status_t status = SWITCH_STATUS_FALSE;
if (switch_core_session_media_flow(session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_RECVONLY) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG3, "Writing video to RECVONLY session\n");
if (switch_core_session_media_flow(session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_RECVONLY || switch_core_session_media_flow(session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG3, "Writing video to RECVONLY/INACTIVE session\n");
return SWITCH_STATUS_SUCCESS;
}
@@ -11293,8 +11267,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_video_frame(switch_cor
return SWITCH_STATUS_FALSE;
}
if (switch_core_session_media_flow(session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_RECVONLY) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG3, "Writing video to RECVONLY session\n");
if (switch_core_session_media_flow(session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_RECVONLY || switch_core_session_media_flow(session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG3, "Writing video to RECVONLY/INACTIVE session\n");
return SWITCH_STATUS_SUCCESS;
}
@@ -11524,6 +11498,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_video_frame(switch_core
switch_io_event_hook_video_read_frame_t *ptr;
uint32_t loops = 0;
switch_media_handle_t *smh;
int patchers = 0;
switch_assert(session != NULL);
@@ -11679,7 +11654,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_video_frame(switch_core
if (bp->callback && switch_test_flag(bp, SMBF_READ_VIDEO_PING)) {
if (switch_test_flag(bp, SMBF_READ_VIDEO_PATCH)) {
patchers++;
}
bp->video_ping_frame = *frame;
if (bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ_VIDEO_PING) == SWITCH_FALSE
|| (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL))) {
ok = SWITCH_FALSE;
@@ -11705,7 +11685,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_video_frame(switch_core
}
}
if ((*frame) && (*frame)->codec) {
if (patchers) {
switch_set_flag((*frame)->codec, SWITCH_CODEC_FLAG_VIDEO_PATCHING);
} else {
switch_clear_flag((*frame)->codec, SWITCH_CODEC_FLAG_VIDEO_PATCHING);
}
}
if (status == SWITCH_STATUS_SUCCESS) {
switch_core_session_video_read_callback(session, *frame);
+2 -2
View File
@@ -2031,7 +2031,7 @@ static inline uint32_t switch_img_fmt2fourcc(switch_img_fmt_t fmt)
}
#endif
SWITCH_DECLARE(switch_status_t) switch_img_to_raw(switch_image_t *src, void *dest, switch_size_t size, switch_img_fmt_t fmt)
SWITCH_DECLARE(switch_status_t) switch_img_to_raw(switch_image_t *src, void *dest, int stride, switch_img_fmt_t fmt)
{
#ifdef SWITCH_HAVE_YUV
uint32_t fourcc;
@@ -2050,7 +2050,7 @@ SWITCH_DECLARE(switch_status_t) switch_img_to_raw(switch_image_t *src, void *des
ret = ConvertFromI420(src->planes[0], src->stride[0],
src->planes[1], src->stride[1],
src->planes[2], src->stride[2],
dest, size,
dest, stride,
src->d_w, src->d_h,
fourcc);
+1
View File
@@ -2752,6 +2752,7 @@ static void unsub_all_switch_event_channel(void)
free(head);
}
switch_safe_free(hi);
switch_thread_rwlock_unlock(event_channel_manager.rwlock);
}
+12 -3
View File
@@ -1759,9 +1759,18 @@ static void *SWITCH_THREAD_FUNC early_thread_run(switch_thread_t *thread, void *
switch_codec_implementation_t read_impl = { 0 };
for (i = 0; i < MAX_PEERS && i < state->ttl; i++) {
if (switch_core_session_read_lock(state->originate_status[i].peer_session) == SWITCH_STATUS_SUCCESS) {
originate_status[i].peer_session = state->originate_status[i].peer_session;
originate_status[i].peer_channel = switch_core_session_get_channel(state->originate_status[i].peer_session);
switch_core_session_t *session = state->originate_status[i].peer_session;
switch_channel_t *channel = NULL;
if (session) channel = switch_core_session_get_channel(session);
if (!session || !channel || !switch_channel_up(channel)) {
continue;
}
if (switch_core_session_read_lock(session) == SWITCH_STATUS_SUCCESS) {
originate_status[i].peer_session = session;
originate_status[i].peer_channel = channel;
}
}
+253
View File
@@ -2111,6 +2111,259 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_wait_for_silence(switch_core_session_
return status;
}
SWITCH_DECLARE(switch_status_t) switch_ivr_detect_audio(switch_core_session_t *session, uint32_t thresh,
uint32_t audio_hits, uint32_t timeout_ms, const char *file)
{
uint32_t score, count = 0, j = 0;
double energy = 0;
switch_channel_t *channel = switch_core_session_get_channel(session);
int divisor = 0;
uint32_t channels;
switch_frame_t *read_frame;
switch_status_t status = SWITCH_STATUS_FALSE;
int16_t *data;
uint32_t hits = 0;
switch_codec_t raw_codec = { 0 };
int16_t *abuf = NULL;
switch_frame_t write_frame = { 0 };
switch_file_handle_t fh = { 0 };
int32_t sample_count = 0;
switch_codec_implementation_t read_impl = { 0 };
switch_core_session_get_read_impl(session, &read_impl);
if (timeout_ms) {
sample_count = (read_impl.actual_samples_per_second / 1000) * timeout_ms;
}
if (file) {
if (switch_core_file_open(&fh,
file,
read_impl.number_of_channels,
read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
switch_core_session_reset(session, SWITCH_TRUE, SWITCH_FALSE);
return SWITCH_STATUS_NOTFOUND;
}
switch_zmalloc(abuf, SWITCH_RECOMMENDED_BUFFER_SIZE);
write_frame.data = abuf;
write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
}
if (switch_core_codec_init(&raw_codec,
"L16",
NULL,
NULL,
read_impl.actual_samples_per_second,
read_impl.microseconds_per_packet / 1000,
1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
status = SWITCH_STATUS_FALSE;
goto end;
}
write_frame.codec = &raw_codec;
divisor = read_impl.actual_samples_per_second / 8000;
channels = read_impl.number_of_channels;
switch_core_session_set_read_codec(session, &raw_codec);
while (switch_channel_ready(channel)) {
status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
if (!SWITCH_READ_ACCEPTABLE(status)) {
break;
}
if (sample_count) {
sample_count -= raw_codec.implementation->samples_per_packet;
if (sample_count <= 0) {
switch_channel_set_variable(channel, "detect_audio_timeout", "true");
switch_channel_set_variable_printf(channel, "detect_audio_hits", "%d", hits);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "switch_ivr_detect_audio: TIMEOUT %d hits\n", hits);
break;
}
}
if (abuf) {
switch_size_t olen = raw_codec.implementation->samples_per_packet;
if (switch_core_file_read(&fh, abuf, &olen) != SWITCH_STATUS_SUCCESS) {
break;
}
write_frame.samples = (uint32_t) olen;
write_frame.datalen = (uint32_t) (olen * sizeof(int16_t) * fh.channels);
if ((status = switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0)) != SWITCH_STATUS_SUCCESS) {
break;
}
}
data = (int16_t *) read_frame->data;
for (energy = 0, j = 0, count = 0; count < read_frame->samples; count++) {
energy += abs(data[j++]);
j += channels;
}
score = (uint32_t) (energy / (read_frame->samples / divisor));
if (score >= thresh) {
hits++;
} else {
hits=0;
}
if (hits > audio_hits) {
switch_channel_set_variable(channel, "detect_audio_timeout", "false");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "switch_ivr_detect_audio: AUDIO DETECTED\n");
break;
}
}
switch_core_session_reset(session, SWITCH_FALSE, SWITCH_TRUE);
switch_core_codec_destroy(&raw_codec);
end:
if (abuf) {
switch_core_file_close(&fh);
free(abuf);
}
return status;
}
SWITCH_DECLARE(switch_status_t) switch_ivr_detect_silence(switch_core_session_t *session, uint32_t thresh,
uint32_t silence_hits, uint32_t timeout_ms, const char *file)
{
uint32_t score, count = 0, j = 0;
double energy = 0;
switch_channel_t *channel = switch_core_session_get_channel(session);
int divisor = 0;
uint32_t channels;
switch_frame_t *read_frame;
switch_status_t status = SWITCH_STATUS_FALSE;
int16_t *data;
uint32_t hits = 0;
switch_codec_t raw_codec = { 0 };
int16_t *abuf = NULL;
switch_frame_t write_frame = { 0 };
switch_file_handle_t fh = { 0 };
int32_t sample_count = 0;
switch_codec_implementation_t read_impl = { 0 };
switch_core_session_get_read_impl(session, &read_impl);
if (timeout_ms) {
sample_count = (read_impl.actual_samples_per_second / 1000) * timeout_ms;
}
if (file) {
if (switch_core_file_open(&fh,
file,
read_impl.number_of_channels,
read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
switch_core_session_reset(session, SWITCH_TRUE, SWITCH_FALSE);
return SWITCH_STATUS_NOTFOUND;
}
switch_zmalloc(abuf, SWITCH_RECOMMENDED_BUFFER_SIZE);
write_frame.data = abuf;
write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
}
if (switch_core_codec_init(&raw_codec,
"L16",
NULL,
NULL,
read_impl.actual_samples_per_second,
read_impl.microseconds_per_packet / 1000,
1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
status = SWITCH_STATUS_FALSE;
goto end;
}
write_frame.codec = &raw_codec;
divisor = read_impl.actual_samples_per_second / 8000;
channels = read_impl.number_of_channels;
switch_core_session_set_read_codec(session, &raw_codec);
while (switch_channel_ready(channel)) {
status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
if (!SWITCH_READ_ACCEPTABLE(status)) {
break;
}
if (sample_count) {
sample_count -= raw_codec.implementation->samples_per_packet;
if (sample_count <= 0) {
switch_channel_set_variable(channel, "detect_silence_timeout", "true");
switch_channel_set_variable_printf(channel, "detect_silence_hits", "%d", hits);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "switch_ivr_detect_silence: TIMEOUT %d hits\n", hits);
break;
}
}
if (abuf) {
switch_size_t olen = raw_codec.implementation->samples_per_packet;
if (switch_core_file_read(&fh, abuf, &olen) != SWITCH_STATUS_SUCCESS) {
break;
}
write_frame.samples = (uint32_t) olen;
write_frame.datalen = (uint32_t) (olen * sizeof(int16_t) * fh.channels);
if ((status = switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0)) != SWITCH_STATUS_SUCCESS) {
break;
}
}
data = (int16_t *) read_frame->data;
for (energy = 0, j = 0, count = 0; count < read_frame->samples; count++) {
energy += abs(data[j++]);
j += channels;
}
score = (uint32_t) (energy / (read_frame->samples / divisor));
if (score <= thresh) {
hits++;
} else {
hits=0;
}
if (hits > silence_hits) {
switch_channel_set_variable(channel, "detect_silence_timeout", "false");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "switch_ivr_detect_silence: SILENCE DETECTED\n");
break;
}
}
switch_core_session_reset(session, SWITCH_FALSE, SWITCH_TRUE);
switch_core_codec_destroy(&raw_codec);
end:
if (abuf) {
switch_core_file_close(&fh);
free(abuf);
}
return status;
}
SWITCH_DECLARE(switch_status_t) switch_ivr_read(switch_core_session_t *session,
uint32_t min_digits,
uint32_t max_digits,
+6 -4
View File
@@ -902,10 +902,10 @@ SWITCH_DECLARE(switch_status_t) switch_jb_peek_frame(switch_jb_t *jb, uint32_t t
frame->seq = ntohs(node->packet.header.seq);
frame->timestamp = ntohl(node->packet.header.ts);
frame->m = node->packet.header.m;
frame->datalen = node->len;
frame->datalen = node->len - 12;
if (frame->data && frame->buflen > node->len) {
memcpy(frame->data, node->packet.body, node->len);
if (frame->data && frame->buflen > node->len - 12) {
memcpy(frame->data, node->packet.body, node->len - 12);
}
return SWITCH_STATUS_SUCCESS;
}
@@ -1039,7 +1039,7 @@ SWITCH_DECLARE(uint32_t) switch_jb_pop_nack(switch_jb_t *jb)
top:
for (hi = switch_core_hash_first(jb->missing_seq_hash); hi; hi = switch_core_hash_next(&hi)) {
for (hi = switch_core_hash_first_iter(jb->missing_seq_hash, hi); hi; hi = switch_core_hash_next(&hi)) {
uint16_t seq;
//const char *token;
switch_time_t then = 0;
@@ -1076,6 +1076,8 @@ SWITCH_DECLARE(uint32_t) switch_jb_pop_nack(switch_jb_t *jb)
}
}
switch_safe_free(hi);
if (least && switch_core_inthash_delete(jb->missing_seq_hash, (uint32_t)htons(least))) {
jb_debug(jb, 3, "Found NACKABLE seq %u\n", least);
nack = (uint32_t) htons(least);
+26 -16
View File
@@ -452,6 +452,7 @@ struct switch_rtp {
uint8_t has_ice;
uint8_t punts;
uint8_t clean;
uint32_t last_max_vb_frames;
#ifdef ENABLE_ZRTP
zrtp_session_t *zrtp_session;
zrtp_profile_t *zrtp_profile;
@@ -2069,17 +2070,8 @@ static int check_rtcp_and_ice(switch_rtp_t *rtp_session)
rtcp_generate_report_block(rtp_session, rtcp_report_block);
rtp_session->rtcp_send_msg.header.length = htons((uint16_t)(rtcp_bytes / 4) - 1);
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
//if (rtp_session->remote_ssrc == 0) {
// rtp_session->remote_ssrc = rtp_session->stats.rtcp.peer_ssrc;
//}
//if (rtp_session->remote_ssrc == 0) {
// rtp_session->remote_ssrc = ntohl(rtp_session->last_rtp_hdr.ssrc);
//}
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
if (rtp_session->pli_count) {
switch_rtcp_ext_hdr_t *ext_hdr;
@@ -2094,7 +2086,8 @@ static int check_rtcp_and_ice(switch_rtp_t *rtp_session)
ext_hdr->send_ssrc = htonl(rtp_session->ssrc);
ext_hdr->recv_ssrc = htonl(rtp_session->remote_ssrc);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG1, "Sending RTCP PLI\n");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG1, "Sending RTCP PLI %u %u\n",
rtp_session->ssrc, rtp_session->remote_ssrc);
ext_hdr->length = htons((uint8_t)(sizeof(switch_rtcp_ext_hdr_t) / 4) - 1);
rtcp_bytes += sizeof(switch_rtcp_ext_hdr_t);
@@ -2927,7 +2920,6 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_address(switch_rtp_t *rtp_
switch_mutex_lock(rtp_session->write_mutex);
rtp_session->remote_addr = remote_addr;
switch_cp_addr(rtp_session->rtp_from_addr, rtp_session->remote_addr);
if (change_adv_addr) {
rtp_session->remote_host_str = switch_core_strdup(rtp_session->pool, host);
@@ -3734,7 +3726,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_ssrc(switch_rtp_t *rtp_session, u
SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_ssrc(switch_rtp_t *rtp_session, uint32_t ssrc)
{
rtp_session->remote_ssrc = ssrc;
rtp_session->flags[SWITCH_RTP_FLAG_DETECT_SSRC] = 0;
return SWITCH_STATUS_SUCCESS;
}
@@ -4005,6 +3997,7 @@ SWITCH_DECLARE(switch_rtp_t *) switch_rtp_new(const char *rx_host,
rtp_session->rx_host = switch_core_strdup(rtp_session->pool, rx_host);
rtp_session->rx_port = rx_port;
switch_rtp_set_flag(rtp_session, SWITCH_RTP_FLAG_FLUSH);
switch_rtp_set_flag(rtp_session, SWITCH_RTP_FLAG_DETECT_SSRC);
} else {
switch_rtp_release_port(rx_host, rx_port);
}
@@ -4106,9 +4099,15 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_video_buffer_size(switch_rtp_t *r
}
if (!max_frames) {
max_frames = 50;
max_frames = rtp_session->last_max_vb_frames;
}
if (!max_frames || frames >= max_frames) {
max_frames = frames + 8;
}
rtp_session->last_max_vb_frames = max_frames;
if (!rtp_session->vb) {
switch_jb_create(&rtp_session->vb, SJB_VIDEO, frames, max_frames, rtp_session->pool);
switch_jb_set_session(rtp_session->vb, rtp_session->session);
@@ -5251,6 +5250,17 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
rtp_session->missed_count = 0;
switch_cp_addr(rtp_session->rtp_from_addr, rtp_session->from_addr);
rtp_session->last_rtp_hdr = rtp_session->recv_msg.header;
if (rtp_session->flags[SWITCH_RTP_FLAG_DETECT_SSRC]) {
//if (rtp_session->remote_ssrc != rtp_session->stats.rtcp.peer_ssrc && rtp_session->stats.rtcp.peer_ssrc) {
// rtp_session->remote_ssrc = rtp_session->stats.rtcp.peer_ssrc;
//}
if (rtp_session->remote_ssrc != rtp_session->last_rtp_hdr.ssrc && rtp_session->last_rtp_hdr.ssrc) {
rtp_session->remote_ssrc = ntohl(rtp_session->last_rtp_hdr.ssrc);
}
}
}
}
@@ -5802,7 +5812,7 @@ static void handle_nack(switch_rtp_t *rtp_session, uint32_t nack)
send_msg->header.pt, ntohl(send_msg->header.ts), ntohs(send_msg->header.seq), send_msg->header.m);
}
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "RE----SEND %u\n", ntohs(send_msg->header.seq));
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "RE----SEND %u\n", ntohs(send_msg->header.seq));
switch_rtp_write_raw(rtp_session, (void *) send_msg, &bytes, SWITCH_FALSE);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG1, "Cannot send NACK for seq %u\n", ntohs(seq));
@@ -5826,7 +5836,7 @@ static void handle_nack(switch_rtp_t *rtp_session, uint32_t nack)
send_msg->header.pt, ntohl(send_msg->header.ts), ntohs(send_msg->header.seq), send_msg->header.m);
}
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "RE----SEND %u\n", ntohs(send_msg->header.seq));
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "RE----SEND %u\n", ntohs(send_msg->header.seq));
switch_rtp_write_raw(rtp_session, (void *) &send_msg, &bytes, SWITCH_FALSE);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG1, "Cannot send NACK for seq %u\n", ntohs(seq) + i);
+41 -15
View File
@@ -42,6 +42,12 @@
// #define DEBUG_VP9
#ifdef DEBUG_VP9
#define VPX_SWITCH_LOG_LEVEL SWITCH_LOG_ERROR
#else
#define VPX_SWITCH_LOG_LEVEL SWITCH_LOG_DEBUG1
#endif
#define SLICE_SIZE SWITCH_DEFAULT_VIDEO_SIZE
#define KEY_FRAME_MIN_FREQ 250000
@@ -291,6 +297,7 @@ struct vpx_context {
int got_start_frame;
uint32_t last_received_timestamp;
switch_bool_t last_received_complete_picture;
uint16_t last_received_seq;
int need_key_frame;
int need_encoder_reset;
int need_decoder_reset;
@@ -299,6 +306,7 @@ struct vpx_context {
switch_memory_pool_t *pool;
switch_buffer_t *pbuffer;
switch_time_t start_time;
switch_image_t *patch_img;
};
typedef struct vpx_context vpx_context_t;
@@ -332,6 +340,7 @@ static switch_status_t init_decoder(switch_codec_t *codec)
context->last_ts = 0;
context->last_received_timestamp = 0;
context->last_received_complete_picture = 0;
context->last_received_seq = 0;
context->decoder_init = 1;
context->got_key_frame = 0;
context->no_key_frame = 0;
@@ -405,7 +414,7 @@ static switch_status_t init_encoder(switch_codec_t *codec)
config->g_lag_in_frames = 0;
config->kf_max_dist = 360;//2000;
threads = cpus / 4;
if (threads < 0) threads = 1;
if (threads < 1) threads = 1;
config->g_threads = threads;
if (context->is_vp9) {
@@ -965,7 +974,8 @@ static switch_status_t buffer_vp9_packets(vpx_context_t *context, switch_frame_t
int len = 0;
#ifdef DEBUG_VP9
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%02x %02x %02x %02x m=%d len=%4d "
switch_log_printf(SWITCH_CHANNEL_LOG, frame->m ? SWITCH_LOG_ERROR : SWITCH_LOG_INFO,
"[%02x %02x %02x %02x] m=%d len=%4d seq=%d ts=%u ssrc=%u "
"have_pid=%d "
"have_p_layer=%d "
"have_layer_ind=%d "
@@ -974,7 +984,7 @@ static switch_status_t buffer_vp9_packets(vpx_context_t *context, switch_frame_t
"end=%d "
"have_ss=%d "
"zero=%d\n",
*data, *(data+1), *(data+2), *(data+3), frame->m, frame->datalen,
*data, *(data+1), *(data+2), *(data+3), frame->m, frame->datalen, frame->seq, frame->timestamp, frame->ssrc,
desc->have_pid,
desc->have_p_layer,
desc->have_layer_ind,
@@ -1000,7 +1010,7 @@ static switch_status_t buffer_vp9_packets(vpx_context_t *context, switch_frame_t
vp9++;
#ifdef DEBUG_VP9
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "have pid: %d start=%d end=%d\n", pid, desc->start, desc->end);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "have pid: %d start=%d end=%d\n", pid, desc->start, desc->end);
#endif
}
@@ -1071,12 +1081,7 @@ static switch_status_t buffer_vp9_packets(vpx_context_t *context, switch_frame_t
goto end;
}
if (switch_buffer_inuse(context->vpx_packet_buffer)) { // middle packet
if (desc->start) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "got invalid vp9 packet, packet loss? resetting buffer\n");
switch_buffer_zero(context->vpx_packet_buffer);
}
} else { // start packet
if (!switch_buffer_inuse(context->vpx_packet_buffer)) { // start packet
if (!desc->start) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "got invalid vp9 packet, packet loss? waiting for a start packet\n");
goto end;
@@ -1089,7 +1094,7 @@ static switch_status_t buffer_vp9_packets(vpx_context_t *context, switch_frame_t
end:
#ifdef DEBUG_VP9
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "buffered %d bytes, buffer size: %" SWITCH_SIZE_T_FMT "\n", len, switch_buffer_inuse(context->vpx_packet_buffer));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "buffered %d bytes, buffer size: %" SWITCH_SIZE_T_FMT "\n", len, switch_buffer_inuse(context->vpx_packet_buffer));
#endif
return SWITCH_STATUS_SUCCESS;
@@ -1114,11 +1119,16 @@ static switch_status_t switch_vpx_decode(switch_codec_t *codec, switch_frame_t *
is_keyframe = IS_VP9_KEY_FRAME(*(unsigned char *)frame->data);
is_start = IS_VP9_START_PKT(*(unsigned char *)frame->data);
#ifdef DEBUG_VP9
if (is_keyframe) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "================Got a key frame!!!!========================\n");
switch_log_printf(SWITCH_CHANNEL_LOG, VPX_SWITCH_LOG_LEVEL, "================Got a key frame!!!!========================\n");
}
#endif
if (context->last_received_seq && context->last_received_seq + 1 != frame->seq) {
switch_log_printf(SWITCH_CHANNEL_LOG, VPX_SWITCH_LOG_LEVEL, "Packet loss detected last=%d got=%d lost=%d\n", context->last_received_seq, frame->seq, frame->seq - context->last_received_seq);
if (is_keyframe && context->vpx_packet_buffer) switch_buffer_zero(context->vpx_packet_buffer);
}
context->last_received_seq = frame->seq;
} else { // vp8
is_start = (*(unsigned char *)frame->data & 0x10);
is_keyframe = IS_VP8_KEY_FRAME((uint8_t *)frame->data);
@@ -1213,8 +1223,15 @@ static switch_status_t switch_vpx_decode(switch_codec_t *codec, switch_frame_t *
err = vpx_codec_decode(decoder, data, (unsigned int)len, NULL, 0);
if (err != VPX_CODEC_OK) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Error decoding %" SWITCH_SIZE_T_FMT " bytes, [%d:%s:%s]\n",
switch_log_printf(SWITCH_CHANNEL_LOG, VPX_SWITCH_LOG_LEVEL, "Error decoding %" SWITCH_SIZE_T_FMT " bytes, [%d:%s:%s]\n",
len, err, vpx_codec_error(decoder), vpx_codec_error_detail(decoder));
if (err == VPX_CODEC_MEM_ERROR) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "VPX MEM ERROR, resetting decoder!\n");
context->need_decoder_reset = 1;
}
switch_goto_status(SWITCH_STATUS_RESTART, end);
}
@@ -1264,6 +1281,12 @@ end:
switch_set_flag(frame, SFF_WAIT_KEY_FRAME);
}
if (frame->img && (codec->flags & SWITCH_CODEC_FLAG_VIDEO_PATCHING)) {
switch_img_free(&context->patch_img);
switch_img_copy(frame->img, &context->patch_img);
frame->img = context->patch_img;
}
return status;
}
@@ -1326,6 +1349,9 @@ static switch_status_t switch_vpx_destroy(switch_codec_t *codec)
vpx_context_t *context = (vpx_context_t *)codec->private_info;
if (context) {
switch_img_free(&context->patch_img);
if ((codec->flags & SWITCH_CODEC_FLAG_ENCODE)) {
vpx_codec_destroy(&context->encoder);
}