Merge remote branch 'origin/v1.2.stable' into v1.2.stable-em_management

This commit is contained in:
Moises Silva 2013-10-22 10:06:42 -04:00
commit 7a3cc7c9af
31 changed files with 832 additions and 201 deletions

View File

@ -3,7 +3,7 @@ AC_DEFUN([AX_COMPILER_VENDOR],
AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor,
[ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=unknown [ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=unknown
# note: don't check for gcc first since some other compilers define __GNUC__ # note: don't check for gcc first since some other compilers define __GNUC__
for ventest in intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do for ventest in intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ clang:__clang__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do
vencpp="defined("`echo $ventest | cut -d: -f2 | sed 's/,/) || defined(/g'`")" vencpp="defined("`echo $ventest | cut -d: -f2 | sed 's/,/) || defined(/g'`")"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[
#if !($vencpp) #if !($vencpp)

View File

@ -82,7 +82,6 @@ dialplans/mod_dialplan_xml
#endpoints/mod_dingaling #endpoints/mod_dingaling
#endpoints/mod_gsmopen #endpoints/mod_gsmopen
#endpoints/mod_h323 #endpoints/mod_h323
#endpoints/mod_html5
#endpoints/mod_khomp #endpoints/mod_khomp
endpoints/mod_loopback endpoints/mod_loopback
#endpoints/mod_opal #endpoints/mod_opal

View File

@ -1 +1 @@
1.2.11 1.2.14

View File

@ -3,10 +3,10 @@
# Must change all of the below together # Must change all of the below together
# For a release, set revision for that tagged release as well and uncomment # For a release, set revision for that tagged release as well and uncomment
AC_INIT([freeswitch], [1.2.13], bugs@freeswitch.org) AC_INIT([freeswitch], [1.2.14], bugs@freeswitch.org)
AC_SUBST(SWITCH_VERSION_MAJOR, [1]) AC_SUBST(SWITCH_VERSION_MAJOR, [1])
AC_SUBST(SWITCH_VERSION_MINOR, [2]) AC_SUBST(SWITCH_VERSION_MINOR, [2])
AC_SUBST(SWITCH_VERSION_MICRO, [13]) AC_SUBST(SWITCH_VERSION_MICRO, [14])
AC_SUBST(SWITCH_VERSION_REVISION, []) AC_SUBST(SWITCH_VERSION_REVISION, [])
AC_SUBST(SWITCH_VERSION_REVISION_HUMAN, []) AC_SUBST(SWITCH_VERSION_REVISION_HUMAN, [])
@ -167,11 +167,19 @@ SWITCH_AM_LDFLAGS="-lm"
#set SOLINK variable based on compiler and host #set SOLINK variable based on compiler and host
if test "x${ax_cv_c_compiler_vendor}" = "xsun" ; then if test "x${ax_cv_c_compiler_vendor}" = "xsun" ; then
SOLINK="-Bdynamic -dy -G" SOLINK="-Bdynamic -dy -G"
elif test "x${ax_cv_c_compiler_vendor}" = "xgnu" ; then elif test "x${ax_cv_c_compiler_vendor}" = "xclang" ; then
case "$host" in case "$host" in
*darwin12.*|*darwin11.*|*darwin10.*) *darwin*)
SOLINK="-dynamic -force-flat-namespace" SOLINK="-dynamic -force-flat-namespace"
;; ;;
*)
AC_ERROR([Please update configure.in with SOLINK values for your compiler])
;;
esac
elif test "x${ax_cv_c_compiler_vendor}" = "xgnu" ; then
case "$host" in
# older Xcode test for darwin, Xcode 4/5 use clang above
*darwin*) *darwin*)
SOLINK="-dynamic -bundle -force-flat-namespace" SOLINK="-dynamic -bundle -force-flat-namespace"
;; ;;
@ -185,7 +193,6 @@ elif test "x${ax_cv_c_compiler_vendor}" = "xgnu" ; then
else else
AC_ERROR([Please update configure.in with SOLINK values for your compiler]) AC_ERROR([Please update configure.in with SOLINK values for your compiler])
fi fi
# set DYNAMIC_LIB_EXTEN # set DYNAMIC_LIB_EXTEN
# we should really be using libtool so we don't need to do this # we should really be using libtool so we don't need to do this
case "$host" in case "$host" in
@ -716,6 +723,17 @@ if test x"$ac_cv_gcc_declaration_after_statement" = xyes; then
fi fi
CFLAGS="$saved_CFLAGS" CFLAGS="$saved_CFLAGS"
if test "x${ax_cv_c_compiler_vendor}" = "xclang" ; then
# Next check added for Xcode 5 and systems with clang 5 llvm 3.3 or above, extended offset must be off
AC_CACHE_CHECK([whether compiler supports -Wextended-offsetof], [ac_cv_clang_extended_offsetof], [
AC_TRY_COMPILE([],[return 0;],[ac_cv_clang_extended_offsetof=yes],[ac_cv_clang_extended_offsetof=no])
])
AC_MSG_RESULT($ac_cv_clang_extended_offsetof)
if test x"$ac_cv_clang_extended_offsetof" = xyes; then
APR_ADDTO(CFLAGS, -Wno-extended-offsetof)
fi
fi
# Tested and fixed lot of modules, but some are untested. Will be added back when the core team decide it ready # Tested and fixed lot of modules, but some are untested. Will be added back when the core team decide it ready
# Untested modules : mod_osp mod_soundtouch mod_sangoma_codec mod_dingaling mod_opal mod_skypopen mod_h323 mod_khomp # Untested modules : mod_osp mod_soundtouch mod_sangoma_codec mod_dingaling mod_opal mod_skypopen mod_h323 mod_khomp
# mod_unimrcp mod_cepstral mod_erlang_event mod_snmp mod_perl mod_java mod_managed # mod_unimrcp mod_cepstral mod_erlang_event mod_snmp mod_perl mod_java mod_managed

1
debian/.gitignore vendored
View File

@ -5,6 +5,7 @@
/files /files
/modules.conf /modules.conf
/modules_.conf /modules_.conf
/freeswitch-all.*
/freeswitch-autotools.install /freeswitch-autotools.install
/freeswitch-mod-*.install /freeswitch-mod-*.install
/freeswitch-conf-*.install /freeswitch-conf-*.install

106
debian/bootstrap.sh vendored
View File

@ -6,7 +6,7 @@ mod_dir="../src/mod"
conf_dir="../conf" conf_dir="../conf"
lang_dir="../conf/vanilla/lang" lang_dir="../conf/vanilla/lang"
fs_description="FreeSWITCH is a scalable open source cross-platform telephony platform designed to route and interconnect popular communication protocols using audio, video, text or any other form of media." fs_description="FreeSWITCH is a scalable open source cross-platform telephony platform designed to route and interconnect popular communication protocols using audio, video, text or any other form of media."
mod_build_depends="." mod_build_depends="." mod_depends="." mod_recommends="." mod_suggests="."
supported_distros="squeeze wheezy jessie sid" supported_distros="squeeze wheezy jessie sid"
avoid_mods=( avoid_mods=(
applications/mod_limit applications/mod_limit
@ -204,6 +204,32 @@ EOF
print_core_control () { print_core_control () {
cat <<EOF cat <<EOF
Package: freeswitch-all
Architecture: any
Provides: freeswitch, libfreeswitch1, freeswitch-doc, freeswitch-init
Replaces: freeswitch (<= \${binary:Version}),
libfreeswitch1 (<= \${binary:Version}),
freeswitch-doc (<= \${binary:Version}),
freeswitch-sysvinit (<= \${binary:Version}),
freeswitch-systemd (<= \${binary:Version})
Breaks: freeswitch (<= \${binary:Version}),
libfreeswitch1 (<= \${binary:Version}),
freeswitch-doc (<= \${binary:Version}),
freeswitch-sysvinit (<= \${binary:Version}),
freeswitch-systemd (<= \${binary:Version})
Depends: \${shlibs:Depends}, \${perl:Depends}, \${misc:Depends},
freeswitch-music-default (>= 1.0.8),
freeswitch-sounds-en-us-callie (>= 1.0.25) | freeswitch-sounds,
$(debian_wrap "${mod_depends}")
Recommends:
$(debian_wrap "${mod_recommends}")
Suggests: freeswitch-all-dbg,
$(debian_wrap "${mod_suggests}")
Description: Cross-Platform Scalable Multi-Protocol Soft Switch
$(debian_wrap "${fs_description}")
.
This package contains FreeSWITCH and all modules and extras.
Package: freeswitch Package: freeswitch
Architecture: any Architecture: any
Depends: \${shlibs:Depends}, \${perl:Depends}, \${misc:Depends}, Depends: \${shlibs:Depends}, \${perl:Depends}, \${misc:Depends},
@ -616,6 +642,16 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch
This is a metapackage which depends on all mod_say languages for This is a metapackage which depends on all mod_say languages for
FreeSWITCH. FreeSWITCH.
Package: freeswitch-all-dbg
Section: debug
Priority: extra
Architecture: any
Depends: \${misc:Depends}, freeswitch (= \${binary:Version})
Description: debugging symbols for FreeSWITCH
$(debian_wrap "${fs_description}")
.
This package contains debugging symbols for FreeSWITCH.
Package: freeswitch-dbg Package: freeswitch-dbg
Section: debug Section: debug
Priority: extra Priority: extra
@ -890,6 +926,7 @@ gencontrol_per_cat () {
geninstall_per_mod () { geninstall_per_mod () {
local f=freeswitch-${module_name//_/-}.install local f=freeswitch-${module_name//_/-}.install
(print_edit_warning; print_mod_install "$module_name") > $f (print_edit_warning; print_mod_install "$module_name") > $f
print_mod_install "$module_name" >> freeswitch-all.install
test -f $f.tmpl && cat $f.tmpl >> $f test -f $f.tmpl && cat $f.tmpl >> $f
} }
@ -912,6 +949,7 @@ genconf () {
local p=freeswitch-conf-${conf//_/-} local p=freeswitch-conf-${conf//_/-}
local f=$p.install local f=$p.install
(print_edit_warning; print_conf_install) > $f (print_edit_warning; print_conf_install) > $f
print_conf_install >> freeswitch-all.install
test -f $f.tmpl && cat $f.tmpl >> $f test -f $f.tmpl && cat $f.tmpl >> $f
local f=$p.lintian-overrides local f=$p.lintian-overrides
(print_edit_warning; print_conf_overrides "$p") > $f (print_edit_warning; print_conf_overrides "$p") > $f
@ -923,26 +961,50 @@ genlang () {
local p=freeswitch-lang-${lang//_/-} local p=freeswitch-lang-${lang//_/-}
local f=$p.install local f=$p.install
(print_edit_warning; print_lang_install) > $f (print_edit_warning; print_lang_install) > $f
print_lang_install >> freeswitch-all.install
test -f $f.tmpl && cat $f.tmpl >> $f test -f $f.tmpl && cat $f.tmpl >> $f
local f=$p.lintian-overrides local f=$p.lintian-overrides
(print_edit_warning; print_lang_overrides "$p") > $f (print_edit_warning; print_lang_overrides "$p") > $f
test -f $f.tmpl && cat $f.tmpl >> $f test -f $f.tmpl && cat $f.tmpl >> $f
} }
accumulate_build_depends () { accumulate_mod_deps () {
local x="" local x=""
# build-depends
if [ -n "$(eval echo \$build_depends_$codename)" ]; then if [ -n "$(eval echo \$build_depends_$codename)" ]; then
x="$(eval echo \$build_depends_$codename)" x="$(eval echo \$build_depends_$codename)"
else else x="${build_depends}"; fi
x="${build_depends}"
fi
if [ -n "$x" ]; then if [ -n "$x" ]; then
if [ ! "$mod_build_depends" = "." ]; then if [ ! "$mod_build_depends" = "." ]; then
mod_build_depends="${mod_build_depends}, ${x}" mod_build_depends="${mod_build_depends}, ${x}"
else else mod_build_depends="${x}"; fi; fi
mod_build_depends="${x}" # depends
fi if [ -n "$(eval echo \$depends_$codename)" ]; then
fi x="$(eval echo \$depends_$codename)"
else x="${depends}"; fi
x="$(echo "$x" | sed 's/, \?/\n/g' | grep -v '^freeswitch' | tr '\n' ',' | sed -e 's/,$//' -e 's/,/, /g')"
if [ -n "$x" ]; then
if [ ! "$mod_depends" = "." ]; then
mod_depends="${mod_depends}, ${x}"
else mod_depends="${x}"; fi; fi
# recommends
if [ -n "$(eval echo \$recommends_$codename)" ]; then
x="$(eval echo \$recommends_$codename)"
else x="${recommends}"; fi
x="$(echo "$x" | sed 's/, \?/\n/g' | grep -v '^freeswitch' | tr '\n' ',' | sed -e 's/,$//' -e 's/,/, /g')"
if [ -n "$x" ]; then
if [ ! "$mod_recommends" = "." ]; then
mod_recommends="${mod_recommends}, ${x}"
else mod_recommends="${x}"; fi; fi
# suggests
if [ -n "$(eval echo \$suggests_$codename)" ]; then
x="$(eval echo \$suggests_$codename)"
else x="${suggests}"; fi
x="$(echo "$x" | sed 's/, \?/\n/g' | grep -v '^freeswitch' | tr '\n' ',' | sed -e 's/,$//' -e 's/,/, /g')"
if [ -n "$x" ]; then
if [ ! "$mod_suggests" = "." ]; then
mod_suggests="${mod_suggests}, ${x}"
else mod_suggests="${x}"; fi; fi
} }
genmodctl_new_mod () { genmodctl_new_mod () {
@ -1108,10 +1170,13 @@ echo "Generating control-modules.gen as sanity check..." >&2
map_modules ':' 'genmodctl_cat' 'genmodctl_mod' \ map_modules ':' 'genmodctl_cat' 'genmodctl_mod' \
) > control-modules.gen ) > control-modules.gen
echo "Accumulating build dependencies from modules..." >&2 echo "Accumulating dependencies from modules..." >&2
map_modules 'mod_filter' '' 'accumulate_build_depends' map_modules 'mod_filter' '' 'accumulate_mod_deps'
echo "Generating debian/..." >&2 echo "Generating debian/..." >&2
> control > control
> freeswitch-all.install
(print_edit_warning; print_mod_overrides "freeswitch-all") \
> freeswitch-all.lintian-overrides
(print_edit_warning; print_source_control; print_core_control) >> control (print_edit_warning; print_source_control; print_core_control) >> control
echo "Generating debian/ (conf)..." >&2 echo "Generating debian/ (conf)..." >&2
(echo "### conf"; echo) >> control (echo "### conf"; echo) >> control
@ -1125,6 +1190,25 @@ print_edit_warning > modules_.conf
map_modules "mod_filter" \ map_modules "mod_filter" \
"gencontrol_per_cat genmodules_per_cat" \ "gencontrol_per_cat genmodules_per_cat" \
"gencontrol_per_mod geninstall_per_mod genoverrides_per_mod genmodules_per_mod" "gencontrol_per_mod geninstall_per_mod genoverrides_per_mod genmodules_per_mod"
echo "Generating debian/ (-all package)..." >&2
grep -e '^Package:' control | grep -v '^freeswitch-all$' | while xread l; do
m="${l#*: }"
f=$m.install
if [ -s $f ]; then
grep -v '^##\|^$' $f | while xread x; do
if ! grep -e "$x" freeswitch-all.install >/dev/null; then
printf '%s\n' "$x" >> freeswitch-all.install
fi
done
fi
done
for x in postinst postrm preinst prerm; do
cp -a freeswitch.$x freeswitch-all.$x
done
cp -a freeswitch-doc.docs freeswitch-all.docs
#cp -a freeswitch-systemd.freeswitch.service freeswitch-all.freeswitch.service
cp -a freeswitch-sysvinit.freeswitch.default freeswitch-all.freeswitch.default
cp -a freeswitch-sysvinit.freeswitch.init freeswitch-all.freeswitch.init
echo "Generating additional lintian overrides..." >&2 echo "Generating additional lintian overrides..." >&2
grep -e '^Package:' control | while xread l; do grep -e '^Package:' control | while xread l; do

View File

@ -229,7 +229,7 @@ Description: Voicemail detection
Module: applications/mod_voicemail Module: applications/mod_voicemail
Description: Voicemail Description: Voicemail
This module provides a voicemail system. This module provides a voicemail system.
Depends: mail-transport-agent Depends: ssmtp | mail-transport-agent
Module: applications/mod_voicemail_ivr Module: applications/mod_voicemail_ivr
Description: Voicemail IVR Description: Voicemail IVR
@ -395,10 +395,6 @@ Description: mod_h323
Adds mod_h323. Adds mod_h323.
Build-Depends: libopenh323-dev | libh323plus-dev, libpt-dev Build-Depends: libopenh323-dev | libh323plus-dev, libpt-dev
Module: endpoints/mod_html5
Description: HTML5 endpoint module
This module adds support for HTML5 technologies such as WebRTC.
Module: endpoints/mod_khomp Module: endpoints/mod_khomp
Description: mod_khomp Description: mod_khomp
Adds mod_khomp. Adds mod_khomp.

1
debian/copyright vendored
View File

@ -1765,7 +1765,6 @@ License: GPL-2+
Files: src/mod/endpoints/mod_rtmp/rtmp.c Files: src/mod/endpoints/mod_rtmp/rtmp.c
src/mod/endpoints/mod_rtmp/mod_rtmp.[ch] src/mod/endpoints/mod_rtmp/mod_rtmp.[ch]
src/mod/endpoints/mod_rtmp/rtmp_sig.c src/mod/endpoints/mod_rtmp/rtmp_sig.c
src/mod/endpoints/mod_html5/mod_html5.c
src/mod/endpoints/mod_rtmp/rtmp_tcp.c src/mod/endpoints/mod_rtmp/rtmp_tcp.c
Copyright: 2011-2012, Barracuda Networks Inc. Copyright: 2011-2012, Barracuda Networks Inc.
License: MPL-1.1 License: MPL-1.1

View File

@ -0,0 +1,2 @@
debian/tmp/usr/perl/freeswitch.pm /usr/lib/perl5
debian/tmp/usr/perl/freeswitch.so /usr/lib/perl5/auto/freeswitch

1
debian/rules vendored
View File

@ -104,6 +104,7 @@ override_dh_auto_install:
override_dh_installinit: override_dh_installinit:
dh_installinit -pfreeswitch-sysvinit --name=freeswitch dh_installinit -pfreeswitch-sysvinit --name=freeswitch
dh_installinit -pfreeswitch-all --name=freeswitch
debian-bootstrap: debian/.stamp-bootstrap debian-bootstrap: debian/.stamp-bootstrap
debian/.stamp-bootstrap: debian/.stamp-bootstrap:

View File

@ -28,26 +28,34 @@ rm -rf aclocal.m4 libtool.m4 ltsugar.m4 autom4te*.cache
$libtoolize --copy --automake $libtoolize --copy --automake
# #
# Build aclocal.m4 from libtool's libtool.m4 # find libtool.m4
# #
if [ -f libtool.m4 ]; then if [ ! -f libtool.m4 ]; then
ltfile=libtool.m4
else
ltpath=`dirname $libtoolize` ltpath=`dirname $libtoolize`
ltfile=${LIBTOOL_M4-`cd $ltpath/../share/aclocal ; pwd`/libtool.m4} ltfile=${LIBTOOL_M4-`cd $ltpath/../share/aclocal ; pwd`/libtool.m4}
if [ -f $ltfile ]; then
echo "libtool.m4 found at $ltfile"
cp $ltfile libtool.m4
else
echo "libtool.m4 not found - aborting!"
exit 1
fi
fi fi
echo "Incorporating $ltfile into aclocal.m4 ..."
#
# Build aclocal.m4 from libtool's m4 files
#
echo "dnl THIS FILE IS AUTOMATICALLY GENERATED BY buildconf.sh" > aclocal.m4 echo "dnl THIS FILE IS AUTOMATICALLY GENERATED BY buildconf.sh" > aclocal.m4
echo "dnl edits here will be lost" >> aclocal.m4 echo "dnl edits here will be lost" >> aclocal.m4
cat $ltfile >> aclocal.m4
if [ -f ltsugar.m4 ]; then for m4file in libtool.m4 ltsugar.m4 ltoptions.m4 ltversion.m4 lt~obsolete.m4
echo "Incorporating ltsugar.m4 into aclocal.m4 ..." do
cat ltsugar.m4 >> aclocal.m4 if [ -f $m4file ]; then
fi echo "Incorporating $m4file into aclocal.m4 ..."
cat $m4file >> aclocal.m4
# Clean up again rm -f $m4file
rm -f libtool.m4 ltsugar.m4 fi
done
cross_compile_warning="warning: AC_TRY_RUN called without default to allow cross compiling" cross_compile_warning="warning: AC_TRY_RUN called without default to allow cross compiling"

View File

@ -12,6 +12,7 @@ dnl
AC_INIT(Makefile.in) AC_INIT(Makefile.in)
AC_CONFIG_AUX_DIR(conftools) AC_CONFIG_AUX_DIR(conftools)
AC_CONFIG_MACRO_DIR(.)
dnl dnl
dnl Follow the GNU/Linux convention of odd number minor version for dnl Follow the GNU/Linux convention of odd number minor version for

View File

@ -80,6 +80,15 @@ esac
#set SOLINK variable based on compiler and host #set SOLINK variable based on compiler and host
if test "x${ax_cv_c_compiler_vendor}" = "xsun" ; then if test "x${ax_cv_c_compiler_vendor}" = "xsun" ; then
SOLINK="-Bdynamic -dy -G" SOLINK="-Bdynamic -dy -G"
elif test "x${ax_cv_c_compiler_vendor}" = "xclang" ; then
case "$host" in
*darwin*)
SOLINK="-dynamic -bundle -force-flat-namespace"
;;
*)
AC_ERROR([Please update configure.in with SOLINK values for your compiler])
;;
esac
elif test "x${ax_cv_c_compiler_vendor}" = "xgnu" ; then elif test "x${ax_cv_c_compiler_vendor}" = "xgnu" ; then
case "$host" in case "$host" in
*darwin*) *darwin*)

View File

@ -1 +1 @@
Fri Sep 20 00:39:20 CDT 2013 Tue Oct 8 23:05:34 CDT 2013

View File

@ -640,15 +640,17 @@ static void print_media(sdp_printer_t *p,
print_key(p, m->m_key); print_key(p, m->m_key);
for (rm = m->m_rtpmaps; rm; rm = rm->rm_next) { for (rm = m->m_rtpmaps; rm; rm = rm->rm_next) {
if (!rm->rm_predef || p->pr_all_rtpmaps) if (rm->rm_encoding && *rm->rm_encoding && (!rm->rm_predef || p->pr_all_rtpmaps)) {
sdp_printf(p, "a=rtpmap:%u %s/%lu%s%s" CRLF, sdp_printf(p, "a=rtpmap:%u %s/%lu%s%s" CRLF,
rm->rm_pt, rm->rm_encoding, rm->rm_rate, rm->rm_pt, rm->rm_encoding, rm->rm_rate,
rm->rm_params ? "/" : "", rm->rm_params ? "/" : "",
rm->rm_params ? rm->rm_params : ""); rm->rm_params ? rm->rm_params : "");
if (rm->rm_fmtp) }
if (rm->rm_fmtp) {
sdp_printf(p, "a=fmtp:%u %s" CRLF, sdp_printf(p, "a=fmtp:%u %s" CRLF,
rm->rm_pt, rm->rm_fmtp); rm->rm_pt, rm->rm_fmtp);
} }
}
if (!p->pr_mode_manual && !m->m_rejected && if (!p->pr_mode_manual && !m->m_rejected &&
(m->m_mode != (unsigned int)session_mode || p->pr_mode_always)) { (m->m_mode != (unsigned int)session_mode || p->pr_mode_always)) {

3
src/mod/.gitignore vendored
View File

@ -36,7 +36,6 @@
/codecs/mod_vp8/Makefile /codecs/mod_vp8/Makefile
/dialplans/mod_dialplan_asterisk/Makefile /dialplans/mod_dialplan_asterisk/Makefile
/dialplans/mod_dialplan_xml/Makefile /dialplans/mod_dialplan_xml/Makefile
/endpoints/mod_html5/mod_html5.log
/endpoints/mod_portaudio/Makefile /endpoints/mod_portaudio/Makefile
/endpoints/mod_portaudio/Makefile.in /endpoints/mod_portaudio/Makefile.in
/endpoints/mod_portaudio/mod_portaudio.log /endpoints/mod_portaudio/mod_portaudio.log
@ -49,8 +48,6 @@
/endpoints/mod_sofia/Makefile /endpoints/mod_sofia/Makefile
/endpoints/mod_sofia/Makefile.in /endpoints/mod_sofia/Makefile.in
/endpoints/mod_sofia/mod_sofia.log /endpoints/mod_sofia/mod_sofia.log
/endpoints/mod_html5/Makefile
/endpoints/mod_html5/Makefile.in
/event_handlers/mod_erlang_event/Makefile /event_handlers/mod_erlang_event/Makefile
/event_handlers/mod_event_socket/Makefile /event_handlers/mod_event_socket/Makefile
/formats/mod_native_file/Makefile /formats/mod_native_file/Makefile

View File

@ -1321,11 +1321,11 @@ SWITCH_STANDARD_API(echo_function)
SWITCH_STANDARD_API(stun_function) SWITCH_STANDARD_API(stun_function)
{ {
char *stun_ip = NULL; char *stun_ip = NULL;
char *src_ip = NULL;
switch_port_t stun_port = (switch_port_t) SWITCH_STUN_DEFAULT_PORT; switch_port_t stun_port = (switch_port_t) SWITCH_STUN_DEFAULT_PORT;
char *p; char *p;
char ip_buf[256] = ""; char ip_buf[256] = "";
char *ip = NULL; char *ip = NULL;
char *pip = NULL;
switch_port_t port = 0; switch_port_t port = 0;
switch_memory_pool_t *pool = NULL; switch_memory_pool_t *pool = NULL;
char *error = ""; char *error = "";
@ -1346,7 +1346,7 @@ SWITCH_STANDARD_API(stun_function)
switch_assert(stun_ip); switch_assert(stun_ip);
port = argv[1] ? atoi(argv[1]) : 0; src_ip = argv[1];
if ((p = strchr(stun_ip, ':'))) { if ((p = strchr(stun_ip, ':'))) {
int iport; int iport;
@ -1359,12 +1359,19 @@ SWITCH_STANDARD_API(stun_function)
p = stun_ip; p = stun_ip;
} }
if (p && (pip = strchr(p, ' '))) { if (!zstr(src_ip) && (p = strchr(src_ip, ':'))) {
*pip++ = '\0'; int iport;
*p++ = '\0';
iport = atoi(p);
if (iport > 0 && iport < 0xFFFF) {
port = (switch_port_t) iport;
}
} else if (!zstr(src_ip)) {
ip = src_ip;
} }
if (pip) { if ( !zstr(src_ip) ) {
switch_copy_string(ip_buf, pip, sizeof(ip_buf)); switch_copy_string(ip_buf, src_ip, sizeof(ip_buf));
} else { } else {
switch_find_local_ip(ip_buf, sizeof(ip_buf), NULL, AF_INET); switch_find_local_ip(ip_buf, sizeof(ip_buf), NULL, AF_INET);
} }
@ -6150,7 +6157,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
SWITCH_ADD_API(commands_api_interface, "sql_escape", "Escape a string to prevent sql injection", sql_escape, SQL_ESCAPE_SYNTAX); SWITCH_ADD_API(commands_api_interface, "sql_escape", "Escape a string to prevent sql injection", sql_escape, SQL_ESCAPE_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "status", "Show current status", status_function, ""); SWITCH_ADD_API(commands_api_interface, "status", "Show current status", status_function, "");
SWITCH_ADD_API(commands_api_interface, "strftime_tz", "Display formatted time of timezone", strftime_tz_api_function, "<timezone_name> [<epoch>|][format string]"); SWITCH_ADD_API(commands_api_interface, "strftime_tz", "Display formatted time of timezone", strftime_tz_api_function, "<timezone_name> [<epoch>|][format string]");
SWITCH_ADD_API(commands_api_interface, "stun", "Execute STUN lookup", stun_function, "<stun_server>[:port]"); SWITCH_ADD_API(commands_api_interface, "stun", "Execute STUN lookup", stun_function, "<stun_server>[:port] [<source_ip>[:<source_port]]");
SWITCH_ADD_API(commands_api_interface, "system", "Execute a system command", system_function, SYSTEM_SYNTAX); SWITCH_ADD_API(commands_api_interface, "system", "Execute a system command", system_function, SYSTEM_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "time_test", "Show time jitter", time_test_function, "<mss> [count]"); SWITCH_ADD_API(commands_api_interface, "time_test", "Show time jitter", time_test_function, "<mss> [count]");
SWITCH_ADD_API(commands_api_interface, "timer_test", "Exercise FS timer", timer_test_function, TIMER_TEST_SYNTAX); SWITCH_ADD_API(commands_api_interface, "timer_test", "Exercise FS timer", timer_test_function, TIMER_TEST_SYNTAX);

View File

@ -283,6 +283,17 @@ struct vid_helper {
int up; int up;
}; };
struct conference_obj;
/* Record Node */
typedef struct conference_record {
struct conference_obj *conference;
char *path;
switch_memory_pool_t *pool;
switch_bool_t autorec;
struct conference_record *next;
} conference_record_t;
/* Conference Object */ /* Conference Object */
typedef struct conference_obj { typedef struct conference_obj {
char *name; char *name;
@ -348,7 +359,7 @@ typedef struct conference_obj {
int pin_retries; int pin_retries;
int broadcast_chat_messages; int broadcast_chat_messages;
int comfort_noise_level; int comfort_noise_level;
int is_recording; int auto_recording;
int record_count; int record_count;
int video_running; int video_running;
int ivr_dtmf_timeout; int ivr_dtmf_timeout;
@ -381,6 +392,7 @@ typedef struct conference_obj {
cdr_event_mode_t cdr_event_mode; cdr_event_mode_t cdr_event_mode;
struct vid_helper vh[2]; struct vid_helper vh[2];
struct vid_helper mh; struct vid_helper mh;
conference_record_t *rec_node_head;
} conference_obj_t; } conference_obj_t;
/* Relationship with another member */ /* Relationship with another member */
@ -416,6 +428,7 @@ struct conference_member {
switch_codec_t write_codec; switch_codec_t write_codec;
char *rec_path; char *rec_path;
switch_time_t rec_time; switch_time_t rec_time;
conference_record_t *rec;
uint8_t *frame; uint8_t *frame;
uint8_t *last_frame; uint8_t *last_frame;
uint32_t frame_size; uint32_t frame_size;
@ -450,13 +463,6 @@ struct conference_member {
switch_thread_t *input_thread; switch_thread_t *input_thread;
}; };
/* Record Node */
typedef struct conference_record {
conference_obj_t *conference;
char *path;
switch_memory_pool_t *pool;
} conference_record_t;
typedef enum { typedef enum {
CONF_API_SUB_ARGS_SPLIT, CONF_API_SUB_ARGS_SPLIT,
CONF_API_SUB_MEMBER_TARGET, CONF_API_SUB_MEMBER_TARGET,
@ -524,7 +530,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
static switch_status_t chat_send(switch_event_t *message_event); static switch_status_t chat_send(switch_event_t *message_event);
static void launch_conference_record_thread(conference_obj_t *conference, char *path); static void launch_conference_record_thread(conference_obj_t *conference, char *path, switch_bool_t autorec);
static int launch_conference_video_bridge_thread(conference_member_t *member_a, conference_member_t *member_b); static int launch_conference_video_bridge_thread(conference_member_t *member_a, conference_member_t *member_b);
static void launch_conference_video_mirror_thread(conference_member_t *member_a); static void launch_conference_video_mirror_thread(conference_member_t *member_a);
@ -1211,7 +1217,7 @@ static conference_member_t *conference_member_get(conference_obj_t *conference,
} }
/* stop the specified recording */ /* stop the specified recording */
static switch_status_t conference_record_stop(conference_obj_t *conference, char *path) static switch_status_t conference_record_stop(conference_obj_t *conference, switch_stream_handle_t *stream, char *path)
{ {
conference_member_t *member = NULL; conference_member_t *member = NULL;
int count = 0; int count = 0;
@ -1220,10 +1226,21 @@ static switch_status_t conference_record_stop(conference_obj_t *conference, char
switch_mutex_lock(conference->member_mutex); switch_mutex_lock(conference->member_mutex);
for (member = conference->members; member; member = member->next) { for (member = conference->members; member; member = member->next) {
if (switch_test_flag(member, MFLAG_NOCHANNEL) && (!path || !strcmp(path, member->rec_path))) { if (switch_test_flag(member, MFLAG_NOCHANNEL) && (!path || !strcmp(path, member->rec_path))) {
if (member->rec && member->rec->autorec) {
stream->write_function(stream, "Stopped AUTO recording file %s (Auto Recording Now Disabled)\n", member->rec_path);
conference->auto_record = 0;
} else {
stream->write_function(stream, "Stopped recording file %s\n", member->rec_path);
}
switch_clear_flag_locked(member, MFLAG_RUNNING); switch_clear_flag_locked(member, MFLAG_RUNNING);
count++; count++;
} }
} }
conference->record_count -= count;
switch_mutex_unlock(conference->member_mutex); switch_mutex_unlock(conference->member_mutex);
return count; return count;
} }
@ -1965,7 +1982,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
globals.threads++; globals.threads++;
switch_mutex_unlock(globals.hash_mutex); switch_mutex_unlock(globals.hash_mutex);
conference->is_recording = 0; conference->auto_recording = 0;
conference->record_count = 0; conference->record_count = 0;
@ -2105,15 +2122,15 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
} }
/* Start recording if there's more than one participant. */ /* Start recording if there's more than one participant. */
if (conference->auto_record && !conference->is_recording && conference->count > 1) { if (conference->auto_record && !conference->auto_recording && conference->count > 1) {
conference->is_recording = 1; conference->auto_recording++;
conference->record_count++; conference->record_count++;
imember = conference->members; imember = conference->members;
if (imember) { if (imember) {
switch_channel_t *channel = switch_core_session_get_channel(imember->session); switch_channel_t *channel = switch_core_session_get_channel(imember->session);
char *rfile = switch_channel_expand_variables(channel, conference->auto_record); char *rfile = switch_channel_expand_variables(channel, conference->auto_record);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Auto recording file: %s\n", rfile); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Auto recording file: %s\n", rfile);
launch_conference_record_thread(conference, rfile); launch_conference_record_thread(conference, rfile, SWITCH_TRUE);
if (rfile != conference->auto_record) { if (rfile != conference->auto_record) {
conference->record_filename = switch_core_strdup(conference->pool, rfile); conference->record_filename = switch_core_strdup(conference->pool, rfile);
switch_safe_free(rfile); switch_safe_free(rfile);
@ -3877,7 +3894,7 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
int16_t *data_buf; int16_t *data_buf;
switch_file_handle_t fh = { 0 }; switch_file_handle_t fh = { 0 };
conference_member_t smember = { 0 }, *member; conference_member_t smember = { 0 }, *member;
conference_record_t *rec = (conference_record_t *) obj; conference_record_t *rp, *last = NULL, *rec = (conference_record_t *) obj;
conference_obj_t *conference = rec->conference; conference_obj_t *conference = rec->conference;
uint32_t samples = switch_samples_per_packet(conference->rate, conference->interval); uint32_t samples = switch_samples_per_packet(conference->rate, conference->interval);
uint32_t mux_used; uint32_t mux_used;
@ -3915,7 +3932,7 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
fh.samplerate = conference->rate; fh.samplerate = conference->rate;
member->id = next_member_id(); member->id = next_member_id();
member->pool = rec->pool; member->pool = rec->pool;
member->rec = rec;
member->frame_size = SWITCH_RECOMMENDED_BUFFER_SIZE; member->frame_size = SWITCH_RECOMMENDED_BUFFER_SIZE;
member->frame = switch_core_alloc(member->pool, member->frame_size); member->frame = switch_core_alloc(member->pool, member->frame_size);
member->mux_frame = switch_core_alloc(member->pool, member->frame_size); member->mux_frame = switch_core_alloc(member->pool, member->frame_size);
@ -4058,8 +4075,6 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
switch_mutex_unlock(member->audio_out_mutex); switch_mutex_unlock(member->audio_out_mutex);
} }
conference->is_recording = 0;
switch_safe_free(data_buf); switch_safe_free(data_buf);
switch_core_timer_destroy(&timer); switch_core_timer_destroy(&timer);
conference_del_member(conference, member); conference_del_member(conference, member);
@ -4078,6 +4093,23 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
switch_event_fire(&event); switch_event_fire(&event);
} }
if (rec->autorec && conference->auto_recording) {
conference->auto_recording--;
}
switch_mutex_lock(conference->flag_mutex);
for (rp = conference->rec_node_head; rp; rp = rp->next) {
if (rec == rp) {
if (last) {
last->next = rp->next;
} else {
conference->rec_node_head = rp->next;
}
}
}
switch_mutex_unlock(conference->flag_mutex);
if (rec->pool) { if (rec->pool) {
switch_memory_pool_t *pool = rec->pool; switch_memory_pool_t *pool = rec->pool;
rec = NULL; rec = NULL;
@ -6177,11 +6209,20 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc
static switch_status_t conf_api_sub_check_record(conference_obj_t *conference, switch_stream_handle_t *stream, int arc, char **argv) static switch_status_t conf_api_sub_check_record(conference_obj_t *conference, switch_stream_handle_t *stream, int arc, char **argv)
{ {
if (conference->is_recording) { conference_record_t *rec;
stream->write_function(stream, "Record file %s\n", conference->record_filename); int x = 0;
} else {
switch_mutex_lock(conference->flag_mutex);
for (rec = conference->rec_node_head; rec; rec = rec->next) {
stream->write_function(stream, "Record file %s%s%s\n", rec->path, rec->autorec ? " " : "", rec->autorec ? "(Auto)" : "");
x++;
}
if (!x) {
stream->write_function(stream, "Conference is not being recorded.\n"); stream->write_function(stream, "Conference is not being recorded.\n");
} }
switch_mutex_unlock(conference->flag_mutex);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -6190,19 +6231,20 @@ static switch_status_t conf_api_sub_record(conference_obj_t *conference, switch_
switch_assert(conference != NULL); switch_assert(conference != NULL);
switch_assert(stream != NULL); switch_assert(stream != NULL);
if (argc <= 2) if (argc <= 2) {
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
}
stream->write_function(stream, "Record file %s\n", argv[2]); stream->write_function(stream, "Record file %s\n", argv[2]);
conference->record_filename = switch_core_strdup(conference->pool, argv[2]); conference->record_filename = switch_core_strdup(conference->pool, argv[2]);
conference->record_count++; conference->record_count++;
launch_conference_record_thread(conference, argv[2]); launch_conference_record_thread(conference, argv[2], SWITCH_FALSE);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
static switch_status_t conf_api_sub_norecord(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv) static switch_status_t conf_api_sub_norecord(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv)
{ {
int all; int all, before = conference->record_count, ttl = 0;
switch_event_t *event; switch_event_t *event;
switch_assert(conference != NULL); switch_assert(conference != NULL);
@ -6212,15 +6254,10 @@ static switch_status_t conf_api_sub_norecord(conference_obj_t *conference, switc
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
all = (strcasecmp(argv[2], "all") == 0); all = (strcasecmp(argv[2], "all") == 0);
stream->write_function(stream, "Stop recording file %s\n", argv[2]);
if (!conference_record_stop(conference, all ? NULL : argv[2]) && !all) { if (!conference_record_stop(conference, stream, all ? NULL : argv[2]) && !all) {
stream->write_function(stream, "non-existant recording '%s'\n", argv[2]); stream->write_function(stream, "non-existant recording '%s'\n", argv[2]);
} else { } else {
if (all) {
conference->record_count = 0;
} else {
conference->record_count--;
}
if (test_eflag(conference, EFLAG_RECORD) && if (test_eflag(conference, EFLAG_RECORD) &&
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
conference_add_event_data(conference, event); conference_add_event_data(conference, event);
@ -6231,6 +6268,9 @@ static switch_status_t conf_api_sub_norecord(conference_obj_t *conference, switc
} }
} }
ttl = before - conference->record_count;
stream->write_function(stream, "Stopped recording %d file%s\n", ttl, ttl == 1 ? "" : "s");
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -6282,6 +6322,13 @@ static switch_status_t conf_api_sub_recording(conference_obj_t *conference, swit
switch_assert(conference != NULL); switch_assert(conference != NULL);
switch_assert(stream != NULL); switch_assert(stream != NULL);
if (argc > 2 && argc <= 3) {
if (strcasecmp(argv[2], "stop") == 0 || strcasecmp(argv[2], "check") == 0) {
argv[3] = "all";
argc++;
}
}
if (argc <= 3) { if (argc <= 3) {
/* It means that old syntax is used */ /* It means that old syntax is used */
return conf_api_sub_record(conference,stream,argc,argv); return conf_api_sub_record(conference,stream,argc,argv);
@ -8023,7 +8070,7 @@ static void launch_conference_video_mirror_thread(conference_member_t *member_a)
launch_thread_detached(conference_video_mirror_thread_run, pool, &conference->mh); launch_thread_detached(conference_video_mirror_thread_run, pool, &conference->mh);
} }
static void launch_conference_record_thread(conference_obj_t *conference, char *path) static void launch_conference_record_thread(conference_obj_t *conference, char *path, switch_bool_t autorec)
{ {
switch_thread_t *thread; switch_thread_t *thread;
switch_threadattr_t *thd_attr = NULL; switch_threadattr_t *thd_attr = NULL;
@ -8042,11 +8089,15 @@ static void launch_conference_record_thread(conference_obj_t *conference, char *
return; return;
} }
conference->is_recording = 1;
rec->conference = conference; rec->conference = conference;
rec->path = switch_core_strdup(pool, path); rec->path = switch_core_strdup(pool, path);
rec->pool = pool; rec->pool = pool;
rec->autorec = autorec;
switch_mutex_lock(conference->flag_mutex);
rec->next = conference->rec_node_head;
conference->rec_node_head = rec;
switch_mutex_unlock(conference->flag_mutex);
switch_threadattr_create(&thd_attr, rec->pool); switch_threadattr_create(&thd_attr, rec->pool);
switch_threadattr_detach_set(thd_attr, 1); switch_threadattr_detach_set(thd_attr, 1);

View File

@ -283,10 +283,17 @@ SWITCH_STANDARD_APP(clear_digit_action_function)
{ {
//switch_channel_t *channel = switch_core_session_get_channel(session); //switch_channel_t *channel = switch_core_session_get_channel(session);
switch_ivr_dmachine_t *dmachine; switch_ivr_dmachine_t *dmachine;
char *realm = switch_core_session_strdup(session, data); char *realm = NULL;
char *target_str; char *target_str;
switch_digit_action_target_t target = DIGIT_TARGET_SELF; switch_digit_action_target_t target = DIGIT_TARGET_SELF;
if (zstr((char *)data)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "clear_digit_action called with no args");
return;
}
realm = switch_core_session_strdup(session, data);
if ((target_str = strchr(realm, ','))) { if ((target_str = strchr(realm, ','))) {
*target_str++ = '\0'; *target_str++ = '\0';
target = str2target(target_str); target = str2target(target_str);
@ -4615,6 +4622,7 @@ static switch_status_t file_string_file_read(switch_file_handle_t *handle, void
return status; return status;
} }
static switch_status_t file_string_file_write(switch_file_handle_t *handle, void *data, size_t *len) static switch_status_t file_string_file_write(switch_file_handle_t *handle, void *data, size_t *len)
{ {
file_string_context_t *context = handle->private_info; file_string_context_t *context = handle->private_info;
@ -4633,10 +4641,101 @@ static switch_status_t file_string_file_write(switch_file_handle_t *handle, void
return status; return status;
} }
static switch_status_t file_url_file_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence)
{
switch_file_handle_t *fh = handle->private_info;
return switch_core_file_seek(fh, cur_sample, samples, whence);
}
static switch_status_t file_url_file_close(switch_file_handle_t *handle)
{
switch_file_handle_t *fh = handle->private_info;
if (switch_test_flag(fh, SWITCH_FILE_OPEN)) {
switch_core_file_close(fh);
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t file_url_file_read(switch_file_handle_t *handle, void *data, size_t *len)
{
switch_file_handle_t *fh = handle->private_info;
return switch_core_file_read(fh, data, len);
}
static switch_status_t file_url_file_open(switch_file_handle_t *handle, const char *path)
{
switch_file_handle_t *fh = switch_core_alloc(handle->memory_pool, sizeof(*fh));
switch_status_t status;
char *url_host;
char *url_path;
if (zstr(path)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NULL path\n");
return SWITCH_STATUS_FALSE;
}
/* parse and check host */
url_host = switch_core_strdup(handle->memory_pool, path);
if (!(url_path = strchr(url_host, '/'))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing path\n");
return SWITCH_STATUS_FALSE;
}
*url_path = '\0';
/* TODO allow this host */
if (!zstr(url_host) && strcasecmp(url_host, "localhost")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "not localhost\n");
return SWITCH_STATUS_FALSE;
}
/* decode and check path */
url_path++;
if (zstr(url_path)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "empty path\n");
return SWITCH_STATUS_FALSE;
}
if (strstr(url_path, "%2f") || strstr(url_path, "%2F")) {
/* don't allow %2f or %2F encoding (/) */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "encoded slash is not allowed\n");
return SWITCH_STATUS_FALSE;
}
url_path = switch_core_sprintf(handle->memory_pool, "/%s", url_path);
switch_url_decode(url_path);
/* TODO convert to native file separators? */
handle->private_info = fh;
status = switch_core_file_open(fh, url_path, handle->channels, handle->samplerate, handle->flags, NULL);
if (status == SWITCH_STATUS_SUCCESS) {
handle->samples = fh->samples;
handle->cur_samplerate = fh->samplerate;
handle->cur_channels = fh->channels;
handle->format = fh->format;
handle->sections = fh->sections;
handle->seekable = fh->seekable;
handle->speed = fh->speed;
handle->interval = fh->interval;
handle->max_samples = 0;
if (switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
switch_set_flag(handle, SWITCH_FILE_NATIVE);
} else {
switch_clear_flag(handle, SWITCH_FILE_NATIVE);
}
}
return status;
}
static switch_status_t file_url_file_write(switch_file_handle_t *handle, void *data, size_t *len)
{
switch_file_handle_t *fh = handle->private_info;
return switch_core_file_write(fh, data, len);
}
/* Registration */ /* Registration */
static char *file_string_supported_formats[SWITCH_MAX_CODECS] = { 0 }; static char *file_string_supported_formats[SWITCH_MAX_CODECS] = { 0 };
static char *file_url_supported_formats[SWITCH_MAX_CODECS] = { 0 };
/* /FILE STRING INTERFACE */ /* /FILE STRING INTERFACE */
@ -5504,6 +5603,17 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
file_interface->file_write = file_string_file_write; file_interface->file_write = file_string_file_write;
file_interface->file_seek = file_string_file_seek; file_interface->file_seek = file_string_file_seek;
file_url_supported_formats[0] = "file";
file_interface = (switch_file_interface_t *) switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
file_interface->interface_name = modname;
file_interface->extens = file_url_supported_formats;
file_interface->file_open = file_url_file_open;
file_interface->file_close = file_url_file_close;
file_interface->file_read = file_url_file_read;
file_interface->file_write = file_url_file_write;
file_interface->file_seek = file_url_file_seek;
error_endpoint_interface = (switch_endpoint_interface_t *) switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE); error_endpoint_interface = (switch_endpoint_interface_t *) switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
error_endpoint_interface->interface_name = "error"; error_endpoint_interface->interface_name = "error";

View File

@ -3078,10 +3078,17 @@ static switch_status_t deliver_vm(vm_profile_t *profile,
vm_cc_num = switch_separate_string(vm_cc_dup, ',', vm_cc_list, (sizeof(vm_cc_list) / sizeof(vm_cc_list[0]))); vm_cc_num = switch_separate_string(vm_cc_dup, ',', vm_cc_list, (sizeof(vm_cc_list) / sizeof(vm_cc_list[0])));
for (vm_cc_i=0; vm_cc_i<vm_cc_num; vm_cc_i++) { for (vm_cc_i=0; vm_cc_i<vm_cc_num; vm_cc_i++) {
char *cmd, *val;
const char *vm_cc_current = vm_cc_list[vm_cc_i]; const char *vm_cc_current = vm_cc_list[vm_cc_i];
char *cmd = switch_mprintf("%s %s %s '%s' %s@%s %s",
val = strdup(caller_id_name);
switch_url_decode(val);
cmd = switch_mprintf("%s %s %s '%s' %s@%s %s",
vm_cc_current, file_path, caller_id_number, vm_cc_current, file_path, caller_id_number,
caller_id_name, myid, domain_name, read_flags); val, myid, domain_name, read_flags);
free(val);
if (voicemail_inject(cmd, session) == SWITCH_STATUS_SUCCESS) { if (voicemail_inject(cmd, session) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Sent Carbon Copy to %s\n", vm_cc_current); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Sent Carbon Copy to %s\n", vm_cc_current);

View File

@ -21,12 +21,12 @@ $(MODNAME).lo: $(FLITE_A)
$(FLITE_DIR): $(FLITE_DIR):
$(GETLIB) $(FLITE)-current.tar.bz2 $(GETLIB) $(FLITE)-current.tar.bz2
$(FLITE_BUILDDIR)/Makefile: $(FLITE_DIR) $(FLITE_BUILDDIR)/.stamp-configure: $(FLITE_DIR)
mkdir -p $(FLITE_BUILDDIR) mkdir -p $(FLITE_BUILDDIR)
cd $(FLITE_BUILDDIR) && $(DEFAULT_VARS) $(FLITE_DIR)/configure $(DEFAULT_ARGS) --srcdir=$(FLITE_DIR) --with-audio=none --with-pic --disable-shared cd $(FLITE_BUILDDIR) && $(DEFAULT_VARS) $(FLITE_DIR)/configure $(DEFAULT_ARGS) --srcdir=$(FLITE_DIR) --with-audio=none --with-pic --disable-shared
$(TOUCH_TARGET) test -f Makefile && touch $@
$(FLITE_A): $(FLITE_DIR) $(FLITE_BUILDDIR)/Makefile $(FLITE_A): $(FLITE_DIR) $(FLITE_BUILDDIR)/.stamp-configure
cd $(FLITE_BUILDDIR) && $(MAKE) -j1 cd $(FLITE_BUILDDIR) && $(MAKE) -j1
test -d $(FLITE_LIBDIR) || mkdir $(FLITE_LIBDIR) test -d $(FLITE_LIBDIR) || mkdir $(FLITE_LIBDIR)
TARGET_OS=`grep TARGET_OS $(FLITE_BUILDDIR)/config/config | sed "s/^.*= //"` ;\ TARGET_OS=`grep TARGET_OS $(FLITE_BUILDDIR)/config/config | sed "s/^.*= //"` ;\

View File

@ -15,11 +15,11 @@ install: $(LICSERVER) $(VALIDATOR) $(MOD)
$(LICSERVER) $(VALIDATOR) $(MOD): $(G729INSTALLER) $(LICSERVER) $(VALIDATOR) $(MOD): $(G729INSTALLER)
$(SHELL) $(G729INSTALLER) $(bindir) $(moddir) nobanner $(SHELL) $(G729INSTALLER) $(bindir) $(moddir) nobanner
$(ECHO) @echo
$(ECHO) @echo
$(ECHO) Now you can activate your license by running $(MAKE) mod_com_g729-activate @echo Now you can activate your license by running $(MAKE) mod_com_g729-activate
$(ECHO) @echo
$(ECHO) @echo
$(G729INSTALLER): $(G729INSTALLER):
rm -f $(top_srcdir)/libs/fsg729-*-installer* rm -f $(top_srcdir)/libs/fsg729-*-installer*

View File

@ -709,6 +709,10 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
} }
tech_pvt->write_frame = (switch_frame_t *) pop; tech_pvt->write_frame = (switch_frame_t *) pop;
switch_clear_flag(tech_pvt->write_frame, SFF_RAW_RTP);
tech_pvt->write_frame->timestamp = 0;
tech_pvt->write_frame->codec = &tech_pvt->read_codec; tech_pvt->write_frame->codec = &tech_pvt->read_codec;
*frame = tech_pvt->write_frame; *frame = tech_pvt->write_frame;
tech_pvt->packet_count++; tech_pvt->packet_count++;

View File

@ -718,6 +718,8 @@ struct private_object {
sofia_private_t *sofia_private; sofia_private_t *sofia_private;
uint8_t flags[TFLAG_MAX]; uint8_t flags[TFLAG_MAX];
switch_payload_t agreed_pt; switch_payload_t agreed_pt;
int channels;
int adv_channels;
switch_payload_t audio_recv_pt; switch_payload_t audio_recv_pt;
switch_payload_t video_recv_pt; switch_payload_t video_recv_pt;
switch_core_session_t *session; switch_core_session_t *session;

View File

@ -39,6 +39,15 @@
switch_cache_db_handle_t *_sofia_glue_get_db_handle(sofia_profile_t *profile, const char *file, const char *func, int line); switch_cache_db_handle_t *_sofia_glue_get_db_handle(sofia_profile_t *profile, const char *file, const char *func, int line);
#define sofia_glue_get_db_handle(_p) _sofia_glue_get_db_handle(_p, __FILE__, __SWITCH_FUNC__, __LINE__) #define sofia_glue_get_db_handle(_p) _sofia_glue_get_db_handle(_p, __FILE__, __SWITCH_FUNC__, __LINE__)
static int get_channels(const switch_codec_implementation_t *imp)
{
if (!strcasecmp(imp->iananame, "opus")) {
return 2; /* IKR???*/
}
return imp->number_of_channels;
}
void sofia_glue_set_udptl_image_sdp(private_object_t *tech_pvt, switch_t38_options_t *t38_options, int insist) void sofia_glue_set_udptl_image_sdp(private_object_t *tech_pvt, switch_t38_options_t *t38_options, int insist)
{ {
char buf[2048] = ""; char buf[2048] = "";
@ -308,8 +317,15 @@ static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen,
} }
if (tech_pvt->ianacodes[i] > 95 || verbose_sdp) { if (tech_pvt->ianacodes[i] > 95 || verbose_sdp) {
int channels = get_channels(imp);
if (channels > 1) {
switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d %s/%d/%d\n", tech_pvt->ianacodes[i], imp->iananame, rate, channels);
} else {
switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d %s/%d\n", tech_pvt->ianacodes[i], imp->iananame, rate); switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d %s/%d\n", tech_pvt->ianacodes[i], imp->iananame, rate);
} }
}
if (fmtp) { if (fmtp) {
switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=fmtp:%d %s\n", tech_pvt->ianacodes[i], fmtp); switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=fmtp:%d %s\n", tech_pvt->ianacodes[i], fmtp);
@ -530,7 +546,15 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\n"); switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\n");
rate = tech_pvt->rm_rate; rate = tech_pvt->rm_rate;
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\n", tech_pvt->agreed_pt, tech_pvt->rm_encoding, rate);
if (tech_pvt->adv_channels > 1) {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d/%d\n",
tech_pvt->agreed_pt, tech_pvt->rm_encoding, rate, tech_pvt->adv_channels);
} else {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\n",
tech_pvt->agreed_pt, tech_pvt->rm_encoding, rate);
}
if (fmtp_out) { if (fmtp_out) {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\n", tech_pvt->agreed_pt, fmtp_out); switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\n", tech_pvt->agreed_pt, fmtp_out);
} }
@ -735,6 +759,7 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch
const switch_codec_implementation_t *imp = tech_pvt->codecs[i]; const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
char *fmtp = NULL; char *fmtp = NULL;
uint32_t ianacode = tech_pvt->ianacodes[i]; uint32_t ianacode = tech_pvt->ianacodes[i];
int channels = 1;
if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) { if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
continue; continue;
@ -751,9 +776,15 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch
rate = imp->samples_per_second; rate = imp->samples_per_second;
} }
channels = get_channels(imp);
if (channels > 1) {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d/%d\n", ianacode, imp->iananame,
imp->samples_per_second, channels);
} else {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\n", ianacode, imp->iananame, switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\n", ianacode, imp->iananame,
imp->samples_per_second); imp->samples_per_second);
}
if (!zstr(ov_fmtp)) { if (!zstr(ov_fmtp)) {
fmtp = (char *) ov_fmtp; fmtp = (char *) ov_fmtp;
@ -4414,7 +4445,6 @@ int sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly)
switch_channel_stop_broadcast(b_channel); switch_channel_stop_broadcast(b_channel);
switch_channel_wait_for_flag(b_channel, CF_BROADCAST, SWITCH_FALSE, 5000, NULL); switch_channel_wait_for_flag(b_channel, CF_BROADCAST, SWITCH_FALSE, 5000, NULL);
} }
switch_core_session_rwunlock(b_session);
} }
sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD); sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
@ -5316,6 +5346,23 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp); switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
tech_pvt->audio_recv_pt = (switch_payload_t)map->rm_pt; tech_pvt->audio_recv_pt = (switch_payload_t)map->rm_pt;
if (!strcasecmp((char *) map->rm_encoding, "opus")) {
if (tech_pvt->channels == 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Invalid SDP for opus. Don't ask.. but it needs a /2\n");
tech_pvt->adv_channels = 1;
} else {
tech_pvt->adv_channels = 2; /* IKR ???*/
}
if (!zstr((char *) map->rm_fmtp) && switch_stristr("stereo=1", (char *) map->rm_fmtp)) {
tech_pvt->channels = 2;
} else {
tech_pvt->channels = 1;
}
} else {
tech_pvt->adv_channels = tech_pvt->channels;
}
if (!switch_true(mirror) && if (!switch_true(mirror) &&
switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND &&
(!sofia_test_flag(tech_pvt, TFLAG_REINVITE) || sofia_test_pflag(tech_pvt->profile, PFLAG_RENEG_ON_REINVITE))) { (!sofia_test_flag(tech_pvt, TFLAG_REINVITE) || sofia_test_pflag(tech_pvt->profile, PFLAG_RENEG_ON_REINVITE))) {

View File

@ -128,6 +128,8 @@ struct rayo_call {
switch_time_t idle_start_time; switch_time_t idle_start_time;
/** 1 if joined to call, 2 if joined to mixer */ /** 1 if joined to call, 2 if joined to mixer */
int joined; int joined;
/** pending join */
iks *pending_join_request;
/** ID of joined party TODO this will be many mixers / calls */ /** ID of joined party TODO this will be many mixers / calls */
const char *joined_id; const char *joined_id;
/** set if response needs to be sent to IQ request */ /** set if response needs to be sent to IQ request */
@ -937,6 +939,15 @@ static void rayo_call_cleanup(struct rayo_actor *actor)
RAYO_SEND_MESSAGE_DUP(actor, rayo_call_get_dcp_jid(call), revent); RAYO_SEND_MESSAGE_DUP(actor, rayo_call_get_dcp_jid(call), revent);
} }
/* lost the race: pending join failed... send IQ result to client now. */
if (call->pending_join_request) {
iks *request = call->pending_join_request;
iks *result = iks_new_error_detailed(request, STANZA_ERROR_ITEM_NOT_FOUND, "call ended");
call->pending_join_request = NULL;
RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result);
iks_delete(call->pending_join_request);
}
iks_delete(revent); iks_delete(revent);
switch_event_destroy(&event); switch_event_destroy(&event);
} }
@ -1068,6 +1079,7 @@ static struct rayo_call *rayo_call_init(struct rayo_call *call, switch_memory_po
call->joined = 0; call->joined = 0;
call->joined_id = NULL; call->joined_id = NULL;
call->ringing_sent = 0; call->ringing_sent = 0;
call->pending_join_request = NULL;
switch_core_hash_init(&call->pcps, pool); switch_core_hash_init(&call->pcps, pool);
switch_safe_free(call_jid); switch_safe_free(call_jid);
@ -1292,6 +1304,17 @@ static struct rayo_peer_server *rayo_peer_server_create(const char *jid)
return rserver; return rserver;
} }
/**
* Check if message sender has control of offered call.
* @param call the Rayo call
* @param msg the message
* @return 1 if sender has call control, 0 if sender does not have control
*/
static int has_call_control(struct rayo_call *call, struct rayo_message *msg)
{
return (!strcmp(rayo_call_get_dcp_jid(call), msg->from_jid) || is_internal_message(msg) || is_admin_client_message(msg));
}
/** /**
* Check if message sender has control of offered call. Take control if nobody else does. * Check if message sender has control of offered call. Take control if nobody else does.
* @param call the Rayo call * @param call the Rayo call
@ -1299,7 +1322,7 @@ static struct rayo_peer_server *rayo_peer_server_create(const char *jid)
* @param msg the message * @param msg the message
* @return 1 if sender has call control * @return 1 if sender has call control
*/ */
static int has_call_control(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg) static int take_call_control(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg)
{ {
int control = 0; int control = 0;
@ -1313,7 +1336,7 @@ static int has_call_control(struct rayo_call *call, switch_core_session_t *sessi
control = 1; control = 1;
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_INFO, "%s has control of call\n", rayo_call_get_dcp_jid(call)); switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_INFO, "%s has control of call\n", rayo_call_get_dcp_jid(call));
} }
} else if (!strcmp(rayo_call_get_dcp_jid(call), msg->from_jid) || is_internal_message(msg) || is_admin_client_message(msg)) { } else if (has_call_control(call, msg)) {
control = 1; control = 1;
} }
@ -1358,7 +1381,7 @@ static iks *rayo_call_command_ok(struct rayo_call *call, switch_core_session_t *
if (bad) { if (bad) {
response = iks_new_error(node, STANZA_ERROR_BAD_REQUEST); response = iks_new_error(node, STANZA_ERROR_BAD_REQUEST);
} else if (!has_call_control(call, session, msg)) { } else if (!take_call_control(call, session, msg)) {
response = iks_new_error(node, STANZA_ERROR_CONFLICT); response = iks_new_error(node, STANZA_ERROR_CONFLICT);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, %s conflict\n", msg->from_jid, RAYO_JID(call)); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, %s conflict\n", msg->from_jid, RAYO_JID(call));
} }
@ -1711,13 +1734,14 @@ static iks *on_rayo_hangup(struct rayo_actor *call, struct rayo_message *msg, vo
* Join calls together * Join calls together
* @param call the call that joins * @param call the call that joins
* @param session the session * @param session the session
* @param node the join request * @param msg the rayo join message
* @param call_uri to join * @param call_uri to join
* @param media mode (direct/bridge) * @param media mode (direct/bridge)
* @return the response * @return the response
*/ */
static iks *join_call(struct rayo_call *call, switch_core_session_t *session, iks *node, const char *call_uri, const char *media) static iks *join_call(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg, const char *call_uri, const char *media)
{ {
iks *node = msg->payload;
iks *response = NULL; iks *response = NULL;
/* take call out of media path if media = "direct" */ /* take call out of media path if media = "direct" */
const char *bypass = !strcmp("direct", media) ? "true" : "false"; const char *bypass = !strcmp("direct", media) ? "true" : "false";
@ -1727,6 +1751,9 @@ static iks *join_call(struct rayo_call *call, switch_core_session_t *session, ik
if (!b_call) { if (!b_call) {
/* not a rayo call */ /* not a rayo call */
response = iks_new_error_detailed(node, STANZA_ERROR_SERVICE_UNAVAILABLE, "b-leg is not a rayo call"); response = iks_new_error_detailed(node, STANZA_ERROR_SERVICE_UNAVAILABLE, "b-leg is not a rayo call");
} else if (!has_call_control(b_call, msg)) {
/* not allowed to join to this call */
response = iks_new_error(node, STANZA_ERROR_NOT_ALLOWED);
} else if (b_call->joined) { } else if (b_call->joined) {
/* don't support multiple joined calls */ /* don't support multiple joined calls */
response = iks_new_error_detailed(node, STANZA_ERROR_CONFLICT, "multiple joined calls not supported"); response = iks_new_error_detailed(node, STANZA_ERROR_CONFLICT, "multiple joined calls not supported");
@ -1737,10 +1764,13 @@ static iks *join_call(struct rayo_call *call, switch_core_session_t *session, ik
if (switch_false(bypass)) { if (switch_false(bypass)) {
switch_channel_pre_answer(switch_core_session_get_channel(session)); switch_channel_pre_answer(switch_core_session_get_channel(session));
} }
if (switch_ivr_uuid_bridge(rayo_call_get_uuid(call), rayo_call_get_uuid(b_call)) == SWITCH_STATUS_SUCCESS) { call->pending_join_request = iks_copy(node);
response = iks_new_iq_result(node); if (switch_ivr_uuid_bridge(rayo_call_get_uuid(call), rayo_call_get_uuid(b_call)) != SWITCH_STATUS_SUCCESS) {
} else { iks *request = call->pending_join_request;
response = iks_new_error_detailed(node, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to bridge call"); iks *result = iks_new_error_detailed(request, STANZA_ERROR_ITEM_NOT_FOUND, "failed to bridge call");
call->pending_join_request = NULL;
RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result);
iks_delete(call->pending_join_request);
} }
RAYO_UNLOCK(b_call); RAYO_UNLOCK(b_call);
} }
@ -1749,40 +1779,99 @@ static iks *join_call(struct rayo_call *call, switch_core_session_t *session, ik
/** /**
* Execute command on session's conference * Execute command on session's conference
* @param session to execute conference API on
* @param conf_name of conference
* @param command to send to conference
* @param node IQ request
* @return response on failure
*/ */
static void exec_conference_api(switch_core_session_t *session, const char *conf_name, const char *command) static iks *exec_conference_api(switch_core_session_t *session, const char *conf_name, const char *command, iks *node)
{ {
iks *response = NULL;
switch_stream_handle_t stream = { 0 }; switch_stream_handle_t stream = { 0 };
const char *conf_member_id = switch_channel_get_variable(switch_core_session_get_channel(session), "conference_member_id"); const char *conf_member_id = switch_channel_get_variable(switch_core_session_get_channel(session), "conference_member_id");
SWITCH_STANDARD_STREAM(stream); SWITCH_STANDARD_STREAM(stream);
switch_api_execute("conference", switch_core_session_sprintf(session, "%s %s %s", conf_name, command, conf_member_id), NULL, &stream); switch_api_execute("conference", switch_core_session_sprintf(session, "%s %s %s", conf_name, command, conf_member_id), NULL, &stream);
if (!zstr(stream.data) && strncmp("OK", stream.data, 2)) {
response = iks_new_error_detailed_printf(node, STANZA_ERROR_SERVICE_UNAVAILABLE, "%s", stream.data);
}
switch_safe_free(stream.data); switch_safe_free(stream.data);
return response;
}
/**
* Execute conference app on session
* @param session to execute conference API on
* @param command to send to conference (conference name, member flags, etc)
* @param node IQ request
* @return response on failure
*/
static iks *exec_conference_app(switch_core_session_t *session, const char *command, iks *node)
{
iks *response = NULL;
switch_event_t *execute_event = NULL;
switch_channel_t *channel = switch_core_session_get_channel(session);
/* conference requires local media on channel */
if (!switch_channel_media_ready(channel) && switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
/* shit */
response = iks_new_error_detailed(node, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to start media");
return response;
}
/* send execute conference event to session */
if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute");
switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", "conference");
switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", command);
//switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event_uuid", uuid);
switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event-lock", "true");
if (!switch_channel_test_flag(channel, CF_PROXY_MODE)) {
switch_channel_set_flag(channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA);
}
if (switch_core_session_queue_private_event(session, &execute_event, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) {
response = iks_new_error_detailed(node, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to join mixer (queue event failed)");
if (execute_event) {
switch_event_destroy(&execute_event);
}
return response;
}
}
return response;
} }
/** /**
* Join call to a mixer * Join call to a mixer
* @param call the call that joins * @param call the call that joins
* @param session the session * @param session the session
* @param node the join request * @param msg the join request
* @param mixer_name the mixer to join * @param mixer_name the mixer to join
* @param direction the media direction * @param direction the media direction
* @return the response * @return the response
*/ */
static iks *join_mixer(struct rayo_call *call, switch_core_session_t *session, iks *node, const char *mixer_name, const char *direction) static iks *join_mixer(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg, const char *mixer_name, const char *direction)
{ {
iks *node = msg->payload;
iks *response = NULL; iks *response = NULL;
if (call->joined_id) { if (call->joined_id) {
/* adjust join conference params */ /* adjust join conference params */
if (!strcmp("duplex", direction)) { if (!strcmp("duplex", direction)) {
exec_conference_api(session, mixer_name, "unmute"); if ((response = exec_conference_api(session, mixer_name, "unmute", node)) ||
exec_conference_api(session, mixer_name, "undeaf"); (response = exec_conference_api(session, mixer_name, "undeaf", node))) {
return response;
}
} else if (!strcmp("recv", direction)) { } else if (!strcmp("recv", direction)) {
exec_conference_api(session, mixer_name, "mute"); if ((response = exec_conference_api(session, mixer_name, "mute", node)) ||
exec_conference_api(session, mixer_name, "undeaf"); (response = exec_conference_api(session, mixer_name, "undeaf", node))) {
return response;
}
} else { } else {
exec_conference_api(session, mixer_name, "unmute"); if ((response = exec_conference_api(session, mixer_name, "unmute", node)) ||
exec_conference_api(session, mixer_name, "deaf"); (response = exec_conference_api(session, mixer_name, "deaf", node))) {
return response;
}
} }
response = iks_new_iq_result(node); response = iks_new_iq_result(node);
} else { } else {
@ -1793,10 +1882,12 @@ static iks *join_mixer(struct rayo_call *call, switch_core_session_t *session, i
} else if (!strcmp("recv", direction)) { } else if (!strcmp("recv", direction)) {
conf_args = switch_core_session_sprintf(session, "%s+flags{mute}", conf_args); conf_args = switch_core_session_sprintf(session, "%s+flags{mute}", conf_args);
} }
if (switch_core_session_execute_application_async(session, "conference", conf_args) == SWITCH_STATUS_SUCCESS) {
response = iks_new_iq_result(node); call->pending_join_request = iks_copy(node);
} else { response = exec_conference_app(session, conf_args, node);
response = iks_new_error_detailed(node, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed execute conference app"); if (response) {
iks_delete(call->pending_join_request);
call->pending_join_request = NULL;
} }
} }
return response; return response;
@ -1806,14 +1897,13 @@ static iks *join_mixer(struct rayo_call *call, switch_core_session_t *session, i
* Handle <iq><join> request * Handle <iq><join> request
* @param call the Rayo call * @param call the Rayo call
* @param session the session * @param session the session
* @param node the <iq> node * @param msg the rayo join message
*/ */
static iks *on_rayo_join(struct rayo_actor *call, struct rayo_message *msg, void *session_data) static iks *on_rayo_join(struct rayo_actor *call, struct rayo_message *msg, void *session_data)
{ {
iks *node = msg->payload;
switch_core_session_t *session = (switch_core_session_t *)session_data; switch_core_session_t *session = (switch_core_session_t *)session_data;
iks *response = NULL; iks *response = NULL;
iks *join = iks_find(node, "join"); iks *join = iks_find(msg->payload, "join");
const char *join_id; const char *join_id;
const char *mixer_name; const char *mixer_name;
const char *call_uri; const char *call_uri;
@ -1821,7 +1911,7 @@ static iks *on_rayo_join(struct rayo_actor *call, struct rayo_message *msg, void
/* validate input attributes */ /* validate input attributes */
if (!VALIDATE_RAYO_JOIN(join)) { if (!VALIDATE_RAYO_JOIN(join)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Bad join attrib\n"); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Bad join attrib\n");
response = iks_new_error(node, STANZA_ERROR_BAD_REQUEST); response = iks_new_error(msg->payload, STANZA_ERROR_BAD_REQUEST);
goto done; goto done;
} }
mixer_name = iks_find_attrib(join, "mixer-name"); mixer_name = iks_find_attrib(join, "mixer-name");
@ -1835,29 +1925,35 @@ static iks *on_rayo_join(struct rayo_actor *call, struct rayo_message *msg, void
/* can't join both mixer and call */ /* can't join both mixer and call */
if (!zstr(mixer_name) && !zstr(call_uri)) { if (!zstr(mixer_name) && !zstr(call_uri)) {
response = iks_new_error_detailed(node, STANZA_ERROR_BAD_REQUEST, "mixer-name and call-uri are mutually exclusive"); response = iks_new_error_detailed(msg->payload, STANZA_ERROR_BAD_REQUEST, "mixer-name and call-uri are mutually exclusive");
goto done; goto done;
} }
/* need to join *something* */ /* need to join *something* */
if (zstr(mixer_name) && zstr(call_uri)) { if (zstr(mixer_name) && zstr(call_uri)) {
response = iks_new_error_detailed(node, STANZA_ERROR_BAD_REQUEST, "mixer-name or call-uri is required"); response = iks_new_error_detailed(msg->payload, STANZA_ERROR_BAD_REQUEST, "mixer-name or call-uri is required");
goto done; goto done;
} }
if ((RAYO_CALL(call)->joined == JOINED_CALL) || if ((RAYO_CALL(call)->joined == JOINED_CALL) ||
(RAYO_CALL(call)->joined == JOINED_MIXER && strcmp(RAYO_CALL(call)->joined_id, join_id))) { (RAYO_CALL(call)->joined == JOINED_MIXER && strcmp(RAYO_CALL(call)->joined_id, join_id))) {
/* already joined */ /* already joined */
response = iks_new_error_detailed(node, STANZA_ERROR_CONFLICT, "call is already joined"); response = iks_new_error_detailed(msg->payload, STANZA_ERROR_CONFLICT, "call is already joined");
goto done;
}
if (RAYO_CALL(call)->pending_join_request) {
/* don't allow concurrent join requests */
response = iks_new_error_detailed(msg->payload, STANZA_ERROR_UNEXPECTED_REQUEST, "(un)join request is pending");
goto done; goto done;
} }
if (!zstr(mixer_name)) { if (!zstr(mixer_name)) {
/* join conference */ /* join conference */
response = join_mixer(RAYO_CALL(call), session, node, mixer_name, iks_find_attrib(join, "direction")); response = join_mixer(RAYO_CALL(call), session, msg, mixer_name, iks_find_attrib(join, "direction"));
} else { } else {
/* bridge calls */ /* bridge calls */
response = join_call(RAYO_CALL(call), session, node, call_uri, iks_find_attrib(join, "media")); response = join_call(RAYO_CALL(call), session, msg, call_uri, iks_find_attrib(join, "media"));
} }
done: done:
@ -1868,20 +1964,18 @@ done:
* unjoin call to a bridge * unjoin call to a bridge
* @param call the call that unjoined * @param call the call that unjoined
* @param session the session * @param session the session
* @param node the unjoin request * @param msg the unjoin request
* @param call_uri the b-leg xmpp URI * @param call_uri the b-leg xmpp URI
* @return the response * @return the response
*/ */
static iks *unjoin_call(struct rayo_call *call, switch_core_session_t *session, iks *node, const char *call_uri) static iks *unjoin_call(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg, const char *call_uri)
{ {
iks *node = msg->payload;
iks *response = NULL; iks *response = NULL;
const char *bleg_uuid = switch_channel_get_variable(switch_core_session_get_channel(session), SWITCH_BRIDGE_UUID_VARIABLE);
const char *bleg_uri = switch_core_session_sprintf(session, "xmpp:%s@%s", bleg_uuid ? bleg_uuid : "", RAYO_JID(globals.server));
/* bleg must match call_uri */ if (!strcmp(call_uri, call->joined_id)) {
if (!zstr(bleg_uri) && !strcmp(bleg_uri, call_uri)) {
/* unbridge call */ /* unbridge call */
response = iks_new_iq_result(node); call->pending_join_request = iks_copy(node);
switch_ivr_park_session(session); switch_ivr_park_session(session);
} else { } else {
/* not bridged or wrong b-leg URI */ /* not bridged or wrong b-leg URI */
@ -1895,15 +1989,16 @@ static iks *unjoin_call(struct rayo_call *call, switch_core_session_t *session,
* unjoin call to a mixer * unjoin call to a mixer
* @param call the call that unjoined * @param call the call that unjoined
* @param session the session * @param session the session
* @param node the unjoin request * @param msg the unjoin request
* @param mixer_name the mixer name * @param mixer_name the mixer name
* @return the response * @return the response
*/ */
static iks *unjoin_mixer(struct rayo_call *call, switch_core_session_t *session, iks *node, const char *mixer_name) static iks *unjoin_mixer(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg, const char *mixer_name)
{ {
switch_channel_t *channel = switch_core_session_get_channel(session); switch_channel_t *channel = switch_core_session_get_channel(session);
const char *conf_member_id = switch_channel_get_variable(channel, "conference_member_id"); const char *conf_member_id = switch_channel_get_variable(channel, "conference_member_id");
const char *conf_name = switch_channel_get_variable(channel, "conference_name"); const char *conf_name = switch_channel_get_variable(channel, "conference_name");
iks *node = msg->payload;
iks *response = NULL; iks *response = NULL;
/* not conferenced, or wrong conference */ /* not conferenced, or wrong conference */
@ -1916,11 +2011,12 @@ static iks *unjoin_mixer(struct rayo_call *call, switch_core_session_t *session,
goto done; goto done;
} }
/* kick the member */
response = exec_conference_api(session, mixer_name, "hup", node);
if (!response) {
/* ack command */ /* ack command */
response = iks_new_iq_result(node); response = iks_new_iq_result(node);
}
/* kick the member */
exec_conference_api(session, mixer_name, "hup");
done: done:
@ -1935,31 +2031,39 @@ done:
*/ */
static iks *on_rayo_unjoin(struct rayo_actor *call, struct rayo_message *msg, void *session_data) static iks *on_rayo_unjoin(struct rayo_actor *call, struct rayo_message *msg, void *session_data)
{ {
iks *node = msg->payload;
switch_core_session_t *session = (switch_core_session_t *)session_data; switch_core_session_t *session = (switch_core_session_t *)session_data;
iks *response = NULL; iks *response = NULL;
iks *unjoin = iks_find(node, "unjoin"); iks *unjoin = iks_find(msg->payload, "unjoin");
const char *call_uri = iks_find_attrib(unjoin, "call-uri"); const char *call_uri = iks_find_attrib(unjoin, "call-uri");
const char *mixer_name = iks_find_attrib(unjoin, "mixer-name"); const char *mixer_name = iks_find_attrib(unjoin, "mixer-name");
if (!zstr(call_uri) && !zstr(mixer_name)) { if (!zstr(call_uri) && !zstr(mixer_name)) {
response = iks_new_error(node, STANZA_ERROR_BAD_REQUEST); response = iks_new_error(msg->payload, STANZA_ERROR_BAD_REQUEST);
} else if (RAYO_CALL(call)->pending_join_request) {
/* need to let pending request finish first */
response = iks_new_error_detailed(msg->payload, STANZA_ERROR_UNEXPECTED_REQUEST, "(un)join request is pending");
} else if (!RAYO_CALL(call)->joined) { } else if (!RAYO_CALL(call)->joined) {
/* not joined to anything */ /* not joined to anything */
response = iks_new_error(node, STANZA_ERROR_SERVICE_UNAVAILABLE); response = iks_new_error_detailed(msg->payload, STANZA_ERROR_SERVICE_UNAVAILABLE, "not joined to anything");
} else if (RAYO_CALL(call)->joined == JOINED_MIXER && !zstr(call_uri)) {
/* joined to mixer, not call */
response = iks_new_error_detailed(msg->payload, STANZA_ERROR_SERVICE_UNAVAILABLE, "not joined to call");
} else if (RAYO_CALL(call)->joined == JOINED_CALL && !zstr(mixer_name)) {
/* joined to call, not mixer */
response = iks_new_error_detailed(msg->payload, STANZA_ERROR_SERVICE_UNAVAILABLE, "not joined to mixer");
} else if (!zstr(call_uri)) { } else if (!zstr(call_uri)) {
response = unjoin_call(RAYO_CALL(call), session, node, call_uri); response = unjoin_call(RAYO_CALL(call), session, msg, call_uri);
} else if (!zstr(mixer_name)) { } else if (!zstr(mixer_name)) {
response = unjoin_mixer(RAYO_CALL(call), session, node, mixer_name); response = unjoin_mixer(RAYO_CALL(call), session, msg, mixer_name);
} else { } else {
/* unjoin everything */ /* unjoin everything */
if (RAYO_CALL(call)->joined == JOINED_MIXER) { if (RAYO_CALL(call)->joined == JOINED_MIXER) {
response = unjoin_mixer(RAYO_CALL(call), session, node, RAYO_CALL(call)->joined_id); response = unjoin_mixer(RAYO_CALL(call), session, msg, RAYO_CALL(call)->joined_id);
} else if (RAYO_CALL(call)->joined == JOINED_CALL) { } else if (RAYO_CALL(call)->joined == JOINED_CALL) {
response = unjoin_call(RAYO_CALL(call), session, node, RAYO_CALL(call)->joined_id); response = unjoin_call(RAYO_CALL(call), session, msg, RAYO_CALL(call)->joined_id);
} else { } else {
/* shouldn't happen */ /* shouldn't happen */
response = iks_new_error(node, STANZA_ERROR_INTERNAL_SERVER_ERROR); response = iks_new_error(msg->payload, STANZA_ERROR_INTERNAL_SERVER_ERROR);
} }
} }
@ -2501,6 +2605,15 @@ static void on_mixer_add_member_event(struct rayo_mixer *mixer, switch_event_t *
call->joined = JOINED_MIXER; call->joined = JOINED_MIXER;
call->joined_id = switch_core_strdup(RAYO_POOL(call), rayo_mixer_get_name(mixer)); call->joined_id = switch_core_strdup(RAYO_POOL(call), rayo_mixer_get_name(mixer));
/* send IQ result to client now. */
if (call->pending_join_request) {
iks *request = call->pending_join_request;
iks *result = iks_new_iq_result(request);
call->pending_join_request = NULL;
RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result);
iks_delete(request);
}
/* send mixer joined event to member DCP */ /* send mixer joined event to member DCP */
add_member_event = iks_new_presence("joined", RAYO_NS, RAYO_JID(call), call->dcp_jid); add_member_event = iks_new_presence("joined", RAYO_NS, RAYO_JID(call), call->dcp_jid);
x = iks_find(add_member_event, "joined"); x = iks_find(add_member_event, "joined");
@ -2661,31 +2774,53 @@ static void on_call_bridge_event(struct rayo_client *rclient, switch_event_t *ev
struct rayo_call *b_call; struct rayo_call *b_call;
if (call) { if (call) {
/* send A-leg event */ iks *revent;
iks *revent = iks_new_presence("joined", RAYO_NS, iks *joined;
switch_event_get_header(event, "variable_rayo_call_jid"),
switch_event_get_header(event, "variable_rayo_dcp_jid"));
iks *joined = iks_find(revent, "joined");
iks_insert_attrib_printf(joined, "call-uri", "xmpp:%s@%s", b_uuid, RAYO_JID(globals.server));
call->joined = JOINED_CALL; call->joined = JOINED_CALL;
call->joined_id = switch_core_strdup(RAYO_POOL(call), b_uuid); call->joined_id = switch_core_sprintf(RAYO_POOL(call), "xmpp:%s@%s", b_uuid, RAYO_JID(globals.server));
RAYO_SEND_MESSAGE(call, RAYO_JID(rclient), revent); /* send IQ result to client now. */
if (call->pending_join_request) {
iks *request = call->pending_join_request;
iks *result = iks_new_iq_result(request);
call->pending_join_request = NULL;
RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result);
iks_delete(request);
}
/* send B-leg event */
b_call = RAYO_CALL_LOCATE_BY_ID(b_uuid); b_call = RAYO_CALL_LOCATE_BY_ID(b_uuid);
if (b_call) { if (b_call) {
b_call->joined = JOINED_CALL;
b_call->joined_id = switch_core_sprintf(RAYO_POOL(b_call), "xmpp:%s@s", a_uuid, RAYO_JID(globals.server));
/* send IQ result to client now. */
if (b_call->pending_join_request) {
iks *request = b_call->pending_join_request;
iks *result = iks_new_iq_result(request);
b_call->pending_join_request = NULL;
RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result);
iks_delete(request);
}
/* send B-leg event */
revent = iks_new_presence("joined", RAYO_NS, RAYO_JID(b_call), rayo_call_get_dcp_jid(b_call)); revent = iks_new_presence("joined", RAYO_NS, RAYO_JID(b_call), rayo_call_get_dcp_jid(b_call));
joined = iks_find(revent, "joined"); joined = iks_find(revent, "joined");
iks_insert_attrib_printf(joined, "call-uri", "xmpp:%s@%s", a_uuid, RAYO_JID(globals.server)); iks_insert_attrib_printf(joined, "call-uri", "xmpp:%s@%s", a_uuid, RAYO_JID(globals.server));
b_call->joined = JOINED_CALL;
b_call->joined_id = switch_core_strdup(RAYO_POOL(b_call), a_uuid);
RAYO_SEND_MESSAGE(b_call, rayo_call_get_dcp_jid(b_call), revent); RAYO_SEND_MESSAGE(b_call, rayo_call_get_dcp_jid(b_call), revent);
RAYO_UNLOCK(b_call); RAYO_UNLOCK(b_call);
} }
/* send A-leg event */
revent = iks_new_presence("joined", RAYO_NS,
switch_event_get_header(event, "variable_rayo_call_jid"),
switch_event_get_header(event, "variable_rayo_dcp_jid"));
joined = iks_find(revent, "joined");
iks_insert_attrib_printf(joined, "call-uri", "xmpp:%s@%s", b_uuid, RAYO_JID(globals.server));
RAYO_SEND_MESSAGE(call, RAYO_JID(rclient), revent);
RAYO_UNLOCK(call); RAYO_UNLOCK(call);
} }
} }
@ -2703,33 +2838,85 @@ static void on_call_unbridge_event(struct rayo_client *rclient, switch_event_t *
struct rayo_call *b_call; struct rayo_call *b_call;
if (call) { if (call) {
/* send A-leg event */ iks *revent;
iks *revent = iks_new_presence("unjoined", RAYO_NS, iks *joined;
switch_event_get_header(event, "variable_rayo_call_jid"),
switch_event_get_header(event, "variable_rayo_dcp_jid"));
iks *joined = iks_find(revent, "unjoined");
iks_insert_attrib_printf(joined, "call-uri", "xmpp:%s@%s", b_uuid, RAYO_JID(globals.server));
RAYO_SEND_MESSAGE(call, RAYO_JID(rclient), revent);
call->joined = 0; call->joined = 0;
call->joined_id = NULL; call->joined_id = NULL;
/* send B-leg event */ /* send IQ result to client now. */
if (call->pending_join_request) {
iks *request = call->pending_join_request;
iks *result = iks_new_iq_result(request);
call->pending_join_request = NULL;
RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result);
iks_delete(request);
}
b_call = RAYO_CALL_LOCATE_BY_ID(b_uuid); b_call = RAYO_CALL_LOCATE_BY_ID(b_uuid);
if (b_call) { if (b_call) {
b_call->joined = 0;
b_call->joined_id = NULL;
/* send IQ result to client now. */
if (b_call->pending_join_request) {
iks *request = b_call->pending_join_request;
iks *result = iks_new_iq_result(request);
b_call->pending_join_request = NULL;
RAYO_SEND_REPLY(b_call, iks_find_attrib_soft(request, "from"), result);
iks_delete(request);
}
/* send B-leg event */
revent = iks_new_presence("unjoined", RAYO_NS, RAYO_JID(b_call), rayo_call_get_dcp_jid(b_call)); revent = iks_new_presence("unjoined", RAYO_NS, RAYO_JID(b_call), rayo_call_get_dcp_jid(b_call));
joined = iks_find(revent, "unjoined"); joined = iks_find(revent, "unjoined");
iks_insert_attrib_printf(joined, "call-uri", "xmpp:%s@%s", a_uuid, RAYO_JID(globals.server)); iks_insert_attrib_printf(joined, "call-uri", "xmpp:%s@%s", a_uuid, RAYO_JID(globals.server));
RAYO_SEND_MESSAGE(b_call, rayo_call_get_dcp_jid(b_call), revent); RAYO_SEND_MESSAGE(b_call, rayo_call_get_dcp_jid(b_call), revent);
b_call->joined = 0;
b_call->joined_id = NULL;
RAYO_UNLOCK(b_call); RAYO_UNLOCK(b_call);
} }
/* send A-leg event */
revent = iks_new_presence("unjoined", RAYO_NS,
switch_event_get_header(event, "variable_rayo_call_jid"),
switch_event_get_header(event, "variable_rayo_dcp_jid"));
joined = iks_find(revent, "unjoined");
iks_insert_attrib_printf(joined, "call-uri", "xmpp:%s@%s", b_uuid, RAYO_JID(globals.server));
RAYO_SEND_MESSAGE(call, RAYO_JID(rclient), revent);
RAYO_UNLOCK(call); RAYO_UNLOCK(call);
} }
} }
/**
* Handle call execute application event
* @param rclient the Rayo client
* @param event the execute event
*/
static void on_call_execute_event(struct rayo_client *rclient, switch_event_t *event)
{
struct rayo_call *call = RAYO_CALL_LOCATE_BY_ID(switch_event_get_header(event, "Unique-ID"));
if (call) {
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(RAYO_ID(call)), SWITCH_LOG_DEBUG, "Application %s execute\n", switch_event_get_header(event, "Application"));
RAYO_UNLOCK(call);
}
}
/**
* Handle call execute application complete event
* @param rclient the Rayo client
* @param event the execute complete event
*/
static void on_call_execute_complete_event(struct rayo_client *rclient, switch_event_t *event)
{
struct rayo_call *call = RAYO_CALL_LOCATE_BY_ID(switch_event_get_header(event, "Unique-ID"));
if (call) {
const char *app = switch_event_get_header(event, "Application");
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(RAYO_ID(call)), SWITCH_LOG_DEBUG, "Application %s execute complete: %s \n",
app,
switch_event_get_header(event, "Application-Response"));
RAYO_UNLOCK(call);
}
}
/** /**
* Handle events to deliver to client connection * Handle events to deliver to client connection
@ -2756,6 +2943,12 @@ static void rayo_client_handle_event(struct rayo_client *rclient, switch_event_t
case SWITCH_EVENT_CHANNEL_UNBRIDGE: case SWITCH_EVENT_CHANNEL_UNBRIDGE:
on_call_unbridge_event(rclient, event); on_call_unbridge_event(rclient, event);
break; break;
case SWITCH_EVENT_CHANNEL_EXECUTE:
on_call_execute_event(rclient, event);
break;
case SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE:
on_call_execute_complete_event(rclient, event);
break;
default: default:
/* don't care */ /* don't care */
break; break;
@ -2881,7 +3074,9 @@ static switch_status_t rayo_call_on_read_frame(switch_core_session_t *session, s
switch_time_t idle_start = call->idle_start_time; switch_time_t idle_start = call->idle_start_time;
int idle_duration_ms = (now - idle_start) / 1000; int idle_duration_ms = (now - idle_start) / 1000;
/* detect idle session (rayo-client has stopped controlling call) and terminate call */ /* detect idle session (rayo-client has stopped controlling call) and terminate call */
if (!rayo_call_is_joined(call) && idle_duration_ms > globals.max_idle_ms) { if (rayo_call_is_joined(call)) {
call->idle_start_time = now;
} else if (idle_duration_ms > globals.max_idle_ms) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Ending abandoned call. idle_duration_ms = %i ms\n", idle_duration_ms); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Ending abandoned call. idle_duration_ms = %i ms\n", idle_duration_ms);
switch_channel_hangup(channel, RAYO_CAUSE_HANGUP); switch_channel_hangup(channel, RAYO_CAUSE_HANGUP);
} }
@ -2974,8 +3169,9 @@ done:
if (ok) { if (ok) {
switch_channel_set_variable(channel, "hangup_after_bridge", "false"); switch_channel_set_variable(channel, "hangup_after_bridge", "false");
switch_channel_set_variable(channel, "transfer_after_bridge", "false"); switch_channel_set_variable(channel, "transfer_after_bridge", "");
switch_channel_set_variable(channel, "park_after_bridge", "true"); switch_channel_set_variable(channel, "park_after_bridge", "true");
switch_channel_set_variable(channel, "hold_hangup_xfer_exten", "foo"); /* Icky hack to prevent unjoin of call on hold from hanging up b-leg. park_after_bridge will take precedence over the transfer_after_bridge variable that gets set by this var */
switch_channel_set_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE, "-1"); /* required so that output mixing works */ switch_channel_set_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE, "-1"); /* required so that output mixing works */
switch_core_event_hook_add_read_frame(session, rayo_call_on_read_frame); switch_core_event_hook_add_read_frame(session, rayo_call_on_read_frame);
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
@ -3828,6 +4024,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_rayo_load)
switch_event_bind(modname, SWITCH_EVENT_CHANNEL_ANSWER, NULL, route_call_event, NULL); switch_event_bind(modname, SWITCH_EVENT_CHANNEL_ANSWER, NULL, route_call_event, NULL);
switch_event_bind(modname, SWITCH_EVENT_CHANNEL_BRIDGE, NULL, route_call_event, NULL); switch_event_bind(modname, SWITCH_EVENT_CHANNEL_BRIDGE, NULL, route_call_event, NULL);
switch_event_bind(modname, SWITCH_EVENT_CHANNEL_UNBRIDGE, NULL, route_call_event, NULL); switch_event_bind(modname, SWITCH_EVENT_CHANNEL_UNBRIDGE, NULL, route_call_event, NULL);
switch_event_bind(modname, SWITCH_EVENT_CHANNEL_EXECUTE, NULL, route_call_event, NULL);
switch_event_bind(modname, SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE, NULL, route_call_event, NULL);
switch_event_bind(modname, SWITCH_EVENT_CHANNEL_DESTROY, NULL, on_call_end_event, NULL); switch_event_bind(modname, SWITCH_EVENT_CHANNEL_DESTROY, NULL, on_call_end_event, NULL);

View File

@ -692,11 +692,14 @@ static int get_file_from_macro(struct ssml_parser *parsed_data, char *to_say)
static int get_file_from_voice(struct ssml_parser *parsed_data, char *to_say) static int get_file_from_voice(struct ssml_parser *parsed_data, char *to_say)
{ {
struct ssml_node *cur_node = parsed_data->cur_node; struct ssml_node *cur_node = parsed_data->cur_node;
if (cur_node->tts_voice) {
char *file = switch_core_sprintf(parsed_data->pool, "%s%s", cur_node->tts_voice->prefix, to_say); char *file = switch_core_sprintf(parsed_data->pool, "%s%s", cur_node->tts_voice->prefix, to_say);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding <%s>: \"%s\"\n", cur_node->tag_name, file); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding <%s>: \"%s\"\n", cur_node->tag_name, file);
parsed_data->files[parsed_data->num_files].name = file; parsed_data->files[parsed_data->num_files].name = file;
parsed_data->files[parsed_data->num_files++].prefix = NULL; parsed_data->files[parsed_data->num_files++].prefix = NULL;
return 1; return 1;
}
return 0;
} }
/** /**
@ -708,7 +711,7 @@ static int process_cdata_tts(struct ssml_parser *parsed_data, char *data, size_t
if (!len) { if (!len) {
return IKS_OK; return IKS_OK;
} }
if (cur_node && cur_node->tts_voice && parsed_data->num_files < parsed_data->max_files) { if (cur_node && parsed_data->num_files < parsed_data->max_files) {
int i = 0; int i = 0;
int empty = 1; int empty = 1;
char *to_say; char *to_say;
@ -728,7 +731,9 @@ static int process_cdata_tts(struct ssml_parser *parsed_data, char *data, size_t
to_say[len] = '\0'; to_say[len] = '\0';
if (!cur_node->say_macro || !get_file_from_macro(parsed_data, to_say)) { if (!cur_node->say_macro || !get_file_from_macro(parsed_data, to_say)) {
/* use voice instead */ /* use voice instead */
get_file_from_voice(parsed_data, to_say); if (!get_file_from_voice(parsed_data, to_say)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No TTS voices available to render text!\n");
}
} }
free(to_say); free(to_say);
return IKS_OK; return IKS_OK;

View File

@ -2600,7 +2600,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_destroy(void)
switch_nat_shutdown(); switch_nat_shutdown();
} }
switch_xml_destroy(); switch_xml_destroy();
switch_core_session_uninit();
switch_console_shutdown(); switch_console_shutdown();
switch_channel_global_uninit(); switch_channel_global_uninit();
@ -2610,6 +2609,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_destroy(void)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Finalizing Shutdown.\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Finalizing Shutdown.\n");
switch_log_shutdown(); switch_log_shutdown();
switch_core_session_uninit();
switch_core_unset_variables(); switch_core_unset_variables();
switch_core_memory_stop(); switch_core_memory_stop();

View File

@ -2480,8 +2480,8 @@ void switch_core_session_init(switch_memory_pool_t *pool)
switch_queue_create(&session_manager.thread_queue, 100000, session_manager.memory_pool); switch_queue_create(&session_manager.thread_queue, 100000, session_manager.memory_pool);
switch_threadattr_create(&thd_attr, session_manager.memory_pool); switch_threadattr_create(&thd_attr, session_manager.memory_pool);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
switch_thread_create(&session_manager.manager_thread, thd_attr, switch_core_session_thread_pool_manager, NULL, session_manager.memory_pool);
session_manager.ready = 1; session_manager.ready = 1;
switch_thread_create(&session_manager.manager_thread, thd_attr, switch_core_session_thread_pool_manager, NULL, session_manager.memory_pool);
} }
} }
@ -2491,16 +2491,17 @@ void switch_core_session_uninit(void)
int sanity = 100; int sanity = 100;
switch_status_t st = SWITCH_STATUS_FALSE; switch_status_t st = SWITCH_STATUS_FALSE;
switch_core_hash_destroy(&session_manager.session_table);
session_manager.ready = 0; session_manager.ready = 0;
wake_queue();
switch_thread_join(&st, session_manager.manager_thread);
while(session_manager.running && --sanity > 0) { while(session_manager.running && --sanity > 0) {
switch_queue_interrupt_all(session_manager.thread_queue); switch_queue_interrupt_all(session_manager.thread_queue);
switch_yield(100000); switch_yield(100000);
} }
switch_thread_join(&st, session_manager.manager_thread);
switch_core_hash_destroy(&session_manager.session_table);
} }
SWITCH_DECLARE(switch_app_log_t *) switch_core_session_get_app_log(switch_core_session_t *session) SWITCH_DECLARE(switch_app_log_t *) switch_core_session_get_app_log(switch_core_session_t *session)

View File

@ -2777,7 +2777,7 @@ static void do_2833(switch_rtp_t *rtp_session, switch_core_session_t *session)
rtp_session->dtmf_data.out_digit_dur = rdigit->duration; rtp_session->dtmf_data.out_digit_dur = rdigit->duration;
rtp_session->dtmf_data.out_digit = rdigit->digit; rtp_session->dtmf_data.out_digit = rdigit->digit;
rtp_session->dtmf_data.out_digit_packet[0] = (unsigned char) switch_char_to_rfc2833(rdigit->digit); rtp_session->dtmf_data.out_digit_packet[0] = (unsigned char) switch_char_to_rfc2833(rdigit->digit);
rtp_session->dtmf_data.out_digit_packet[1] = 7; rtp_session->dtmf_data.out_digit_packet[1] = 13;
rtp_session->dtmf_data.out_digit_packet[2] = (unsigned char) (rtp_session->dtmf_data.out_digit_sub_sofar >> 8); rtp_session->dtmf_data.out_digit_packet[2] = (unsigned char) (rtp_session->dtmf_data.out_digit_sub_sofar >> 8);
rtp_session->dtmf_data.out_digit_packet[3] = (unsigned char) rtp_session->dtmf_data.out_digit_sub_sofar; rtp_session->dtmf_data.out_digit_packet[3] = (unsigned char) rtp_session->dtmf_data.out_digit_sub_sofar;

82
support-d/gl Executable file
View File

@ -0,0 +1,82 @@
#!/usr/bin/perl
my $pager = `which less` || `which more`;
my $tmpdir = "/tmp/FSJIRA";
system("mkdir -p $tmpdir");
my $cmd = "git log " . join(" ", @ARGV);
open(CMD, "$cmd |");
open(PAGER, "|$pager");
select PAGER;
while(my $line = <CMD>) {
print $line;
if ($line =~ /([A-Z]+\-[0-9]+)/) {
my $bug = $1;
my $txt = bugtxt($bug);
if ($txt) {
print "=" x 80 . "\n";
print $txt;
print "=" x 80 . "\n";
}
}
}
close(CMD);
close(PAGER);
sub catfile($) {
my $file = shift;
open(I, $file) or return;
$/ = undef;
my $txt = <I>;
$/ = "\n";
close(I);
return $txt;
}
sub bugtxt($)
{
my $bug = shift or return "";
my $now = time;
my $tmp;
$bug =~ s/\.\.//g;
$bug =~ s/^\///g;
$bug =~ s/~//g;
$bug =~ s/[^a-zA-Z0-9\-]//g;
$tmp = "$tmpdir/$bug.txt";
if(-f $tmp) {
return catfile($tmp);
}
my $cmd = "wget -q http://jira.freeswitch.org/si/jira.issueviews:issue-xml/$bug/$bug.xml -O $tmp";
system($cmd);
my $txt = catfile($tmp);
my ($a,$title) = $txt =~ /\<title\>(.*?)\<\/title\>/smg;
my ($status) = $txt =~ /\<status.*?\>(.*?)\<\/status\>/smg;
my ($a,$des) = $txt =~ /\<description\>(.*?)\<\/description\>/smg;
my ($alogin, $aname) = $txt =~ /\<assignee username=\"([^\"]+)\"\>(.*?)\<\/assignee\>/smg;
my ($rlogin, $rname) = $txt =~ /\<reporter username=\"([^\"]+)\"\>(.*?)\<\/reporter\>/smg;
if ($rname && $aname) {
my $data = "$title\nReporter: $rname [$rlogin]\nAssignee: $aname [$alogin]\nStatus: $status\nhttp://jira.freeswitch.org/browse/$bug\n";
open(O, ">$tmp");
print O $data;
close(O);
return $data;
} else {
unlink($tmp);
}
}