Merge remote branch 'origin/v1.2.stable' into v1.2.stable-em_management
This commit is contained in:
commit
7a3cc7c9af
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
1.2.11
|
1.2.14
|
||||||
|
|
28
configure.in
28
configure.in
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
debian/tmp/usr/perl/freeswitch.pm /usr/lib/perl5
|
||||||
|
debian/tmp/usr/perl/freeswitch.so /usr/lib/perl5/auto/freeswitch
|
|
@ -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:
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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*)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Fri Sep 20 00:39:20 CDT 2013
|
Tue Oct 8 23:05:34 CDT 2013
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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/^.*= //"` ;\
|
||||||
|
|
|
@ -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*
|
||||||
|
|
|
@ -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++;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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))) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue