Merge branch 'master' into v1.6

This commit is contained in:
Ken Rice 2016-04-21 10:45:00 -05:00
commit 3266df82fc
79 changed files with 10303 additions and 8546 deletions

View File

@ -533,7 +533,7 @@ libs/libzrtp/libzrtp.a:
cd libs/libzrtp && $(MAKE)
libs/libvpx/Makefile:
cd libs/libvpx && CC=$(CC) CXX=$(CXX) CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" ./configure --enable-pic --disable-docs --disable-examples --disable-install-bins --disable-install-srcs --disable-unit-tests --extra-cflags="-fvisibility=hidden"
cd libs/libvpx && CC="$(CC)" CXX="$(CXX)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" ./configure --enable-pic --disable-docs --disable-examples --disable-install-bins --disable-install-srcs --disable-unit-tests --extra-cflags="$(VISIBILITY_FLAG)"
libs/libvpx/libvpx.a: libs/libvpx/Makefile
@cd libs/libvpx && $(MAKE)

View File

@ -13,5 +13,9 @@
<param name="ssl-verifypeer" value="true"/>
<!-- verify host name matches certificate -->
<param name="ssl-verifyhost" value="true"/>
<!-- default is 300 seconds, override here -->
<!--param name="connect-timeout" value="300"/-->
<!-- default is 300 seconds, override here -->
<!--param name="download-timeout" value="300"/-->
</settings>
</configuration>

View File

@ -16,7 +16,7 @@
</connection>
</connections>
<params>
<param name="debug" value="1"/>
<param name="ignore-connect-fail" value="true"/>
</params>
</profile>
</profiles>

View File

@ -13,5 +13,9 @@
<param name="ssl-verifypeer" value="true"/>
<!-- verify host name matches certificate -->
<param name="ssl-verifyhost" value="true"/>
<!-- default is 300 seconds, override here -->
<!--param name="connect-timeout" value="300"/-->
<!-- default is 300 seconds, override here -->
<!--param name="download-timeout" value="300"/-->
</settings>
</configuration>

View File

@ -5,6 +5,15 @@
<!-- <param name="auto-restart" value="false"/> -->
<param name="debug-presence" value="0"/>
<!-- <param name="capture-server" value="udp:homer.domain.com:5060"/> -->
<!--
the new format for HEPv2/v3 and capture ID
protocol:host:port;hep=2;capture_id=200;
-->
<!-- <param name="capture-server" value="udp:homer.domain.com:5060;hep=3;capture_id=100"/> -->
</global_settings>
<!--

View File

@ -411,6 +411,7 @@ elif test "x${ax_cv_c_compiler_vendor}" = "xgnu" ; then
AC_SUBST([AM_MOD_AVMD_CXXFLAGS], [-std=gnu99]) # FS-8809, needed for MAP_POPULATE
if test "$ac_cv_gcc_supports_w_no_unused_result" = yes; then
APR_ADDTO(SWITCH_AM_CFLAGS, -Werror)
APR_ADDTO(SWITCH_AM_CFLAGS, -Wno-unused-result)
fi
if test "${enable_64}" = "yes"; then
case "$host" in
@ -450,6 +451,16 @@ if test "${enable_address_sanitizer}" = "yes"; then
fi
case "${ax_cv_c_compiler_vendor}" in
sun)
VISIBILITY_FLAG=-xldscope=hidden
;;
*)
VISIBILITY_FLAG=-fvisibility=hidden
;;
esac
AC_SUBST(VISIBILITY_FLAG)
#
# gcc visibility cflag checks
#
@ -1395,7 +1406,7 @@ PKG_CHECK_MODULES([SMPP34], [libsmpp34 >= 1.10],[
AM_CONDITIONAL([HAVE_SMPP34],[true])],[
AC_MSG_RESULT([no]); AM_CONDITIONAL([HAVE_SMPP34],[false])])
PKG_CHECK_MODULES([HIREDIS], [hiredis >= 0.11.0],[
PKG_CHECK_MODULES([HIREDIS], [hiredis >= 0.10.0],[
AM_CONDITIONAL([HAVE_HIREDIS],[true])],[
AC_MSG_RESULT([no]); AM_CONDITIONAL([HAVE_HIREDIS],[false])])
@ -1902,7 +1913,7 @@ AC_SUBST(OUR_DISABLED_INSTALL_MODS)
AC_SUBST(OUR_DISABLED_UNINSTALL_MODS)
AC_SUBST(AM_MAKEFLAGS)
ac_configure_args="$ac_configure_args CONFIGURE_CFLAGS='$CFLAGS $CPPFLAGS' CONFIGURE_CXXFLAGS='$CXXFLAGS $CPPFLAGS' CONFIGURE_LDFLAGS='$LDFLAGS' "
ac_configure_args="$ac_configure_args --with-modinstdir=${modulesdir} CONFIGURE_CFLAGS='$CFLAGS $CPPFLAGS' CONFIGURE_CXXFLAGS='$CXXFLAGS $CPPFLAGS' CONFIGURE_LDFLAGS='$LDFLAGS' "
# --prefix='$prefix' --exec_prefix='$exec_prefix' --libdir='$libdir' --libexecdir='$libexecdir' --bindir='$bindir' --sbindir='$sbindir' \
# --localstatedir='$localstatedir' --datadir='$datadir'"

94
debian/bootstrap.sh vendored
View File

@ -276,40 +276,6 @@ list_pkgs () {
map_pkgs list_pkgs_thunk
}
list_freeswitch_all_pkgs () {
list_pkgs \
| grep -v '^freeswitch-all$' \
| grep -v -- '-dbg$'
}
list_freeswitch_all_provides () {
list_freeswitch_all_pkgs \
| intersperse ',\n '
}
list_freeswitch_all_replaces () {
list_freeswitch_all_pkgs \
| postfix ' (<= ${binary:Version})' \
| intersperse ',\n '
}
list_freeswitch_all_dbg_pkgs () {
list_pkgs \
| grep -v '^freeswitch-all-dbg$' \
| grep -- '-dbg$'
}
list_freeswitch_all_dbg_provides () {
list_freeswitch_all_dbg_pkgs \
| intersperse ',\n '
}
list_freeswitch_all_dbg_replaces () {
list_freeswitch_all_dbg_pkgs \
| postfix ' (<= ${binary:Version})' \
| intersperse ',\n '
}
print_source_control () {
local libtool_dep="libtool, libtool-bin"
case "$codename" in
@ -341,7 +307,7 @@ Build-Depends:
libogg-dev, libspeex-dev, libspeexdsp-dev,
# configure options
libssl-dev, unixodbc-dev, libpq-dev,
libncurses5-dev, libjpeg62-turbo-dev | libjpeg62-dev | libjpeg8-dev,
libncurses5-dev, libjpeg62-turbo-dev | libjpeg-turbo8-dev | libjpeg62-dev | libjpeg8-dev,
python-dev, python-all-dev, python-support (>= 0.90), erlang-dev,
# documentation
doxygen,
@ -364,22 +330,11 @@ print_core_control () {
cat <<EOF
Package: freeswitch-all
Architecture: any
Provides: $(list_freeswitch_all_provides)
Replaces: $(list_freeswitch_all_replaces)
Conflicts: $(list_freeswitch_all_replaces)
Depends: \${shlibs:Depends}, \${perl:Depends}, \${misc:Depends},
freeswitch-music-default (>= 1.0.8),
freeswitch-sounds-en-us-callie (>= 1.0.25) | freeswitch-sounds,
yasm,
$(debian_wrap "${mod_depends}")
Recommends:
$(debian_wrap "${mod_recommends}")
Suggests: freeswitch-all-dbg,
$(debian_wrap "${mod_suggests}")
Depends: freeswitch-meta-all (= \${binary:Version})
Description: Cross-Platform Scalable Multi-Protocol Soft Switch
$(debian_wrap "${fs_description}")
.
This package contains FreeSWITCH and all modules and extras.
This is a package which depends on all packaged FreeSWITCH modules.
Package: freeswitch
Architecture: any
@ -806,10 +761,7 @@ Package: freeswitch-all-dbg
Section: debug
Priority: extra
Architecture: any
Provides: $(list_freeswitch_all_dbg_provides)
Replaces: $(list_freeswitch_all_dbg_replaces)
Breaks: $(list_freeswitch_all_dbg_replaces)
Depends: \${misc:Depends}, freeswitch-all (= \${binary:Version})
Depends: \${misc:Depends}, freeswitch-meta-all (= \${binary:Version})
Description: debugging symbols for FreeSWITCH
$(debian_wrap "${fs_description}")
.
@ -1060,7 +1012,6 @@ gencontrol_per_cat () {
geninstall_per_mod () {
local f=freeswitch-${module_name//_/-}.install
(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
}
@ -1082,7 +1033,6 @@ genconf () {
local p=freeswitch-conf-${conf//_/-}
local f=$p.install
(print_edit_warning; print_conf_install) > $f
print_conf_install >> freeswitch-all.install
test -f $f.tmpl && cat $f.tmpl >> $f
local f=$p.lintian-overrides
(print_edit_warning; print_conf_overrides "$p") > $f
@ -1094,7 +1044,6 @@ genlang () {
local p=freeswitch-lang-${lang//_/-}
local f=$p.install
(print_edit_warning; print_lang_install) > $f
print_lang_install >> freeswitch-all.install
test -f $f.tmpl && cat $f.tmpl >> $f
local f=$p.lintian-overrides
(print_edit_warning; print_lang_overrides "$p") > $f
@ -1324,9 +1273,6 @@ echo "Accumulating dependencies from modules..." >&2
map_modules 'mod_filter' '' 'accumulate_mod_deps'
echo "Generating debian/..." >&2
> 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
echo "Generating debian/ (conf)..." >&2
(echo "### conf"; echo) >> control
@ -1339,29 +1285,17 @@ echo "Generating debian/ (modules)..." >&2
map_modules "mod_filter" \
"gencontrol_per_cat" \
"gencontrol_per_mod geninstall_per_mod genoverrides_per_mod"
echo "Generating debian/ (-all package)..." >&2
grep -e '^Package:' control | grep -v '^freeswitch-all$' | while xread l; do
m="${l#*: }"
conf_merge freeswitch-all.install $m.install
done
echo "/usr/share/freeswitch/fonts" >> freeswitch-all.install
echo "/var/lib/freeswitch/images" >> freeswitch-all.install
for x in postinst postrm preinst prerm; do
cp -a freeswitch.$x freeswitch-all.$x
done
cp -a freeswitch-doc.docs freeswitch-all.docs
if [ ${use_sysvinit} = "true" ]; then
cp -a freeswitch-sysvinit.freeswitch.init freeswitch-all.freeswitch.init
cp -a freeswitch-sysvinit.freeswitch.default freeswitch-all.freeswitch.default
echo -n freeswitch-sysvinit >freeswitch-init.provided_by
else
cp -a freeswitch-systemd.freeswitch.service freeswitch-all.freeswitch.service
cp -a freeswitch-systemd.freeswitch.tmpfile freeswitch-all.freeswitch.tmpfile
echo -n freeswitch-systemd >freeswitch-init.provided_by
fi
##### Not sure if this is needed at all... if this is supposed to be included somewhere it should be for just the freeswitch package
#if [ ${use_sysvinit} = "true" ]; then
# cp -a freeswitch-sysvinit.freeswitch.init freeswitch-all.freeswitch.init
# cp -a freeswitch-sysvinit.freeswitch.default freeswitch-all.freeswitch.default
# echo -n freeswitch-sysvinit >freeswitch-init.provided_by
#else
# cp -a freeswitch-systemd.freeswitch.service freeswitch-all.freeswitch.service
# cp -a freeswitch-systemd.freeswitch.tmpfile freeswitch-all.freeswitch.tmpfile
# echo -n freeswitch-systemd >freeswitch-init.provided_by
#fi
echo "Generating additional lintian overrides..." >&2

17
debian/rules vendored
View File

@ -100,23 +100,6 @@ override_dh_auto_install:
dh_auto_install -- -C libs/esl pymod-install
rm -f debian/tmp/usr/share/freeswitch/grammar/model/communicator/COPYING
override_dh_installinit:
if [ `cat debian/freeswitch-init.provided_by` = freeswitch-systemd ]; then \
dh_systemd_enable -pfreeswitch-systemd --name=freeswitch; \
dh_systemd_start -pfreeswitch-systemd --name=freeswitch; \
dh_systemd_enable -pfreeswitch-all --name=freeswitch; \
dh_systemd_start -pfreeswitch-all --name=freeswitch; \
else \
dh_installinit -pfreeswitch-sysvinit --name=freeswitch; \
dh_installinit -pfreeswitch-all --name=freeswitch; \
fi
override_dh_makeshlibs:
dh_makeshlibs
sed \
-e '/^libfreeswitch 1/{s/freeswitch-all/libfreeswitch1/g}' \
-i debian/freeswitch-all/DEBIAN/shlibs
debian-bootstrap: debian/.stamp-bootstrap
debian/.stamp-bootstrap:
(cd debian && ./bootstrap.sh)

1
debian/util.sh vendored
View File

@ -260,6 +260,7 @@ get_sources () {
prefix=`echo $distro | awk -F/ '{print $1}'`
suffix="`echo $distro | awk -F/ '{print $2}'`"
if test -n "$suffix" ; then full="$tgt_distro/$suffix" ; else full="$tgt_distro" ; fi
if [ "$distro" == "trusty" -a "$components" == "main" ] ; then components="main universe"; fi
printf "$type $path $full $components\n"
done < "$2"
}

View File

@ -31,7 +31,7 @@ PROJECT_NAME = "FreeSWITCH API Documentation"
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = 1.5.14b
PROJECT_NUMBER = 1.7.0
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.

View File

@ -0,0 +1,142 @@
{
"TITLE_ACTIVE_CALL": "Ups, der er et aktivt opkald.",
"MESSAGE_ACTIVE_CALL_HANGUP": "Du er allerede i et opkald. Vil du lægge på?",
"MESSAGE_ACTIVE_CALL_BACK": "Det ser ud til du sidste gang var i et opkald. Vil du tilbage til det?",
"TITLE_INCOMING_CALL": "Indkommende kald",
"MESSAGE_INCOMING_CALL": "Fra ",
"MESSAGE_NO_HANGUP_CALL": "Der er ikke noget opkald at lægge på.",
"MESSAGE_ENTER_FILENAME": "Vær venlig at indtaste filnavnet",
"TITLE_ENABLE_VIDEO": "Vil du slå video til for dette opkald?",
"MESSAGE_ENABLE_VIDEO": "Video vil være slået til for de næste opkald.",
"TITLE_INSERT_BANNER": "Vær venlig at indsætte bannerteksten",
"TITLE_INSERT_CANVAS_ID": "Vær venlig at indsætte Canvas Id'et",
"TITLE_INSERT_LAYER": "Vær venlig at indsætte laget",
"TITLE_TRANSFER": "Viderestil gruppen?",
"MESSAGE_TRANSFER": "Til hvilken destination vil du viderestille opkaldet?",
"LABEL_TRANSFER": "Destination",
"MESSAGE_DISPLAY_SETTINGS": "Det er ikke muligt at vise eksempelvisnings indstillinger under et kald",
"BUTTON_END_CALL": "Afslut kald",
"BUTTON_CLOSE": "Luk",
"MESSAGE_PLAY": "Afspil",
"MESSAGE_STOP": "Stop",
"MESSAGE_RECORD": "Optag",
"MESSAGE_STOP_RECORD": "Stop med at optage",
"MESSAGE_SNAPSHOT": "Snapshot",
"MESSAGE_VIDEO_MODE": "Videotilstand",
"MESSAGE_MUTE_MIC": "Slå mikrofon til/fra",
"MESSAGE_MUTE_VIDEO": "Slå video til/fra",
"MESSAGE_FULLSCREEN": "Skift fuldskærmstilstand",
"MESSAGE_SCREENSHARE": "Skærmdeling",
"MESSAGE_OPEN_CLOSE_CHAT": "Åben/luk chat",
"MESSAGE_SPEAKER": "Højtaler",
"MESSAGE_POPUP": "Popup",
"CHAT_TITLE_MEMBERS": "Medlemmer",
"CHAT_TITLE": "Chat",
"CHAT_NO_MEMBERS": "Der er ingen medlemmer at vise.",
"CHAT_GENERAL": "Generel",
"CHAT_TITLE_KICK": "Fjern",
"CHAT_KICK": "Fjern",
"CHAT_TITLE_VIDEO_FLOOR": "Video niveau",
"CHAT_FLOOR": "Niveau",
"CHAT_TITLE_TRANSFER": "Viderestil",
"CHAT_TRANSFER": "Viderestil",
"CHAT_BANNER": "Banner",
"CHAT_TITLE_SET": "Sæt",
"CHAT_SET": "Sæt",
"CHAT_TITLE_RESET": "Nulstil",
"CHAT_RESET": "Nulstil",
"CHAT_CANVAS": "Canvas",
"CHAT_CANVAS_IN": "Canvas ind",
"CHAT_CANVAS_OUT": "Canvas ud",
"CHAT_PREV": "Forrige",
"CHAT_NEXT": "Næste",
"CHAT_LAYER": "Lag",
"CHAT_AUDIO_VIDEO": "Lyd/Video",
"CHAT_TITLE_MUTE_UNMUTE_MIC": "Slå mikrofon til/fra",
"CHAT_MUTE_MIC": "Slå mikrofon fra",
"CHAT_UNMUTE_MIC": "Slå mikrofon til",
"CHAT_TITLE_MUTE_UNMUTE_MIC": "Slå video til/fra",
"CHAT_NO_MESSAGES": "Der er ingen beskeder at vise.",
"CHAT_SEND_MESSAGE": "Send",
"CHAT_TYPE_MESSAGE": "Skriv din besked her...",
"TITLE_CONTRIBUTORS": "Bidragsydere",
"MESSAGE_CONNECTION_UNTRUSTED": "Denne forbindelse er ikke til at stole på.",
"MESSAGE_TOGGLE_NAVIGATION": "Vis/skjul navigation",
"BANDWIDTH_INFO": "Båndbredde information",
"BANDWIDTH_INFO_INCOMING": "Indkommende:",
"BANDWIDTH_INFO_OUTGOING": "Udgående:",
"BANDWIDTH_INFO_VIDEO_RES": "Video opløsning:",
"IN_CALL": "I opkald:",
"LAST_CALL": "Sidste opkald:",
"OPEN_NEW_WINDOW": "Åben nyt vindue",
"CHANGE_LOGIN_INFO": "Rediger loginoplysninger",
"LOGOUT": "Log ud",
"ABOUT": "Om",
"HELP": "Hjælp",
"CONTRIBUTORS": "Bidragsydere",
"TITLE_PREVIEW_SETTINGS": "Opsæt indstillinger for kamera og mikrofon",
"CAMERA__SETTNGS": "Kamera:",
"MIC_SETTINGS": "Mikrofon:",
"SAVE": "Gem",
"LOADING": "Henter",
"ERRORS" : "Fejl",
"CALLING_TO": "Ringer til ",
"CANCELLING": "Annullerer...",
"DETERMINING_SPEED": "Bestemmer din hastighed...",
"CALL_HISTORY": "Opkaldshistorik",
"CLEAR_CALL_HISTORY": "Ryd historik",
"NO_CALL_HISTORY": "Ingen opkaldshistorik.",
"ENTER_EXTENSION": "Skriv en udvidelse",
"CALL_EXTENSION": "Opkaldsudvidelse",
"LOGIN": "Log ind",
"LOGIN_INFORMATION": "Log ind oplysninger",
"SAVE_LOGIN_INFORMATION": "Gem log ind oplysninger",
"INVALID_LOGIN_FIELDS": "Kontroller felterne nedenfor og prøv igen.",
"NAME": "Navn",
"YOUR_NAME": "Dit navn",
"EMAIL": "Email",
"YOUR_EMAIL": "Din email",
"USER": "Bruger",
"PASSWORD": "Adgangskode",
"CALLER_ID": "Den ringende parts ID",
"HOSTNAME": "Hostname",
"WEBSOCKET_URL": "Websocket URL",
"SETTINGS": "Indstillinger",
"DEVICE_SETTINGS": "Enhedsindstillinger",
"SHARE_DEVICE": "Del enhed",
"SPEAKER": "Højtaler:",
"SPEAKER_FEATURE": "Din browser understøtter ikke denne funktion",
"PREVIEW_SETTINGS": "Vis indstillingerne",
"REFRESH_DEVICE_LIST": "Opdater enhedslisten",
"GENERAL_SETTINGS": "Generelle indstillinger:",
"USE_VIDEO": "Brug video",
"USE_STEREO_AUDIO": "Stereolyd",
"USE_STUN": "Brug STUN",
"SCALE_VIDEO": "Skalér video til at matche kameraopløsningen",
"ASK_BEFORE_RECOVER": "Spørg før genetablering af kald",
"BEST_FRAME_RATE": "Bedste billedhastighed:",
"AUDIO_SETTINGS": "Lydindstillinger:",
"ECHO_CANCEL": "Fjernelse af ekko",
"NOISE_SUPPRESSION": "Støjdæmpning",
"HIGHPASS_FILTER": "High-pass filter",
"VIDEO_SETTINGS": "Videoindstillinger:",
"REMOTE_ENCODER": "Dedikeret fjern-enkoder er aktiveret.",
"AUTO_SPEED_RES": "Bestem automatisk indstillinger for hastighed og opløsning",
"RECHECK_BANDWIDTH": "Tjek båndbredden før hvert udgående opkald",
"CHECK_NETWORK_SPEED": "Tjek netværkshastighed",
"VIDEO_QUALITY": "Videokvalitet:",
"MAX_INCOMING_BANDWIDTH": "Max indgående båndbredde:",
"MAX_OUTGOING_BANDWIDTH": "Max udgående båndbredde:",
"FACTORY_RESET": "Nulstil til fabriksindstillinger",
"SAVE_DEVICE_SETTINGS": "Gem enhedsindstillinger",
"BROWSER_COMPATIBILITY": "Tjek browser kompatibilitet.",
"REFRESH_MEDIA_DEVICES": "Opdater medieenhed.",
"BROWSER_WITHOUT_WEBRTC": "Fejk: browseren understøtter ikke WebRTC.",
"CHECK_PERMISSION_MEDIA": "Tjekker medie tilladelser",
"CHECK_PROVISIONING_CONF": "Konfiguration af provisionering.",
"CHECK_LOGIN": "Tjekker log ind oplysninger.",
"CHECK_CONNECTION_SPEED": "Tjek forbindelseshastighed.",
"ERROR_PERMISSION_MEDIA": "Fejl: Medie tilladelse nægtet",
"ERROR_PROVISIONING_CONF": "Fejl: Provisioneringen fejlede.",
"PLEASE_WAIT": "Vent venligst..."
}

View File

@ -147,5 +147,7 @@
"CHAT_VOL_MINUS": "Vol -",
"CHAT_VOL_PLUS": "Vol +",
"CHAT_GAIN_MINUS": "Gain -",
"CHAT_GAIN_PLUS": "Gain +"
"CHAT_GAIN_PLUS": "Gain +",
"LANGUAGE": "Language:",
"BROWSER_LANGUAGE": "Browser Language"
}

View File

@ -148,6 +148,8 @@
"CHAT_VOL_MINUS": "Vol -",
"CHAT_VOL_PLUS": "Vol +",
"CHAT_GAIN_MINUS": "Guadagno -",
"CHAT_GAIN_PLUS": "Guadagno +"
"CHAT_GAIN_PLUS": "Guadagno +",
"LANGUAGE": "Lingua:",
"BROWSER_LANGUAGE": "Lingua del browser"
}

View File

@ -79,6 +79,14 @@
</label>
</div>
<div class="form-group">
<label for="settings-language">{{ 'LANGUAGE' | translate }}</label>
<select name="mylanguage" id="settings-language" class="form-control"
ng-model="mydata.language" ng-change="changedLanguage(mydata.language)"
ng-options="item.id as item.name for item in languages">
</select>
</div>
<div class="form-group">
<label for="settings-microphone">{{ 'AUDIO_SETTINGS' | translate }}</label>
<div class="checkbox">

View File

@ -39,7 +39,8 @@
googEchoCancellation: true,
autoBand: true,
testSpeedJoin: true,
bestFrameRate: "15"
bestFrameRate: "15",
language: undefined
};
data.$default(defaultSettings);

View File

@ -20,8 +20,58 @@
'pascalprecht.translate',
]);
vertoApp.config(['$routeProvider', 'gravatarServiceProvider', '$translateProvider',
function($routeProvider, gravatarServiceProvider, $translateProvider) {
vertoApp.constant('configLanguages', {
'languages' : [
{id: 'en', name: 'English'},
{id: 'it', name: 'Italiano'},
{id: 'fr', name: 'Français'},
{id: 'de', name: 'Deutsch'},
{id: 'pt', name: 'Português'},
{id: 'pl', name: 'Polski'},
{id: 'zh', name: '中國'},
{id: 'ru', name: 'Pусский'},
{id: 'sv', name: 'Svenska'},
{id: 'da', name: 'Dansk'},
{id: 'es', name: 'Español'},
{id: 'id', name: 'Indonesia'}
],
'dialects' : {
'en': 'en',
'en_GB': 'en',
'en_US': 'en',
'it': 'it',
'it_IT': 'it',
'fr': 'fr',
'fr_FR': 'fr',
'fr_CA': 'fr',
'pt': 'pt',
'pt_BR': 'pt',
'pt_PT': 'pt',
'de': 'de',
'de_DE': 'de',
'es': 'es',
'es_ES': 'es',
'pl': 'pl',
'pl_PL': 'pl',
'ru': 'ru',
'ru_RU': 'ru',
'sv': 'sv',
'sv_SV': 'sv',
'sv_FI': 'sv',
'da': 'da',
'da_DK': 'da',
'id': 'id',
'id_ID': 'id',
'zh': 'zh',
'zh_CN': 'zh',
'zh_TW': 'zh',
'zh_HK': 'zh'
}
});
vertoApp.config(['$routeProvider', 'gravatarServiceProvider', '$translateProvider', 'configLanguages',
function($routeProvider, gravatarServiceProvider, $translateProvider, configLanguages) {
$routeProvider.
when('/', {
title: 'Loading',
@ -61,42 +111,17 @@
default: 'mm' // Mystery man as default for missing avatars
};
var reg_langs = [];
angular.forEach(configLanguages.languages, function(value, key) {
reg_langs.push(value.id);
});
$translateProvider
.useStaticFilesLoader({
prefix: 'locales/locale-',
suffix: '.json'
})
.registerAvailableLanguageKeys(['en', 'it', 'pt', 'fr', 'de', 'es', 'pl', 'ru', 'sv', 'id', 'zh'], {
'en': 'en',
'en_GB': 'en',
'en_US': 'en',
'it': 'it',
'it_IT': 'it',
'fr': 'fr',
'fr_FR': 'fr',
'fr_CA': 'fr',
'pt': 'pt',
'pt_BR': 'pt',
'pt_PT': 'pt',
'de': 'de',
'de_DE': 'de',
'es': 'es',
'es_ES': 'es',
'pl': 'pl',
'pl_PL': 'pl',
'ru': 'ru',
'ru_RU': 'ru',
'sv': 'sv',
'sv_SV': 'sv',
'sv_FI': 'sv',
'id': 'id',
'id_ID': 'id',
'zh': 'zh',
'zh_CN': 'zh',
'zh_TW': 'zh',
'zh_HK': 'zh'
})
.registerAvailableLanguageKeys(reg_langs, configLanguages.dialects)
.preferredLanguage('en')
.determinePreferredLanguage()
.fallbackLanguage('en')

View File

@ -8,6 +8,12 @@
console.debug('Executing MainController.');
if (storage.data.language && storage.data.language !== 'browser') {
$translate.use(storage.data.language);
} else {
storage.data.language = 'browser';
}
$rootScope.master = $location.search().master;
if ($location.search().watcher === 'true') {
$rootScope.watcher = true;

View File

@ -4,8 +4,8 @@
angular
.module('vertoControllers')
.controller('SettingsController', ['$scope', '$http',
'$location', '$rootScope', 'storage', 'verto', '$translate', 'toastr',
function($scope, $http, $location, $rootScope, storage, verto, $translate, toastr) {
'$location', '$rootScope', 'storage', 'verto', '$translate', 'toastr', 'configLanguages',
function($scope, $http, $location, $rootScope, storage, verto, $translate, toastr, configLanguages) {
console.debug('Executing ModalSettingsController.');
$.material.init();
@ -14,6 +14,15 @@
$scope.storage = storage;
$scope.verto = verto;
$scope.mydata = angular.copy(storage.data);
$scope.languages = configLanguages.languages;
$scope.languages.unshift({id: 'browser', name : $translate.instant('BROWSER_LANGUAGE')});
$scope.mydata.language = storage.data.language || 'browser';
$rootScope.$on('$translateChangeSuccess', function () {
$translate('BROWSER_LANGUAGE').then(function (translation) {
$scope.languages[0].name = translation;
});
});
$rootScope.$on('toggledSettings', function(e, status) {
if (status) {
@ -35,6 +44,20 @@
}
};
$scope.changedLanguage = function(langKey){
if (langKey === 'browser'){
storage.data.language = 'browser';
var browserlang = $translate.preferredLanguage();
$translate.use(browserlang).then(
function(lang) {}, function(fail_lang) {
$translate.use('en');
});
} else {
$translate.use(langKey);
storage.data.language = langKey;
}
};
$scope.refreshDeviceList = function() {
return verto.refreshDevices();
};

View File

@ -1 +1 @@
Wed Aug 19 11:38:49 CDT 2015
Fri Apr 8 13:43:12 EDT 2016

View File

@ -631,6 +631,13 @@ APR_DECLARE(apr_status_t) apr_socket_timeout_set(apr_socket_t *sock,
APR_DECLARE(apr_status_t) apr_socket_opt_get(apr_socket_t *sock,
apr_int32_t opt, apr_int32_t *on);
/**
* Get Socket fd for the socket passed
* @param sock The socket to quesry for the socket fd
*/
APR_DECLARE(int) apr_socket_fd_get(apr_socket_t *sock);
/**
* Query socket timeout for the specified socket
* @param sock The socket to query

View File

@ -110,6 +110,16 @@ APR_DECLARE(apr_status_t) apr_socket_opt_get(apr_socket_t *sock,
}
APR_DECLARE(int) apr_socket_fd_get(apr_socket_t *sock)
{
if (sock) {
return sock->socketdes;
} else {
return 0;
}
}
APR_DECLARE(apr_status_t) apr_socket_atmark(apr_socket_t *sock, int *atmark)
{
int oobmark;

View File

@ -344,6 +344,16 @@ apr_status_t apr_socket_opt_get(apr_socket_t *sock,
}
int apr_socket_fd_get(apr_socket_t *sock)
{
if (sock) {
return sock->socketdes;
} else {
return 0;
}
}
apr_status_t apr_socket_atmark(apr_socket_t *sock, int *atmark)
{
#ifndef BEOS_R5

View File

@ -244,6 +244,16 @@ APR_DECLARE(apr_status_t) apr_socket_opt_get(apr_socket_t *sock,
}
APR_DECLARE(int) apr_socket_fd_get(apr_socket_t *sock)
{
if (sock) {
return sock->socketdes;
} else {
return 0;
}
}
APR_DECLARE(apr_status_t) apr_socket_atmark(apr_socket_t *sock, int *atmark)
{
u_long oobmark;

View File

@ -107,7 +107,7 @@ ifeq ($(CONFIG_VP9_DECODER),yes)
endif
VP9_PREFIX=vp9/
$(BUILD_PFX)$(VP9_PREFIX)%.c.o: CFLAGS += -Wextra
$(BUILD_PFX)$(VP9_PREFIX)%.c.o:
# VP10 make file
ifeq ($(CONFIG_VP10),yes)
@ -141,7 +141,7 @@ ifeq ($(CONFIG_VP10_DECODER),yes)
endif
VP10_PREFIX=vp10/
$(BUILD_PFX)$(VP10_PREFIX)%.c.o: CFLAGS += -Wextra
$(BUILD_PFX)$(VP10_PREFIX)%.c.o:
ifeq ($(CONFIG_ENCODERS),yes)
CODEC_DOC_SECTIONS += encoder

View File

@ -21,7 +21,7 @@
# define ZRTP_PLATFORM ZP_ANDROID
# elif defined(__FreeBSD__)
# define ZRTP_PLATFORM ZP_BSD
# elif defined(linux) || defined(__linux)
# elif defined(linux) || defined(__linux__) || defined(__linux)
# include <linux/version.h>
# define ZRTP_PLATFORM ZP_LINUX
# elif defined(__MACOSX__) || defined (__APPLE__) || defined (__MACH__)
@ -88,7 +88,13 @@
*/
#define ZRTP_BYTE_ORDER ZBO_BIG_ENDIAN
#elif defined(ARM) || defined(_ARM_) || defined(ARMV4) || defined(__arm__)
#elif defined(__AARCH64EB__)
/*
* aarch64, big endian
*/
#define ZRTP_BYTE_ORDER ZBO_BIG_ENDIAN
#elif defined(ARM) || defined(_ARM_) || defined(ARMV4) || defined(__arm__) || defined(__AARCH64EL__)
/*
* ARM, default to little endian
*/

View File

@ -1 +1 @@
Wed Sep 9 12:25:38 CDT 2015
Mon Apr 18 10:41:03 CEST 2016

View File

@ -130,6 +130,13 @@ struct hep_iphdr{
struct in_addr hp_dst; /* source and dest address */
};
/* HEPv2 */
struct hep_timehdr{
uint32_t tv_sec; /* seconds */
uint32_t tv_usec; /* useconds */
uint16_t captid; /* Capture ID node */
};
#if SU_HAVE_IN6
struct hep_ip6hdr {
struct in6_addr hp6_src; /* source address */
@ -137,6 +144,101 @@ struct hep_ip6hdr {
};
#endif
/* HEPv3 types */
#if (defined __SUNPRO_CC) || defined(__SUNPRO_C) || defined(_MSC_VER)
#define PACKED
#endif
#ifndef PACKED
#define PACKED __attribute__ ((__packed__))
#endif
#ifdef _MSC_VER
#pragma pack(push, 1)
#endif
struct hep_chunk {
uint16_t vendor_id;
uint16_t type_id;
uint16_t length;
} PACKED;
typedef struct hep_chunk hep_chunk_t;
struct hep_chunk_uint8 {
hep_chunk_t chunk;
uint8_t data;
} PACKED;
typedef struct hep_chunk_uint8 hep_chunk_uint8_t;
struct hep_chunk_uint16 {
hep_chunk_t chunk;
uint16_t data;
} PACKED;
typedef struct hep_chunk_uint16 hep_chunk_uint16_t;
struct hep_chunk_uint32 {
hep_chunk_t chunk;
uint32_t data;
} PACKED;
typedef struct hep_chunk_uint32 hep_chunk_uint32_t;
struct hep_chunk_str {
hep_chunk_t chunk;
char *data;
} PACKED;
typedef struct hep_chunk_str hep_chunk_str_t;
struct hep_chunk_ip4 {
hep_chunk_t chunk;
struct in_addr data;
} PACKED;
typedef struct hep_chunk_ip4 hep_chunk_ip4_t;
struct hep_chunk_ip6 {
hep_chunk_t chunk;
struct in6_addr data;
} PACKED;
typedef struct hep_chunk_ip6 hep_chunk_ip6_t;
struct hep_chunk_payload {
hep_chunk_t chunk;
char *data;
} PACKED;
typedef struct hep_chunk_payload hep_chunk_payload_t;
struct hep_ctrl {
char id[4];
uint16_t length;
} PACKED;
typedef struct hep_ctrl hep_ctrl_t;
struct hep_generic {
hep_ctrl_t header;
hep_chunk_uint8_t ip_family;
hep_chunk_uint8_t ip_proto;
hep_chunk_uint16_t src_port;
hep_chunk_uint16_t dst_port;
hep_chunk_uint32_t time_sec;
hep_chunk_uint32_t time_usec;
hep_chunk_uint8_t proto_t;
hep_chunk_uint32_t capt_id;
} PACKED;
#ifdef _MSC_VER
#pragma pack(pop)
#endif
typedef struct hep_generic hep_generic_t;
/** Maximum size when streaming. */
#define MSG_SSIZE_MAX (USIZE_MAX)

View File

@ -306,6 +306,8 @@ struct tport_master {
su_socket_t mr_capt_sock;
char *mr_capt_name; /**< Servername for capturing received/sent data */
tport_primary_t *mr_primaries; /**< List of primary contacts */
unsigned mr_prot_ver; /* hep version */
unsigned mr_agent_id; /* agent version */
tport_params_t mr_params[1];
@ -486,6 +488,12 @@ void tport_dump_iovec(tport_t const *self, msg_t *msg,
void tport_capt_msg(tport_t const *self, msg_t *msg, size_t n,
su_iovec_t const iov[], size_t iovused, char const *what);
int tport_capt_msg_hepv2(tport_t const *self, msg_t *msg, size_t n,
su_iovec_t const iov[], size_t iovused, char const *what, char **buffer);
int tport_capt_msg_hepv3(tport_t const *self, msg_t *msg, size_t n,
su_iovec_t const iov[], size_t iovused, char const *what, char **buffer);
int tport_tcp_ping(tport_t *self, su_time_t now);
int tport_tcp_pong(tport_t *self);

View File

@ -143,7 +143,9 @@ int tport_open_log(tport_master_t *mr, tagi_t *tags)
char *captname, *p, *host_s;
char port[10];
su_addrinfo_t *ai = NULL, hints[1] = {{ 0 }};
unsigned len =0;
unsigned len =0, iport = 0;
if (mr->mr_capt_name && mr->mr_capt_sock && strcmp(capt, mr->mr_capt_name) == 0)
return n;
@ -173,17 +175,60 @@ int tport_open_log(tport_master_t *mr, tagi_t *tags)
/*the address contains a port number*/
*p = '\0';
p++;
iport = atoi(p);
if (atoi(p) <1024 || atoi(p)>65536)
if (iport <1024 || iport >65536)
{
su_log("invalid port number; must be in [1024,65536]\n");
return n;
}
strncpy(port, p, sizeof(port));
*p = '\0';
snprintf(port, sizeof(port), "%d", iport);
/* default values for capture protocol and agent id */
mr->mr_prot_ver = 3;
mr->mr_agent_id = 200;
/* get all params */
while(p)
{
/* check ; in the URL */
if( (p = strchr(p+1, ';')) == 0 ) {
break;
}
*p = '\0';
p++;
SU_DEBUG_7(("events HEP RRR DATA [%s]\n", p));
if(strncmp(p, "hep=",4) == 0) {
p+=4;
mr->mr_prot_ver = atoi(p);
/* hepv3 come later */
if (mr->mr_prot_ver < 1 || mr->mr_prot_ver > 3)
{
su_log("invalid hep version number; must be in [1-3]\n");
mr->mr_prot_ver = 3;
return n;
}
}
else if(strncmp(p, "capture_id=", 11) == 0) {
p+=11;
if((mr->mr_agent_id = atoi(p)) == 0)
{
mr->mr_agent_id = 200;
su_log("invalid capture id number; must be uint32 \n");
return n;
}
}
else {
su_log("unsupported capture param\n");
return n;
}
}
/* check if we have [] */
if (host_s[0] == '[') {
len = strlen(host_s + 1) - 1;
@ -211,7 +256,6 @@ int tport_open_log(tport_master_t *mr, tagi_t *tags)
hints->ai_socktype = SOCK_DGRAM;
hints->ai_protocol = IPPROTO_UDP;
if (su_getaddrinfo(host_s, port, hints, &ai)) {
su_perror("capture: su_getaddrinfo()");
return n;
@ -357,18 +401,72 @@ void tport_capt_msg(tport_t const *self, msg_t *msg, size_t n,
{
int buflen = 0, error;
char* buffer = NULL;
tport_master_t *mr;
assert(self);
mr = self->tp_master;
/* If we don't have socket, go out */
if (!mr->mr_capt_sock) {
su_log("error: capture socket is not open\n");
return;
}
switch(mr->mr_prot_ver)
{
case 3:
buflen = tport_capt_msg_hepv3(self, msg, n, iov, iovused, what, &buffer);
break;
case 2:
case 1:
buflen = tport_capt_msg_hepv2(self, msg, n, iov, iovused, what, &buffer);
break;
default:
su_log("error: unsupported hep version\n");
break;
}
if(buflen > 0) {
/* check if we have error i.e. capture server is down */
if ((error = su_soerror(mr->mr_capt_sock))) {
su_perror("error: tport_logging: capture socket error");
goto done;
}
su_send(mr->mr_capt_sock, buffer, buflen, 0);
}
done:
/* Now we release it */
if(buffer) free(buffer);
return;
}
/** Capture the data from the iovec */
int tport_capt_msg_hepv2 (tport_t const *self, msg_t *msg, size_t n,
su_iovec_t const iov[], size_t iovused, char const *what, char **buffer)
{
int buflen = 0;
su_sockaddr_t const *su, *su_self;
struct hep_hdr hep_header;
struct hep_timehdr hep_time = {0};
su_time_t now;
#if __sun__
struct hep_iphdr hep_ipheader = {{{{0}}}};
#else
struct hep_iphdr hep_ipheader = {{0}};
struct hep_iphdr hep_ipheader = {{0}};
#endif
#if SU_HAVE_IN6
struct hep_ip6hdr hep_ip6header = {{{{0}}}};
#endif
int eth_frame_len = 8000;
char* buffer;
int eth_frame_len = 16000;
size_t i, dst = 0;
tport_master_t *mr;
@ -382,14 +480,14 @@ void tport_capt_msg(tport_t const *self, msg_t *msg, size_t n,
/* If we don't have socket, go out */
if (!mr->mr_capt_sock) {
su_log("error: capture socket is not open\n");
return;
return 0;
}
/*buffer for ethernet frame*/
buffer = (void*)malloc(eth_frame_len);
*buffer = (void*)malloc(eth_frame_len);
/* VOIP Header */
hep_header.hp_v = 1;
hep_header.hp_v = mr->mr_prot_ver;
hep_header.hp_f = su->su_family;
/* Header Length */
hep_header.hp_l = sizeof(struct hep_hdr);
@ -423,19 +521,22 @@ void tport_capt_msg(tport_t const *self, msg_t *msg, size_t n,
hep_header.hp_dport = dst ? su->su_port : su_self->su_port;
hep_header.hp_sport = dst ? su_self->su_port : su->su_port;
if (hep_header.hp_v == 2){
hep_header.hp_l += sizeof(struct hep_timehdr);
}
/* Copy hepheader */
memset(buffer, '\0', eth_frame_len);
memcpy(buffer, &hep_header, sizeof(struct hep_hdr));
memset(*buffer, '\0', eth_frame_len);
memcpy(*buffer, &hep_header, sizeof(struct hep_hdr));
buflen = sizeof(struct hep_hdr);
if(su->su_family == AF_INET) {
memcpy(buffer + buflen, &hep_ipheader, sizeof(struct hep_iphdr));
memcpy(*buffer + buflen, &hep_ipheader, sizeof(struct hep_iphdr));
buflen += sizeof(struct hep_iphdr);
}
#if SU_HAVE_IN6
else if(su->su_family == AF_INET6) {
memcpy(buffer+buflen, &hep_ip6header, sizeof(struct hep_ip6hdr));
memcpy(*buffer+buflen, &hep_ip6header, sizeof(struct hep_ip6hdr));
buflen += sizeof(struct hep_ip6hdr);
}
#endif
@ -444,6 +545,23 @@ void tport_capt_msg(tport_t const *self, msg_t *msg, size_t n,
goto done;
}
/* copy time header */
if (hep_header.hp_v == 2) {
/* now */
now = su_now();
/* should check for ifdef HAVE_LOCALTIME_R instead -_- */
#if defined(HAVE_GETTIMEOFDAY) || defined(HAVE_CLOCK_MONOTONIC)
hep_time.tv_sec = (now.tv_sec - SU_TIME_EPOCH); /* see su_time0.c 'now' is not really 'now', so we decrease it by SU_TIME_EPOCH */
#else
hep_time.tv_sec = now.tv_sec;
#endif
hep_time.tv_usec = now.tv_usec;
hep_time.captid = mr->mr_agent_id;
memcpy((void*)*buffer+buflen, &hep_time, sizeof(struct hep_timehdr));
buflen += sizeof(struct hep_timehdr);
}
for (i = 0; i < iovused && n > 0; i++) {
size_t len = iov[i].mv_len;
if (len > n)
@ -452,26 +570,251 @@ void tport_capt_msg(tport_t const *self, msg_t *msg, size_t n,
if((buflen + len) > eth_frame_len)
break;
memcpy(buffer + buflen , (void*)iov[i].mv_base, len);
memcpy(*buffer + buflen , (void*)iov[i].mv_base, len);
buflen +=len;
n -= len;
}
/* check if we have error i.e. capture server is down */
if ((error = su_soerror(mr->mr_capt_sock))) {
su_perror("error: tport_logging: capture socket error");
goto done;
}
su_send(mr->mr_capt_sock, buffer, buflen, 0);
return buflen;
done:
/* Now we release it */
if(buffer) free(buffer);
return;
if(*buffer) {
free(*buffer);
*buffer = NULL;
}
return 0;
}
/** Capture the data from the iovec */
int tport_capt_msg_hepv3 (tport_t const *self, msg_t *msg, size_t n,
su_iovec_t const iov[], size_t iovused, char const *what, char **buffer)
{
su_sockaddr_t const *su, *su_self;
struct hep_generic *hg=NULL;
unsigned int buflen=0, iplen=0,tlen=0, payload_len = 0;
su_time_t now;
hep_chunk_ip4_t src_ip4, dst_ip4;
hep_chunk_t payload_chunk;
int orig_n = 0;
#if SU_HAVE_IN6
hep_chunk_ip6_t src_ip6, dst_ip6;
#endif
int eth_frame_len = 16000;
size_t i, dst = 0;
tport_master_t *mr;
assert(self); assert(msg);
su = msg_addr(msg);
su_self = self->tp_pri->pri_primary->tp_addr;
mr = self->tp_master;
/* If we don't have socket, go out */
if (!mr->mr_capt_sock) {
su_log("error: capture socket is not open\n");
return 0;
}
/*buffer for ethernet frame*/
hg = malloc(sizeof(struct hep_generic));
memset(hg, 0, sizeof(struct hep_generic));
/* header set */
memcpy(hg->header.id, "\x48\x45\x50\x33", 4);
/* IP proto */
hg->ip_family.chunk.vendor_id = htons(0x0000);
hg->ip_family.chunk.type_id = htons(0x0001);
hg->ip_family.data = su->su_family;
hg->ip_family.chunk.length = htons(sizeof(hg->ip_family));
/* PROTOCOL */
if(strcmp(self->tp_name->tpn_proto, "tcp") == 0) hg->ip_proto.data = IPPROTO_TCP;
else if(strcmp(self->tp_name->tpn_proto, "tls") == 0) hg->ip_proto.data = IPPROTO_IDP; /* FAKE*/
else if(strcmp(self->tp_name->tpn_proto, "sctp") == 0) hg->ip_proto.data = IPPROTO_SCTP;
else if(strcmp(self->tp_name->tpn_proto, "ws") == 0) hg->ip_proto.data = IPPROTO_TCP;
else if(strcmp(self->tp_name->tpn_proto, "wss") == 0) hg->ip_proto.data = IPPROTO_TCP;
else hg->ip_proto.data = IPPROTO_UDP; /* DEFAULT UDP */
/* Proto ID */
hg->ip_proto.chunk.vendor_id = htons(0x0000);
hg->ip_proto.chunk.type_id = htons(0x0002);
hg->ip_proto.chunk.length = htons(sizeof(hg->ip_proto));
/* Check destination */
if(strncmp("sent", what, 4) == 0) dst = 1;
/* copy destination and source IPs*/
if(su->su_family == AF_INET) {
/* SRC IP */
src_ip4.chunk.vendor_id = htons(0x0000);
src_ip4.chunk.type_id = htons(0x0003);
memcpy(dst ? &dst_ip4.data : &src_ip4.data, &su->su_sin.sin_addr.s_addr, sizeof(su->su_sin.sin_addr.s_addr));
src_ip4.chunk.length = htons(sizeof(src_ip4));
/* DST IP */
dst_ip4.chunk.vendor_id = htons(0x0000);
dst_ip4.chunk.type_id = htons(0x0004);
memcpy(dst ? &src_ip4.data : &dst_ip4.data, &su_self->su_sin.sin_addr.s_addr, sizeof(su_self->su_sin.sin_addr.s_addr));
dst_ip4.chunk.length = htons(sizeof(dst_ip4));
iplen = sizeof(dst_ip4) + sizeof(src_ip4);
}
#if SU_HAVE_IN6
else if(su->su_family == AF_INET6) {
/* SRC IPv6 */
src_ip6.chunk.vendor_id = htons(0x0000);
src_ip6.chunk.type_id = htons(0x0005);
memcpy(dst ? &dst_ip6.data : &src_ip6.data, &su->su_sin.sin_addr.s_addr, sizeof(su->su_sin.sin_addr.s_addr));
src_ip6.chunk.length = htons(sizeof(src_ip6));
/* DST IPv6 */
dst_ip6.chunk.vendor_id = htons(0x0000);
dst_ip6.chunk.type_id = htons(0x0006);
memcpy(dst ? &src_ip6.data : &dst_ip6.data, &su_self->su_sin.sin_addr.s_addr, sizeof(su_self->su_sin.sin_addr.s_addr));
dst_ip6.chunk.length = htons(sizeof(dst_ip6));
iplen = sizeof(dst_ip6) + sizeof(src_ip6);
}
#endif
else {
su_perror("error: tport_logging hepv3: capture: unsupported protocol family");
goto done;
}
/* SRC PORT */
hg->src_port.chunk.vendor_id = htons(0x0000);
hg->src_port.chunk.type_id = htons(0x0007);
hg->src_port.data = dst ? htons(su->su_port) : htons(su_self->su_port);
hg->src_port.chunk.length = htons(sizeof(hg->src_port));
/* DST PORT */
hg->dst_port.chunk.vendor_id = htons(0x0000);
hg->dst_port.chunk.type_id = htons(0x0008);
hg->dst_port.data = dst ? htons(su_self->su_port) : htons(su->su_port);
hg->dst_port.chunk.length = htons(sizeof(hg->dst_port));
/* TIMESTAMP SEC */
hg->time_sec.chunk.vendor_id = htons(0x0000);
hg->time_sec.chunk.type_id = htons(0x0009);
hg->time_sec.chunk.length = htons(sizeof(hg->time_sec));
now = su_now();
/* should check for ifdef HAVE_LOCALTIME_R instead -_- */
#if defined(HAVE_GETTIMEOFDAY) || defined(HAVE_CLOCK_MONOTONIC)
hg->time_sec.data = htonl(now.tv_sec - SU_TIME_EPOCH); /* see su_time0.c 'now' is not really 'now', so we decrease it by SU_TIME_EPOCH */
#else
hg->time_sec.data = htonl(now.tv_sec);
#endif
/* TIMESTAMP USEC */
hg->time_usec.chunk.vendor_id = htons(0x0000);
hg->time_usec.chunk.type_id = htons(0x000a);
hg->time_usec.data = htonl(now.tv_usec);
hg->time_usec.chunk.length = htons(sizeof(hg->time_usec));
/* Protocol TYPE */
hg->proto_t.chunk.vendor_id = htons(0x0000);
hg->proto_t.chunk.type_id = htons(0x000b);
hg->proto_t.data = 0x001; //SIP
hg->proto_t.chunk.length = htons(sizeof(hg->proto_t));
/* Capture ID */
hg->capt_id.chunk.vendor_id = htons(0x0000);
hg->capt_id.chunk.type_id = htons(0x000c);
hg->capt_id.data = htons(mr->mr_agent_id);
hg->capt_id.chunk.length = htons(sizeof(hg->capt_id));
/* Payload caclulation */
orig_n = n;
for (i = 0; i < iovused && n > 0; i++) {
size_t len = iov[i].mv_len;
if (len > n) len = n;
if((payload_len + len) > eth_frame_len) break;
payload_len +=len;
n -= len;
}
/* restore n */
n = orig_n;
/* Payload */
payload_chunk.vendor_id = htons(0x0000);
payload_chunk.type_id = htons(0x000f);
payload_chunk.length = htons(sizeof(payload_chunk) + payload_len);
tlen = sizeof(struct hep_generic) + payload_len + iplen + sizeof(hep_chunk_t);
/* total */
hg->header.length = htons(tlen);
*buffer = (void*)malloc(tlen);
if (*buffer==NULL){
su_perror("error: tport_logging hepv3: no memory for buffer");
goto done;
}
memcpy((void*) *buffer, hg, sizeof(struct hep_generic));
buflen = sizeof(struct hep_generic);
/* IPv4 */
if(su->su_family == AF_INET) {
/* SRC IP */
memcpy((void*) *buffer+buflen, &src_ip4, sizeof(struct hep_chunk_ip4));
buflen += sizeof(struct hep_chunk_ip4);
memcpy((void*) *buffer+buflen, &dst_ip4, sizeof(struct hep_chunk_ip4));
buflen += sizeof(struct hep_chunk_ip4);
}
#if SU_HAVE_IN6
/* IPv6 */
else if(su->su_family == AF_INET6) {
/* SRC IPv6 */
memcpy((void*) *buffer+buflen, &src_ip4, sizeof(struct hep_chunk_ip6));
buflen += sizeof(struct hep_chunk_ip6);
memcpy((void*) *buffer+buflen, &dst_ip6, sizeof(struct hep_chunk_ip6));
buflen += sizeof(struct hep_chunk_ip6);
}
#endif
/* PAYLOAD CHUNK */
memcpy((void*) *buffer+buflen, &payload_chunk, sizeof(struct hep_chunk));
buflen += sizeof(struct hep_chunk);
/* PAYLOAD */
for (i = 0; i < iovused && n > 0; i++) {
size_t len = iov[i].mv_len;
if (len > n) len = n;
/* if the packet too big for us */
if((buflen + len) > eth_frame_len)
break;
memcpy(*buffer + buflen , (void*)iov[i].mv_base, len);
buflen +=len;
n -= len;
}
return buflen;
done:
/* Now we release it */
if(hg) free(hg);
return 0;
}
/** Log the message. */
void tport_log_msg(tport_t *self, msg_t *msg,
char const *what, char const *via,

View File

@ -1103,6 +1103,12 @@ SWITCH_DECLARE(switch_status_t) switch_socket_accept(switch_socket_t ** new_sock
*/
SWITCH_DECLARE(switch_status_t) switch_socket_connect(switch_socket_t *sock, switch_sockaddr_t *sa);
/**
* Get socket fd for the switch socket passed
* @param sock The socket we wish to have fd
*/
SWITCH_DECLARE(int) switch_socket_fd_get(switch_socket_t *sock);
SWITCH_DECLARE(uint16_t) switch_sockaddr_get_port(switch_sockaddr_t *sa);
SWITCH_DECLARE(const char *) switch_get_addr(char *buf, switch_size_t len, switch_sockaddr_t *in);
SWITCH_DECLARE(switch_status_t) switch_getnameinfo(char **hostname, switch_sockaddr_t *sa, int32_t flags);

View File

@ -2654,6 +2654,19 @@ SWITCH_DECLARE(switch_status_t) switch_core_del_registration(const char *user, c
*/
SWITCH_DECLARE(switch_status_t) switch_core_expire_registration(int force);
/*!
\brief Get RTP port range start value
\param[in] void
\param[out] RTP port range start value
*/
SWITCH_DECLARE(uint16_t) switch_core_get_rtp_port_range_start_port(void);
/*!
\brief Get RTP port range end value
\param[in] void
\param[out] RTP port range end value
*/
SWITCH_DECLARE(uint16_t) switch_core_get_rtp_port_range_end_port(void);
SWITCH_DECLARE(char *) switch_say_file_handle_get_variable(switch_say_file_handle_t *sh, const char *var);
SWITCH_DECLARE(char *) switch_say_file_handle_get_path(switch_say_file_handle_t *sh);

View File

@ -278,6 +278,7 @@ SWITCH_DECLARE(void) switch_core_media_resume(switch_core_session_t *session);
SWITCH_DECLARE(void) switch_core_media_init(void);
SWITCH_DECLARE(void) switch_core_media_deinit(void);
SWITCH_DECLARE(void) switch_core_media_set_stats(switch_core_session_t *session);
SWITCH_DECLARE(void) switch_core_media_sync_stats(switch_core_session_t *session);
SWITCH_DECLARE(void) switch_core_session_wake_video_thread(switch_core_session_t *session);
SWITCH_DECLARE(void) switch_core_session_clear_crypto(switch_core_session_t *session);

View File

@ -97,7 +97,13 @@ typedef struct switch_png_s {
int h;
} switch_png_t;
typedef enum {
SRM_NONE = 0, // No rotation.
SRM_90 = 90, // Rotate 90 degrees clockwise.
SRM_180 = 180, // Rotate 180 degrees.
SRM_270 = 270, // Rotate 270 degrees clockwise.
} switch_image_rotation_mode_t;
/*!\brief Open a descriptor, allocating storage for the underlying image
*
@ -209,7 +215,7 @@ SWITCH_DECLARE(void) switch_img_patch_rect(switch_image_t *IMG, int X, int Y, sw
*/
SWITCH_DECLARE(void) switch_img_copy(switch_image_t *img, switch_image_t **new_img);
SWITCH_DECLARE(void) switch_img_rotate_copy(switch_image_t *img, switch_image_t **new_img, switch_image_rotation_mode_t mode);
/*!\brief Flip the image vertically (top for bottom)
*
@ -220,7 +226,7 @@ SWITCH_DECLARE(void) switch_img_copy(switch_image_t *img, switch_image_t **new_i
*
* \return 0 if the requested rectangle is valid, nonzero otherwise.
*/
SWITCH_DECLARE(void) switch_img_flip(switch_image_t *img);
SWITCH_DECLARE(void) switch_img_rotate(switch_image_t **img, switch_image_rotation_mode_t mode);
/*!\brief Close an image descriptor
*

View File

@ -311,6 +311,8 @@ SWITCH_DECLARE(uint8_t) switch_rtp_ready(switch_rtp_t *rtp_session);
*/
SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session);
SWITCH_DECLARE(switch_status_t) switch_rtp_sync_stats(switch_rtp_t *rtp_session);
/*!
\brief Acvite ICE on an RTP session
\return SWITCH_STATUS_SUCCESS

View File

@ -948,13 +948,6 @@ typedef struct {
#pragma pack(push, r1, 1)
#endif
typedef struct switch_rtcp_sdes_unit_s {
unsigned char type;
unsigned char length;
char value[];
} switch_rtcp_sdes_unit_t;
#if SWITCH_BYTE_ORDER == __BIG_ENDIAN
typedef struct switch_rtcp_hdr_s {
unsigned version:2; /* protocol version */
@ -1049,6 +1042,7 @@ typedef enum {
SWITCH_MESSAGE_INDICATE_UNBRIDGE,
SWITCH_MESSAGE_INDICATE_TRANSFER,
SWITCH_MESSAGE_INDICATE_RINGING,
SWITCH_MESSAGE_INDICATE_ALERTING,
SWITCH_MESSAGE_INDICATE_MEDIA,
SWITCH_MESSAGE_INDICATE_3P_MEDIA,
SWITCH_MESSAGE_INDICATE_NOMEDIA,
@ -1358,6 +1352,8 @@ CF_STOP_BROADCAST - Signal to stop broadcast
CF_AUDIO_PAUSE - Audio is not ready to read/write
CF_VIDEO_PAUSE - Video is not ready to read/write
CF_MEDIA_SET - Session has read codec assigned
</pre>
*/

View File

@ -767,6 +767,9 @@ static switch_status_t consume_h264_bitstream(h264_codec_context_t *context, swi
if (pkt->size > 0) av_packet_unref(pkt);
switch_clear_flag(frame, SFF_CNG);
frame->m = 1;
return SWITCH_STATUS_SUCCESS;
}

View File

@ -11,7 +11,6 @@
#include <stdlib.h>
#include <assert.h>
#ifndef INT16_MIN
#define INT16_MIN (-32767-1)
@ -95,7 +94,6 @@ extern size_t next_power_of_2(size_t v);
(bf)->buf_len = CALC_BUFF_LEN((fl), (bl)); \
(bf)->mask = (bf)->buf_len - 1; \
(bf)->buf = (BUFF_TYPE *) switch_core_session_alloc(s, (bf)->buf_len * sizeof(BUFF_TYPE)); \
assert((bf)->buf != NULL); \
(bf)->pos = 0; \
(bf)->lpos = 0; \
(bf)->backlog = 0; \

View File

@ -1,6 +1,6 @@
#ifndef __AVMD_DESA2_TWEAKED_H__
#include <switch.h>
#include <stdio.h>
#ifdef WIN32
#include <float.h>
@ -16,12 +16,8 @@
#include "avmd_fast_acosf.h"
#endif
#include <switch.h>
double
avmd_desa2_tweaked(circ_buffer_t *b, size_t i,
switch_core_session_t *session)
avmd_desa2_tweaked(circ_buffer_t *b, size_t i)
{
double d;
double n;

View File

@ -35,8 +35,7 @@
* from this partial result using
* 0.5 * acos(n/d)
*/
double avmd_desa2_tweaked(circ_buffer_t *b, size_t i,
switch_core_session_t *session);
double avmd_desa2_tweaked(circ_buffer_t *b, size_t i);
#endif /* __AVMD_DESA2_TWEAKED_H__ */

View File

@ -2,7 +2,11 @@
* @brief Options controlling avmd module.
*
* @author Eric des Courtis
* @par Modifications: Piotr Gregor < piotrek.gregor gmail.com >
*
* Contributor(s):
*
* Piotr Gregor <piotrek.gregor gmail.com>:
* Eric des Courtis <eric.des.courtis@benbria.com>
*/
@ -12,7 +16,7 @@
/* define/undefine this to enable/disable printing of avmd
* intermediate computations to log */
/*#define AVMD_DEBUG */
/*#define AVMD_DEBUG*/
/* define/undef this to enable/disable reporting of beep
* detection status after session ended */
@ -30,7 +34,7 @@
#define AVMD_REQUIRE_CONTINUOUS_STREAK
/* define number of samples to skip starting from the beginning
* of frame and after reset */
* of the frame and after reset */
#define AVMD_SAMLPE_TO_SKIP_N 6
/* define/undefine this to enable/disable simplified estimation
@ -38,11 +42,11 @@
* in the range x=[0,PI/2] */
#define AVMD_SIMPLIFIED_ESTIMATION
/* define/undefine to enable/disable avmd on incoming audio */
#define AVMD_INBOUND_CHANNEL
/* define/undefine to enable/disable avmd on internal channel */
/*#define AVMD_INBOUND_CHANNEL*/
/* define/undefine to enable/disable avmd on outgoing audio */
/*#define AVMD_OUTBOUND_CHANNEL*/
/* define/undefine to enable/disable avmd on external channel */
#define AVMD_OUTBOUND_CHANNEL
#endif /* __AVMD_OPTIONS_H__ */

View File

@ -32,8 +32,6 @@ typedef struct {
(void)memset((b), 0, sizeof(sma_buffer_t)); \
(b)->len = (l); \
(b)->data = (BUFF_TYPE *)switch_core_session_alloc((s), sizeof(BUFF_TYPE) * (l)); \
assert((b)->data != NULL); \
(void)memset((b)->data, 0, sizeof(BUFF_TYPE) * (l)); \
(b)->sma = 0.0; \
(b)->pos = 0; \
(b)->lpos = 0; \

View File

@ -126,7 +126,7 @@
<ItemGroup>
<ClInclude Include="avmd_amplitude.h" />
<ClInclude Include="avmd_buffer.h" />
<ClInclude Include="avmd_desa2.h" />
<ClInclude Include="avmd_desa2_tweaked.h" />
<ClInclude Include="avmd_fast_acosf.h" />
<ClInclude Include="avmd_goertzel.h" />
<ClInclude Include="avmd_options.h" />
@ -136,7 +136,7 @@
<ItemGroup>
<ClCompile Include="avmd_amplitude.c" />
<ClCompile Include="avmd_buffer.c" />
<ClCompile Include="avmd_desa2.c" />
<ClCompile Include="avmd_desa2_tweaked.c" />
<ClCompile Include="avmd_fast_acosf.c" />
<ClCompile Include="avmd_goertzel.c" />
<ClCompile Include="mod_avmd.c" />
@ -154,4 +154,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

File diff suppressed because it is too large Load Diff

View File

@ -1783,6 +1783,9 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
/* This is used for the waiting caller to quit waiting for a agent */
switch_channel_set_variable(member_channel, "cc_agent_found", "true");
switch_channel_set_variable(member_channel, "cc_agent_uuid", agent_uuid);
if (switch_true(switch_channel_get_variable(member_channel, SWITCH_BYPASS_MEDIA_AFTER_BRIDGE_VARIABLE))) {
switch_channel_set_flag(member_channel, CF_BYPASS_MEDIA_AFTER_BRIDGE);
}
switch_ivr_uuid_bridge(h->member_session_uuid, switch_core_session_get_uuid(agent_session));
switch_channel_wait_for_flag(agent_channel, CF_BRIDGED, SWITCH_TRUE, 1000, NULL);

View File

@ -91,7 +91,7 @@ api_command_t conference_api_sub_commands[] = {
{"pin", (void_fn_t) & conference_api_sub_pin, CONF_API_SUB_ARGS_SPLIT, "pin", "<pin#>"},
{"nopin", (void_fn_t) & conference_api_sub_pin, CONF_API_SUB_ARGS_SPLIT, "nopin", ""},
{"get", (void_fn_t) & conference_api_sub_get, CONF_API_SUB_ARGS_SPLIT, "get", "<parameter-name>"},
{"set", (void_fn_t) & conference_api_sub_set, CONF_API_SUB_ARGS_SPLIT, "set", "<max_members|sound_prefix|caller_id_name|caller_id_number|endconference_grace_time> <value>"},
{"set", (void_fn_t) & conference_api_sub_set, CONF_API_SUB_ARGS_SPLIT, "set", "<max_members|min_members|wait_min_members_timeout|wait_mod_timeout|sound_prefix|caller_id_name|caller_id_number|endconference_grace_time> <value>"},
{"file-vol", (void_fn_t) & conference_api_sub_file_vol, CONF_API_SUB_ARGS_SPLIT, "file-vol", "<vol#>"},
{"floor", (void_fn_t) & conference_api_sub_floor, CONF_API_SUB_MEMBER_TARGET, "floor", "<member_id|last>"},
{"vid-floor", (void_fn_t) & conference_api_sub_vid_floor, CONF_API_SUB_MEMBER_TARGET, "vid-floor", "<member_id|last> [force]"},
@ -658,29 +658,37 @@ switch_status_t conference_api_sub_kick(conference_member_t *member, switch_stre
switch_status_t conference_api_sub_vid_flip(conference_member_t *member, switch_stream_handle_t *stream, void *data)
{
switch_event_t *event;
char *arg = (char *) data;
if (member == NULL) {
return SWITCH_STATUS_GENERR;
}
if (conference_utils_member_test_flag(member, MFLAG_FLIP_VIDEO)) {
if (conference_utils_member_test_flag(member, MFLAG_FLIP_VIDEO) && !arg) {
conference_utils_member_clear_flag_locked(member, MFLAG_FLIP_VIDEO);
conference_utils_member_clear_flag_locked(member, MFLAG_ROTATE_VIDEO);
} else {
conference_utils_member_set_flag_locked(member, MFLAG_FLIP_VIDEO);
if (arg) {
if (!strcasecmp(arg, "rotate")) {
conference_utils_member_set_flag_locked(member, MFLAG_ROTATE_VIDEO);
} else if (switch_is_number(arg)) {
int num = atoi(arg);
if (num == 0 || num == 90 || num == 180 || num == 270) {
member->flip = num;
}
}
} else {
member->flip = 180;
}
}
if (stream != NULL) {
stream->write_function(stream, "OK flipped %u\n", member->id);
}
if (member->conference && test_eflag(member->conference, EFLAG_KICK_MEMBER)) {
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
conference_member_add_event_data(member, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "vid-flip-member");
switch_event_fire(&event);
}
}
return SWITCH_STATUS_SUCCESS;
}
@ -1309,6 +1317,7 @@ switch_status_t conference_api_sub_vid_layout(conference_obj_t *conference, swit
if (vlayout) {
stream->write_function(stream, "Change canvas %d to layout [%s]\n", idx + 1, vlayout->name);
conference->canvases[idx]->new_vlayout = vlayout;
conference->canvases[idx]->video_layout_group = NULL;
} else if (group_name) {
conference->canvases[idx]->video_layout_group = switch_core_strdup(conference->pool, group_name);
conference_utils_set_flag(conference, CFLAG_REFRESH_LAYOUT);
@ -2730,6 +2739,15 @@ switch_status_t conference_api_sub_get(conference_obj_t *conference,
} else if (strcasecmp(argv[2], "count_ghosts") == 0) {
stream->write_function(stream, "%d",
conference->count_ghosts);
} else if (strcasecmp(argv[2], "min_members") == 0) {
stream->write_function(stream, "%d",
conference->min_members);
} else if (strcasecmp(argv[2], "wait_min_members_timeout") == 0) {
stream->write_function(stream, "%d",
conference->wait_min_members_timeout);
} else if (strcasecmp(argv[2], "wait_mod_timeout") == 0) {
stream->write_function(stream, "%d",
conference->wait_mod_timeout);
} else if (strcasecmp(argv[2], "max_members") == 0) {
stream->write_function(stream, "%d",
conference->max_members);
@ -2784,6 +2802,30 @@ switch_status_t conference_api_sub_set(conference_obj_t *conference,
} else {
ret_status = SWITCH_STATUS_FALSE;
}
} else if (strcasecmp(argv[2], "min_members") == 0) {
int new_min = atoi(argv[3]);
if (new_min >= 0 && (!conference->count || conference_utils_test_flag(conference, CFLAG_WAIT_MIN_MEMBERS))) {
stream->write_function(stream, "%d", conference->min_members);
conference->min_members = new_min;
} else {
ret_status = SWITCH_STATUS_FALSE;
}
} else if (strcasecmp(argv[2], "wait_min_members_timeout") == 0) {
int32_t new_min = atoll(argv[3]);
if (new_min >= 0 && (!conference->count || conference_utils_test_flag(conference, CFLAG_WAIT_MIN_MEMBERS))) {
stream->write_function(stream, "%d", conference->wait_min_members_timeout);
conference->wait_min_members_timeout = new_min;
} else {
ret_status = SWITCH_STATUS_FALSE;
}
} else if (strcasecmp(argv[2], "wait_mod_timeout") == 0) {
int32_t new_timeout = atoll(argv[3]);
if (new_timeout >= 0 && conference_utils_test_flag(conference, CFLAG_WAIT_MOD)) {
stream->write_function(stream, "%d", conference->wait_mod_timeout);
conference->wait_mod_timeout = new_timeout;
} else {
ret_status = SWITCH_STATUS_FALSE;
}
} else if (strcasecmp(argv[2], "sound_prefix") == 0) {
stream->write_function(stream, "%s",conference->sound_prefix);
conference->sound_prefix = switch_core_strdup(conference->pool, argv[3]);

View File

@ -969,7 +969,8 @@ void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, void *ob
/* skip frames that are not actual media or when we are muted or silent */
if ((conference_utils_member_test_flag(member, MFLAG_TALKING) || member->energy_level == 0 || conference_utils_test_flag(member->conference, CFLAG_AUDIO_ALWAYS))
&& conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK) && !conference_utils_test_flag(member->conference, CFLAG_WAIT_MOD)
&& (member->conference->count > 1 || (member->conference->record_count && member->conference->count >= member->conference->min_recording_participants))) {
&& (!conference_utils_test_flag(member->conference, CFLAG_WAIT_MIN_MEMBERS) || (member->conference->record_count && member->conference->count >= member->conference->min_recording_participants))) {
switch_audio_resampler_t *read_resampler = member->read_resampler;
void *data;
uint32_t datalen;
@ -1377,6 +1378,25 @@ void conference_loop_output(conference_member_t *member)
switch_cond_next();
}
if (member->conference->wait_min_members_timeout && switch_epoch_time_now(NULL) - member->join_time >= member->conference->wait_min_members_timeout &&
conference_utils_test_flag(member->conference, CFLAG_WAIT_MIN_MEMBERS))
{
if (!zstr(member->conference->wait_min_members_timeout_message)) {
conference_member_play_file(member, member->conference->wait_min_members_timeout_message, 0, SWITCH_TRUE);
}
member->loop_loop = SWITCH_FALSE;
break;
}
if (member->conference->wait_mod_timeout && switch_epoch_time_now(NULL) - member->join_time >= member->conference->wait_mod_timeout &&
conference_utils_test_flag(member->conference, CFLAG_WAIT_MOD))
{
if (!zstr(member->conference->wait_mod_timeout_message)) {
conference_member_play_file(member, member->conference->wait_mod_timeout_message, 0, SWITCH_TRUE);
}
member->loop_loop = SWITCH_FALSE;
break;
}
} /* Rinse ... Repeat */
end:

View File

@ -724,6 +724,9 @@ switch_status_t conference_member_add(conference_obj_t *conference, conference_m
conference->count_ghosts++;
} else {
conference->count++;
if (conference->min_members && conference->count >= conference->min_members) {
conference_utils_clear_flag_locked(conference, CFLAG_WAIT_MIN_MEMBERS);
}
}
if (conference_utils_member_test_flag(member, MFLAG_ENDCONF)) {
@ -814,7 +817,7 @@ switch_status_t conference_member_add(conference_obj_t *conference, conference_m
conference_utils_clear_flag(conference, CFLAG_WAIT_MOD);
}
if (conference->count > 1) {
if (!conference_utils_test_flag(conference, CFLAG_WAIT_MIN_MEMBERS)) {
if ((conference->moh_sound && !conference_utils_test_flag(conference, CFLAG_WAIT_MOD)) ||
(conference_utils_test_flag(conference, CFLAG_WAIT_MOD) && !switch_true(switch_channel_get_variable(channel, "conference_permanent_wait_mod_moh")))) {
/* stop MoH if any */
@ -826,9 +829,9 @@ switch_status_t conference_member_add(conference_obj_t *conference, conference_m
if (conference_utils_test_flag(conference, CFLAG_ENTER_SOUND) && !conference_utils_member_test_flag(member, MFLAG_SILENT)) {
if (!zstr(enter_sound)) {
conference_file_play(conference, (char *)enter_sound, CONF_DEFAULT_LEADIN,
switch_core_session_get_channel(member->session), 0);
switch_core_session_get_channel(member->session), !conference_utils_test_flag(conference, CFLAG_WAIT_MOD) ? 0 : 1);
} else {
conference_file_play(conference, conference->enter_sound, CONF_DEFAULT_LEADIN, switch_core_session_get_channel(member->session), 0);
conference_file_play(conference, conference->enter_sound, CONF_DEFAULT_LEADIN, switch_core_session_get_channel(member->session), !conference_utils_test_flag(conference, CFLAG_WAIT_MOD) ? 0 : 1);
}
}
}
@ -1191,6 +1194,13 @@ switch_status_t conference_member_del(conference_obj_t *conference, conference_m
if (!--conference->end_count) {
//conference_utils_set_flag_locked(conference, CFLAG_DESTRUCT);
conference->endconference_time = switch_epoch_time_now(NULL);
if (conference_utils_member_test_flag(member, MFLAG_MOD) && !zstr(conference->endconf_mod_exit_message)) {
conference_file_play(conference, conference->endconf_mod_exit_message, 0, channel, 0);
} else {
if (!zstr(conference->endconf_message)) {
conference_file_play(conference, conference->endconf_message, 0, channel, 0);
}
}
}
}
@ -1208,7 +1218,7 @@ switch_status_t conference_member_del(conference_obj_t *conference, conference_m
if (!exit_sound && conference->exit_sound && conference_utils_test_flag(conference, CFLAG_EXIT_SOUND) && !conference_utils_member_test_flag(member, MFLAG_SILENT)) {
conference_file_play(conference, conference->exit_sound, 0, channel, 0);
}
if (conference->count == 1 && conference->alone_sound && !conference_utils_test_flag(conference, CFLAG_WAIT_MOD) && !conference_utils_member_test_flag(member, MFLAG_GHOST)) {
if (!conference_utils_test_flag(conference, CFLAG_WAIT_MIN_MEMBERS) && conference->alone_sound && !conference_utils_test_flag(conference, CFLAG_WAIT_MOD) && !conference_utils_member_test_flag(member, MFLAG_GHOST)) {
conference_file_stop(conference, FILE_STOP_ASYNC);
conference_file_play(conference, conference->alone_sound, 0, channel, 0);
}

View File

@ -499,6 +499,7 @@ void conference_video_scale_and_patch(mcu_layer_t *layer, switch_image_t *ximg,
switch_img_fit(&layer->logo_img, ew, eh, layer->logo_fit);
switch_img_find_position(layer->logo_pos, ew, eh, layer->logo_img->d_w, layer->logo_img->d_h, &ex, &ey);
switch_img_patch(IMG, layer->logo_img, layer->x_pos + ex + layer->geometry.border, layer->y_pos + ey + layer->geometry.border);
if (layer->logo_text_img) {
int tx = 0, ty = 0;
@ -3728,12 +3729,26 @@ switch_status_t conference_video_thread_callback(switch_core_session_t *session,
conference_utils_member_test_flag(member, MFLAG_CAN_BE_SEEN) &&
switch_queue_size(member->video_queue) < member->conference->video_fps.fps * 2 &&
!member->conference->playing_video_file) {
switch_img_copy(frame->img, &img_copy);
if (conference_utils_member_test_flag(member, MFLAG_FLIP_VIDEO)) {
switch_img_flip(img_copy);
}
if (conference_utils_member_test_flag(member, MFLAG_FLIP_VIDEO) || conference_utils_member_test_flag(member, MFLAG_ROTATE_VIDEO)) {
if (conference_utils_member_test_flag(member, MFLAG_ROTATE_VIDEO)) {
if (member->flip_count++ > (int)(member->conference->video_fps.fps / 2)) {
member->flip += 90;
if (member->flip > 270) {
member->flip = 0;
}
member->flip_count = 0;
}
switch_img_rotate_copy(frame->img, &img_copy, member->flip);
} else {
switch_img_rotate_copy(frame->img, &img_copy, member->flip);
}
} else {
switch_img_copy(frame->img, &img_copy);
}
if (switch_queue_trypush(member->video_queue, img_copy) != SWITCH_STATUS_SUCCESS) {
switch_img_free(&img_copy);
}

View File

@ -318,14 +318,14 @@ void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, void *ob
if (conference->perpetual_sound && !conference->async_fnode) {
conference_file_play(conference, conference->perpetual_sound, CONF_DEFAULT_LEADIN, NULL, 1);
} else if (conference->moh_sound && ((nomoh == 0 && conference->count == 1)
} else if (conference->moh_sound && ((nomoh == 0 && conference_utils_test_flag(conference, CFLAG_WAIT_MIN_MEMBERS))
|| conference_utils_test_flag(conference, CFLAG_WAIT_MOD)) && !conference->async_fnode && !conference->fnode) {
conference_file_play(conference, conference->moh_sound, CONF_DEFAULT_LEADIN, NULL, 1);
}
/* Find if no one talked for more than x number of second */
if (conference->terminate_on_silence && conference->count > 1) {
if (conference->terminate_on_silence && !conference_utils_test_flag(conference, CFLAG_WAIT_MIN_MEMBERS)) {
int is_talking = 0;
for (imember = conference->members; imember; imember = imember->next) {
@ -1102,6 +1102,21 @@ void conference_xlist(conference_obj_t *conference, switch_xml_t x_conference, i
switch_xml_set_attr_d(x_conference, "enter_sound", "true");
}
if (conference->min_members > 0) {
switch_snprintf(i, sizeof(i), "%d", conference->min_members);
switch_xml_set_attr_d(x_conference, "min_members", ival);
}
if (conference->wait_min_members_timeout > 0) {
switch_snprintf(i, sizeof(i), "%d", conference->wait_min_members_timeout);
switch_xml_set_attr_d(x_conference, "wait_min_members_timeout", ival);
}
if (conference->wait_mod_timeout > 0) {
switch_snprintf(i, sizeof(i), "%d", conference->wait_mod_timeout);
switch_xml_set_attr_d(x_conference, "wait_mod_timeout", ival);
}
if (conference->max_members > 0) {
switch_snprintf(i, sizeof(i), "%d", conference->max_members);
switch_xml_set_attr_d(x_conference, "max_members", ival);
@ -1823,9 +1838,12 @@ SWITCH_STANDARD_APP(conference_function)
/* if the conference exists, get the pointer to it */
if (!conference) {
const char *max_members_str;
const char *endconference_grace_time_str;
const char *auto_record_str;
const char *max_members_str = NULL;
const char *endconference_grace_time_str = NULL;
const char *auto_record_str = NULL;
const char *min_members_str = NULL;
const char *wait_min_members_timeout_str = NULL;
const char *wait_mod_timeout_str = NULL;
/* no conference yet, so check for join-only flag */
if (flags_str) {
@ -1838,9 +1856,9 @@ SWITCH_STANDARD_APP(conference_function)
}
if (mflags[MFLAG_JOIN_ONLY]) {
switch_event_t *event;
switch_xml_t jos_xml;
char *val;
switch_event_t *event = NULL;
switch_xml_t jos_xml = NULL;
char *val = NULL;
/* send event */
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT);
switch_channel_event_set_basic_data(channel, event);
@ -1899,9 +1917,48 @@ SWITCH_STANDARD_APP(conference_function)
/* Set the minimum number of members (once you go above it you cannot go below it) */
conference->min = 1;
/* check for variable used to specify override for min_members */
if (!zstr(min_members_str = switch_channel_get_variable(channel, "conference_min_members"))) {
uint32_t min_members_val = 0;
errno = 0; /* sanity first */
min_members_val = strtol(min_members_str, NULL, 0); /* base 0 lets 0x... for hex 0... for octal and base 10 otherwise through */
if (errno == ERANGE || errno == EINVAL || (int32_t) min_members_val < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"conference_min_members variable %s is invalid, not setting a limit\n", min_members_str);
} else {
conference->min_members = min_members_val;
}
}
/* check for variable used to specify override for wait_min_members_timeout */
if (!zstr(wait_min_members_timeout_str = switch_channel_get_variable(channel, "conference_wait_min_members_timeout"))) {
int32_t wait_min_members_timeout_val = 0;
errno = 0; /* sanity first */
wait_min_members_timeout_val = strtol(wait_min_members_timeout_str, NULL, 0); /* base 0 lets 0x... for hex 0... for octal and base 10 otherwise through */
if (errno == ERANGE || errno == EINVAL || (int32_t) wait_min_members_timeout_val < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"conference_wait_min_members_timeout variable %s is invalid, not setting a limit\n", wait_min_members_timeout_str);
} else {
conference->wait_min_members_timeout = wait_min_members_timeout_val;
}
}
/* check for variable used to specify override for wait_min_members_timeout */
if (!zstr(wait_mod_timeout_str = switch_channel_get_variable(channel, "conference_wait_mod_timeout"))) {
int32_t wait_mod_timeout_val = 0;
errno = 0; /* sanity first */
wait_mod_timeout_val = strtol(wait_mod_timeout_str, NULL, 0); /* base 0 lets 0x... for hex 0... for octal and base 10 otherwise through */
if (errno == ERANGE || errno == EINVAL || (int32_t) wait_mod_timeout_val < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"conference_wait_mod_timeout variable %s is invalid, not setting a limit\n", wait_mod_timeout_str);
} else {
conference->wait_mod_timeout = wait_mod_timeout_val;
}
}
/* check for variable used to specify override for max_members */
if (!zstr(max_members_str = switch_channel_get_variable(channel, "conference_max_members"))) {
uint32_t max_members_val;
uint32_t max_members_val = 0;
errno = 0; /* sanity first */
max_members_val = strtol(max_members_str, NULL, 0); /* base 0 lets 0x... for hex 0... for octal and base 10 otherwise through */
if (errno == ERANGE || errno == EINVAL || (int32_t) max_members_val < 0 || max_members_val == 1) {
@ -1914,7 +1971,7 @@ SWITCH_STANDARD_APP(conference_function)
/* check for variable to override endconference_grace_time profile value */
if (!zstr(endconference_grace_time_str = switch_channel_get_variable(channel, "conference_endconference_grace_time"))) {
uint32_t grace_time_val;
uint32_t grace_time_val = 0;
errno = 0; /* sanity first */
grace_time_val = strtol(endconference_grace_time_str, NULL, 0); /* base 0 lets 0x... for hex 0... for octal and base 10 otherwise through */
if (errno == ERANGE || errno == EINVAL || (int32_t) grace_time_val < 0) {
@ -1930,6 +1987,10 @@ SWITCH_STANDARD_APP(conference_function)
/* Indicate the conference is dynamic */
conference_utils_set_flag_locked(conference, CFLAG_DYNAMIC);
if (conference->min_members) {
conference_utils_set_flag_locked(conference, CFLAG_WAIT_MIN_MEMBERS);
}
/* acquire a read lock on the thread so it can't leave without us */
if (switch_thread_rwlock_tryrdlock(conference->rwlock) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Read Lock Fail\n");
@ -1963,7 +2024,7 @@ SWITCH_STANDARD_APP(conference_function)
int pin_retries = conference->pin_retries;
int pin_valid = 0;
switch_status_t status = SWITCH_STATUS_SUCCESS;
char *supplied_pin_value;
char *supplied_pin_value = NULL;
/* Answer the channel */
switch_channel_answer(channel);
@ -2383,6 +2444,13 @@ conference_obj_t *conference_new(char *name, conference_xml_cfg_t cfg, switch_co
char *perpetual_sound = NULL;
char *moh_sound = NULL;
char *outcall_templ = NULL;
char *wait_min_members_timeout_message = NULL;
char *wait_mod_timeout_message = NULL;
char *endconf_mod_exit_message = NULL;
char *endconf_message = NULL;
uint32_t min_members = 0;
int32_t wait_min_members_timeout = 0;
int32_t wait_mod_timeout = 0;
char *video_layout_name = NULL;
char *video_layout_group = NULL;
char *video_canvas_size = NULL;
@ -2612,6 +2680,14 @@ conference_obj_t *conference_new(char *name, conference_xml_cfg_t cfg, switch_co
kicked_sound = val;
} else if (!strcasecmp(var, "join-only-sound") && !zstr(val)) {
join_only_sound = val;
} else if (!strcasecmp(var, "wait-min-members-timeout-message") && !zstr(val)) {
wait_min_members_timeout_message = val;
} else if (!strcasecmp(var, "wait-mod-timeout-message") && !zstr(val)) {
wait_mod_timeout_message = val;
} else if (!strcasecmp(var, "endconf-mod-exit-message") && !zstr(val)) {
endconf_mod_exit_message = val;
} else if (!strcasecmp(var, "endconf-message") && !zstr(val)) {
endconf_message = val;
} else if (!strcasecmp(var, "pin") && !zstr(val)) {
pin = val;
} else if (!strcasecmp(var, "moderator-pin") && !zstr(val)) {
@ -2669,6 +2745,27 @@ conference_obj_t *conference_new(char *name, conference_xml_cfg_t cfg, switch_co
} else if (!strcasecmp(var, "sound-prefix") && !zstr(val)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "override sound-prefix with: %s\n", val);
sound_prefix = val;
} else if (!strcasecmp(var, "min-members") && !zstr(val)) {
errno = 0; /* sanity first */
min_members = strtol(val, NULL, 0); /* base 0 lets 0x... for hex 0... for octal and base 10 otherwise through */
if (errno == ERANGE || errno == EINVAL || (int32_t) min_members < 0) {
min_members = 0; /* set to 0 to disable min counts */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "min-members %s is invalid, not setting a limit\n", val);
}
} else if (!strcasecmp(var, "wait-min-members-timeout") && !zstr(val)) {
errno = 0; /* sanity first */
wait_min_members_timeout = strtoll(val, NULL, 0); /* base 0 lets 0x... for hex 0... for octal and base 10 otherwise through */
if (errno == ERANGE || errno == EINVAL || (int32_t) wait_min_members_timeout < 0) {
wait_min_members_timeout = 0; /* set to 0 to disable timeout waiting for min_members */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "wait-min-members-timeout %s is invalid, not setting a limit\n", val);
}
} else if (!strcasecmp(var, "wait-mod-timeout") && !zstr(val)) {
errno = 0; /* sanity first */
wait_mod_timeout = strtoll(val, NULL, 0); /* base 0 lets 0x... for hex 0... for octal and base 10 otherwise through */
if (errno == ERANGE || errno == EINVAL || (int32_t) wait_mod_timeout < 0) {
wait_mod_timeout = 0; /* set to 0 to disable timeout waiting for moderator */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "wait-mod-timeout %s is invalid, not setting a limit\n", val);
}
} else if (!strcasecmp(var, "max-members") && !zstr(val)) {
errno = 0; /* sanity first */
max_members = strtol(val, NULL, 0); /* base 0 lets 0x... for hex 0... for octal and base 10 otherwise through */
@ -3076,6 +3173,22 @@ conference_obj_t *conference_new(char *name, conference_xml_cfg_t cfg, switch_co
conference->is_unlocked_sound = switch_core_strdup(conference->pool, is_unlocked_sound);
}
if (!zstr(wait_min_members_timeout_message)) {
conference->wait_min_members_timeout_message = switch_core_strdup(conference->pool, wait_min_members_timeout_message);
}
if (!zstr(wait_mod_timeout_message)) {
conference->wait_mod_timeout_message = switch_core_strdup(conference->pool, wait_mod_timeout_message);
}
if (!zstr(endconf_mod_exit_message)) {
conference->endconf_mod_exit_message = switch_core_strdup(conference->pool, endconf_mod_exit_message);
}
if (!zstr(endconf_message)) {
conference->endconf_message = switch_core_strdup(conference->pool, endconf_message);
}
if (!zstr(energy_level)) {
conference->energy_level = atoi(energy_level);
if (conference->energy_level < 0) {
@ -3097,6 +3210,11 @@ conference_obj_t *conference_new(char *name, conference_xml_cfg_t cfg, switch_co
}
}
/* its going to be 0 by default, set to a value otherwise so this should be safe */
conference->min_members = min_members;
conference->wait_min_members_timeout = wait_min_members_timeout;
conference->wait_mod_timeout = wait_mod_timeout;
if (!zstr(maxmember_sound)) {
conference->maxmember_sound = switch_core_strdup(conference->pool, maxmember_sound);
}

View File

@ -209,6 +209,7 @@ typedef enum {
MFLAG_SECOND_SCREEN,
MFLAG_SILENT,
MFLAG_FLIP_VIDEO,
MFLAG_ROTATE_VIDEO,
///////////////////////////
MFLAG_MAX
} member_flag_t;
@ -248,6 +249,7 @@ typedef enum {
CFLAG_PERSONAL_CANVAS,
CFLAG_REFRESH_LAYOUT,
CFLAG_VIDEO_MUTE_EXIT_CANVAS,
CFLAG_WAIT_MIN_MEMBERS,
/////////////////////////////////
CFLAG_MAX
} conference_flag_t;
@ -556,6 +558,13 @@ typedef struct conference_obj {
int auto_record_canvas;
char *record_filename;
char *outcall_templ;
char *wait_min_members_timeout_message;
char *wait_mod_timeout_message;
char *endconf_mod_exit_message;
char *endconf_message;
uint32_t min_members;
int32_t wait_min_members_timeout;
int32_t wait_mod_timeout;
char *video_layout_name;
char *video_layout_group;
char *video_canvas_bgcolor;
@ -780,6 +789,8 @@ struct conference_member {
int force_bw_in;
int max_bw_out;
int reset_media;
int flip;
int flip_count;
};
typedef enum {

View File

@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2015, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2016, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@ -24,31 +24,93 @@
* Contributor(s):
*
* William King <william.king@quentustech.com>
* Christopher Rienzo <chris.rienzo@citrix.com>
*
* mod_hiredis.c -- redis client built using the C client library hiredis
*
*/
#include <mod_hiredis.h>
switch_status_t hiredis_profile_create(hiredis_profile_t **new_profile, char *name, uint8_t port)
/* reconnect to redis server */
static switch_status_t hiredis_context_reconnect(hiredis_context_t *context)
{
redisFree(context->context);
context->context = redisConnectWithTimeout(context->connection->host, context->connection->port, context->connection->timeout);
if ( context->context && !context->context->err ) {
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
/* Return a context back to the pool */
static void hiredis_context_release(hiredis_context_t *context, switch_core_session_t *session)
{
if (switch_queue_push(context->connection->context_pool, context) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "hiredis: failed to release back to pool [%s, %d]\n", context->connection->host, context->connection->port);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "hiredis: release back to pool [%s, %d]\n", context->connection->host, context->connection->port);
}
}
/* Grab a context from the pool, reconnect/connect as needed */
static hiredis_context_t *hiredis_connection_get_context(hiredis_connection_t *conn, switch_core_session_t *session)
{
void *val = NULL;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "hiredis: waiting for [%s, %d]\n", conn->host, conn->port);
if ( switch_queue_pop_timeout(conn->context_pool, &val, conn->timeout_us ) == SWITCH_STATUS_SUCCESS ) {
hiredis_context_t *context = (hiredis_context_t *)val;
if ( !context->context ) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "hiredis: attempting[%s, %d]\n", conn->host, conn->port);
context->context = redisConnectWithTimeout(conn->host, conn->port, conn->timeout);
if ( context->context && !context->context->err ) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "hiredis: connection success[%s, %d]\n", conn->host, conn->port);
return context;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "hiredis: connection error[%s, %d] (%s)\n", conn->host, conn->port, context->context->errstr);
hiredis_context_release(context, session);
return NULL;
}
} else if ( context->context->err ) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "hiredis: reconnecting[%s, %d]\n", conn->host, conn->port);
if (hiredis_context_reconnect(context) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "hiredis: reconnection success[%s, %d]\n", conn->host, conn->port);
return context;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "hiredis: reconnection error[%s, %d] (%s)\n", conn->host, conn->port, context->context->errstr);
hiredis_context_release(context, session);
return NULL;
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "hiredis: recycled from pool[%s, %d]\n", conn->host, conn->port);
return context;
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "hiredis: timed out waiting for [%s, %d]\n", conn->host, conn->port);
}
return NULL;
}
switch_status_t hiredis_profile_create(hiredis_profile_t **new_profile, char *name, uint8_t ignore_connect_fail)
{
hiredis_profile_t *profile = NULL;
switch_memory_pool_t *pool = NULL;
switch_core_new_memory_pool(&pool);
switch_core_new_memory_pool(&pool);
profile = switch_core_alloc(pool, sizeof(hiredis_profile_t));
profile->pool = pool;
profile->name = name ? switch_core_strdup(profile->pool, name) : "default";
profile->conn = NULL;
profile->conn_head = NULL;
profile->ignore_connect_fail = ignore_connect_fail;
switch_core_hash_insert(mod_hiredis_globals.profiles, name, (void *) profile);
*new_profile = profile;
return SWITCH_STATUS_SUCCESS;
}
@ -69,7 +131,7 @@ switch_status_t hiredis_profile_destroy(hiredis_profile_t **old_profile)
return SWITCH_STATUS_SUCCESS;
}
switch_status_t hiredis_profile_connection_add(hiredis_profile_t *profile, char *host, char *password, uint32_t port, uint32_t timeout_ms)
switch_status_t hiredis_profile_connection_add(hiredis_profile_t *profile, char *host, char *password, uint32_t port, uint32_t timeout_ms, uint32_t max_contexts)
{
hiredis_connection_t *connection = NULL, *new_conn = NULL;
@ -77,21 +139,39 @@ switch_status_t hiredis_profile_connection_add(hiredis_profile_t *profile, char
new_conn->host = host ? switch_core_strdup(profile->pool, host) : "localhost";
new_conn->password = password ? switch_core_strdup(profile->pool, password) : NULL;
new_conn->port = port ? port : 6379;
new_conn->pool = profile->pool;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "hiredis: adding conn[%d]\n", new_conn->port);
/* create fixed size context pool */
max_contexts = max_contexts > 0 ? max_contexts : 3;
if (switch_queue_create(&new_conn->context_pool, max_contexts, new_conn->pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "hiredis: failed to allocate context pool\n");
return SWITCH_STATUS_GENERR;
} else {
int i = 0;
for (i = 0; i < max_contexts; i++) {
hiredis_context_t *new_context = switch_core_alloc(new_conn->pool, sizeof(hiredis_context_t));
new_context->connection = new_conn;
new_context->context = NULL;
switch_queue_push(new_conn->context_pool, new_context);
}
}
if ( timeout_ms ) {
new_conn->timeout.tv_sec = 0;
new_conn->timeout.tv_usec = timeout_ms * 1000;
new_conn->timeout_us = timeout_ms * 1000;
new_conn->timeout.tv_sec = timeout_ms / 1000;
new_conn->timeout.tv_usec = (timeout_ms % 1000) * 1000;
} else {
new_conn->timeout_us = 500 * 1000;
new_conn->timeout.tv_sec = 0;
new_conn->timeout.tv_usec = 500 * 1000;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "hiredis: adding conn[%s,%d], pool size = %d\n", new_conn->host, new_conn->port, max_contexts);
if ( profile->conn_head != NULL ){
/* Adding 'another' connection */
connection = profile->conn_head;
while ( connection->next != NULL ){
while ( connection->next != NULL ) {
connection = connection->next;
}
connection->next = new_conn;
@ -102,72 +182,90 @@ switch_status_t hiredis_profile_connection_add(hiredis_profile_t *profile, char
return SWITCH_STATUS_SUCCESS;
}
switch_status_t hiredis_profile_reconnect(hiredis_profile_t *profile)
static hiredis_context_t *hiredis_profile_get_context(hiredis_profile_t *profile, hiredis_connection_t *initial_conn, switch_core_session_t *session)
{
hiredis_connection_t *conn = profile->conn_head;
profile->conn = NULL;
hiredis_connection_t *conn = initial_conn ? initial_conn : profile->conn_head;
hiredis_context_t *context;
/* TODO: Needs thorough expansion to handle all disconnection scenarios */
while ( conn ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "hiredis: attempting[%s, %d]\n", conn->host, conn->port);
conn->context = redisConnectWithTimeout(conn->host, conn->port, conn->timeout);
if ( conn->context && conn->context->err) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: connection error[%s]\n", conn->context->errstr);
conn = conn->next;
continue;
context = hiredis_connection_get_context(conn, session);
if (context) {
/* successful redis connection */
return context;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "hiredis: connection success[%s]\n", conn->host);
/* successful redis connection */
profile->conn = conn;
return SWITCH_STATUS_SUCCESS;
conn = conn->next;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: unable to reconnect\n");
return SWITCH_STATUS_GENERR;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "hiredis: unable to connect\n");
return NULL;
}
switch_status_t hiredis_profile_execute_sync(hiredis_profile_t *profile, const char *data, char **resp)
static switch_status_t hiredis_context_execute_sync(hiredis_context_t *context, const char *data, char **resp, switch_core_session_t *session)
{
char *str = NULL;
redisReply *response = NULL;
/* Check connection */
if ( !profile->conn && hiredis_profile_reconnect(profile) != SWITCH_STATUS_SUCCESS ) {
*resp = strdup("hiredis profile unable to establish connection");
return SWITCH_STATUS_GENERR;
}
response = redisCommand(profile->conn->context, data);
redisReply *response;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "hiredis: %s\n", data);
response = redisCommand(context->context, data);
if ( !response ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: empty response received\n");
*resp = NULL;
return SWITCH_STATUS_GENERR;
}
switch(response->type) {
case REDIS_REPLY_STATUS: /* fallthrough */
case REDIS_REPLY_STRING:
str = strdup(response->str);
*resp = strdup(response->str);
break;
case REDIS_REPLY_INTEGER:
str = switch_mprintf("%lld", response->integer);
*resp = switch_mprintf("%lld", response->integer);
break;
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: response error[%s][%d]\n", response->str, response->type);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "hiredis: response error[%s][%d]\n", response->str, response->type);
freeReplyObject(response);
*resp = NULL;
return SWITCH_STATUS_GENERR;
}
freeReplyObject(response);
*resp = str;
return SWITCH_STATUS_SUCCESS;
}
switch_status_t hiredis_profile_execute_sync(hiredis_profile_t *profile, const char *data, char **resp, switch_core_session_t *session)
{
hiredis_context_t *context = NULL;
int reconnected = 0;
context = hiredis_profile_get_context(profile, NULL, session);
while (context) {
if (hiredis_context_execute_sync(context, data, resp, session) == SWITCH_STATUS_SUCCESS) {
/* got result */
hiredis_context_release(context, session);
return SWITCH_STATUS_SUCCESS;
} else if (context->context->err) {
/* have a bad connection, try a single reconnect attempt before moving on to alternate connection */
if (reconnected || hiredis_context_reconnect(context) != SWITCH_STATUS_SUCCESS) {
/* try alternate connection */
hiredis_context_t *new_context = hiredis_profile_get_context(profile, context->connection, session);
hiredis_context_release(context, session);
context = new_context;
if (context) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "hiredis: got alternate connection to [%s, %d]\n", context->connection->host, context->connection->port);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "hiredis: no more alternate connections to try\n");
}
reconnected = 0;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "hiredis: reconnection success[%s, %d]\n", context->connection->host, context->connection->port);
reconnected = 1;
}
} else {
/* no problem with context, so don't retry */
hiredis_context_release(context, session);
return SWITCH_STATUS_GENERR;
}
}
return SWITCH_STATUS_SOCKERR;
}
/* For Emacs:
* Local Variables:

View File

@ -24,6 +24,7 @@
* Contributor(s):
*
* William King <william.king@quentustech.com>
* Christopher Rienzo <chris.rienzo@citrix.com>
*
* mod_hiredis.c -- redis client built using the C client library hiredis
*
@ -44,20 +45,20 @@ switch_status_t mod_hiredis_do_config()
if ( (profiles = switch_xml_child(cfg, "profiles")) != NULL) {
for (profile = switch_xml_child(profiles, "profile"); profile; profile = profile->next) {
hiredis_profile_t *new_profile = NULL;
int debug = 0;
uint8_t ignore_connect_fail = 0;
char *name = (char *) switch_xml_attr_soft(profile, "name");
// Load params
if ( (params = switch_xml_child(profile, "params")) != NULL) {
for (param = switch_xml_child(params, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
if ( ! strncmp(var, "debug", 5) ) {
debug = atoi(switch_xml_attr_soft(param, "value"));
if ( !strncmp(var, "ignore-connect-fail", 19) ) {
ignore_connect_fail = switch_true(switch_xml_attr_soft(param, "value"));
}
}
}
if ( hiredis_profile_create(&new_profile, name, debug) == SWITCH_STATUS_SUCCESS) {
if ( hiredis_profile_create(&new_profile, name, ignore_connect_fail) == SWITCH_STATUS_SUCCESS ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Created profile[%s]\n", name);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create profile[%s]\n", name);
@ -67,7 +68,7 @@ switch_status_t mod_hiredis_do_config()
if ( (connections = switch_xml_child(profile, "connections")) != NULL) {
for (connection = switch_xml_child(connections, "connection"); connection; connection = connection->next) {
char *host = NULL, *password = NULL;
uint32_t port = 0, timeout_ms = 0;
uint32_t port = 0, timeout_ms = 0, max_connections = 0;
for (param = switch_xml_child(connection, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
@ -75,15 +76,17 @@ switch_status_t mod_hiredis_do_config()
host = (char *) switch_xml_attr_soft(param, "value");
} else if ( !strncmp(var, "port", 4) ) {
port = atoi(switch_xml_attr_soft(param, "value"));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "hiredis: adding conn[%u == %s]\n", port, switch_xml_attr_soft(param, "value"));
} else if ( !strncmp(var, "timeout_ms", 10) ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "hiredis: adding conn[%u == %s]\n", port, switch_xml_attr_soft(param, "value"));
} else if ( !strncmp(var, "timeout-ms", 10) || !strncmp(var, "timeout_ms", 10) ) {
timeout_ms = atoi(switch_xml_attr_soft(param, "value"));
} else if ( !strncmp(var, "password", 8) ) {
password = (char *) switch_xml_attr_soft(param, "value");
} else if ( !strncmp(var, "max-connections", 15) ) {
max_connections = atoi(switch_xml_attr_soft(param, "value"));
}
}
if ( hiredis_profile_connection_add(new_profile, host, password, port, timeout_ms) == SWITCH_STATUS_SUCCESS) {
if ( hiredis_profile_connection_add(new_profile, host, password, port, timeout_ms, max_connections) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Created profile[%s]\n", name);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create profile[%s]\n", name);

View File

@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2016, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@ -23,6 +23,7 @@
*
* Contributor(s):
* William King <william.king@quentustech.com>
* Chris Rienzo <chris.rienzo@citrix.com>
*
* mod_hiredis.c -- Redis DB access module
*
@ -45,7 +46,7 @@ SWITCH_STANDARD_APP(raw_app)
if ( !zstr(data) ) {
profile_name = strdup(data);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: invalid data! Use the format 'default set keyname value' \n");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "hiredis: invalid data! Use the format 'default set keyname value' \n");
goto done;
}
@ -53,22 +54,22 @@ SWITCH_STANDARD_APP(raw_app)
*cmd = '\0';
cmd++;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: invalid data! Use the format 'default set keyname value' \n");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "hiredis: invalid data! Use the format 'default set keyname value' \n");
goto done;
}
profile = switch_core_hash_find(mod_hiredis_globals.profiles, profile_name);
if ( !profile ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: Unable to locate profile[%s]\n", profile_name);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "hiredis: Unable to locate profile[%s]\n", profile_name);
return;
}
if ( hiredis_profile_execute_sync(profile, cmd, &response) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: profile[%s] error executing [%s] because [%s]\n", profile_name, cmd, response);
if ( hiredis_profile_execute_sync(profile, cmd, &response, session) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "hiredis: profile[%s] error executing [%s] because [%s]\n", profile_name, cmd, response ? response : "");
}
switch_channel_set_variable(channel, "hiredis_raw_response", response);
switch_channel_set_variable(channel, "hiredis_raw_response", response ? response : "");
done:
switch_safe_free(profile_name);
@ -93,21 +94,23 @@ SWITCH_STANDARD_API(raw_api)
data++;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "hiredis: debug: profile[%s] for command [%s]\n", input, data);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "hiredis: debug: profile[%s] for command [%s]\n", input, data);
profile = switch_core_hash_find(mod_hiredis_globals.profiles, input);
if ( !profile ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: Unable to locate profile[%s]\n", input);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "hiredis: Unable to locate profile[%s]\n", input);
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
if ( hiredis_profile_execute_sync(profile, data, &response) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: profile[%s] error executing [%s] reason:[%s]\n", input, data, response);
if ( hiredis_profile_execute_sync(profile, data, &response, session) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "hiredis: profile[%s] error executing [%s] reason:[%s]\n", input, data, response ? response : "");
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
stream->write_function(stream, response);
if (response) {
stream->write_function(stream, response);
}
done:
switch_safe_free(input);
switch_safe_free(response);
@ -130,14 +133,19 @@ SWITCH_LIMIT_INCR(hiredis_limit_incr)
switch_memory_pool_t *session_pool = switch_core_session_get_pool(session);
if ( zstr(realm) ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: realm must be defined\n");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "hiredis: realm must be defined\n");
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
if ( interval < 0 ) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "hiredis: interval must be >= 0\n");
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
profile = switch_core_hash_find(mod_hiredis_globals.profiles, realm);
if ( !profile ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: Unable to locate profile[%s]\n", realm);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "hiredis: Unable to locate profile[%s]\n", realm);
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
@ -149,13 +157,26 @@ SWITCH_LIMIT_INCR(hiredis_limit_incr)
hashkey = switch_mprintf("incr %s", limit_key);
if ( hiredis_profile_execute_sync(profile, hashkey, &response) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: profile[%s] error executing [%s] because [%s]\n", realm, hashkey, response);
switch_channel_set_variable(channel, "hiredis_raw_response", response);
if ( (status = hiredis_profile_execute_sync(profile, hashkey, &response, session)) != SWITCH_STATUS_SUCCESS ) {
if ( status == SWITCH_STATUS_SOCKERR && profile->ignore_connect_fail ) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "hiredis: ignoring profile[%s] connection error executing [%s]\n", realm, hashkey);
switch_goto_status(SWITCH_STATUS_SUCCESS, done);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "hiredis: profile[%s] error executing [%s] because [%s]\n", realm, hashkey, response ? response : "");
switch_channel_set_variable(channel, "hiredis_raw_response", response ? response : "");
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
switch_channel_set_variable(channel, "hiredis_raw_response", response);
/* set expiration for interval on first increment */
if ( interval && !strcmp("1", response ? response : "") ) {
char *expire_response = NULL;
char *expire_cmd = switch_mprintf("expire %s %d", limit_key, interval);
hiredis_profile_execute_sync(profile, expire_cmd, &expire_response, session);
switch_safe_free(expire_cmd);
switch_safe_free(expire_response);
}
switch_channel_set_variable(channel, "hiredis_raw_response", response ? response : "");
limit_pvt = switch_core_alloc(session_pool, sizeof(hiredis_limit_pvt_t));
limit_pvt->next = switch_channel_get_private(channel, "hiredis_limit_pvt");
@ -166,7 +187,7 @@ SWITCH_LIMIT_INCR(hiredis_limit_incr)
limit_pvt->interval = interval;
switch_channel_set_private(channel, "hiredis_limit_pvt", limit_pvt);
count = atoll(response);
count = atoll(response ? response : "");
if ( !count || count > max ) {
switch_goto_status(SWITCH_STATUS_GENERR, done);
@ -195,31 +216,37 @@ SWITCH_LIMIT_RELEASE(hiredis_limit_release)
hiredis_limit_pvt_t *tmp = limit_pvt;
while (tmp) {
profile = switch_core_hash_find(mod_hiredis_globals.profiles, limit_pvt->realm);
hashkey = switch_mprintf("decr %s", tmp->limit_key);
limit_pvt = tmp->next;
/* Rate limited resources are not auto-decremented, they will expire. */
if (!tmp->interval) {
profile = switch_core_hash_find(mod_hiredis_globals.profiles, limit_pvt->realm);
hashkey = switch_mprintf("decr %s", tmp->limit_key);
if ( limit_pvt && (limit_pvt->interval > 0) && (hiredis_profile_execute_sync(profile, hashkey, &response) != SWITCH_STATUS_SUCCESS)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: profile[%s] error executing [%s] because [%s]\n",
tmp->realm, hashkey, response);
if ( hiredis_profile_execute_sync(profile, hashkey, &response, session) != SWITCH_STATUS_SUCCESS ) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "hiredis: profile[%s] error executing [%s] because [%s]\n",
tmp->realm, hashkey, response ? response : "");
}
switch_safe_free(response);
switch_safe_free(hashkey);
}
tmp = limit_pvt;
switch_safe_free(response);
switch_safe_free(hashkey);
tmp = tmp->next;
}
} else {
profile = switch_core_hash_find(mod_hiredis_globals.profiles, limit_pvt->realm);
hashkey = switch_mprintf("decr %s", limit_pvt->limit_key);
if ( hiredis_profile_execute_sync(profile, hashkey, &response) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: profile[%s] error executing [%s] because [%s]\n", realm, hashkey, response);
switch_channel_set_variable(channel, "hiredis_raw_response", response);
if ( ( status = hiredis_profile_execute_sync(profile, hashkey, &response, session) ) != SWITCH_STATUS_SUCCESS ) {
if ( status == SWITCH_STATUS_SOCKERR && profile->ignore_connect_fail ) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "hiredis: ignoring profile[%s] connection error executing [%s]\n", realm, hashkey);
switch_goto_status(SWITCH_STATUS_SUCCESS, done);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "hiredis: profile[%s] error executing [%s] because [%s]\n", realm, hashkey, response ? response : "");
switch_channel_set_variable(channel, "hiredis_raw_response", response ? response : "");
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
switch_channel_set_variable(channel, "hiredis_raw_response", response);
switch_channel_set_variable(channel, "hiredis_raw_response", response ? response : "");
}
done:
@ -249,12 +276,12 @@ SWITCH_LIMIT_USAGE(hiredis_limit_usage)
hashkey = switch_mprintf("get %s", resource);
if ( hiredis_profile_execute_sync(profile, hashkey, &response) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: profile[%s] error executing [%s] because [%s]\n", realm, hashkey, response);
if ( hiredis_profile_execute_sync(profile, hashkey, &response, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: profile[%s] error executing [%s] because [%s]\n", realm, hashkey, response ? response : "");
goto err;
}
count = atoll(response);
count = atoll(response ? response : "");
switch_safe_free(response);
switch_safe_free(hashkey);
@ -282,6 +309,7 @@ SWITCH_LIMIT_RESET(hiredis_limit_reset)
*/
SWITCH_LIMIT_INTERVAL_RESET(hiredis_limit_interval_reset)
{
/* TODO this doesn't work since the key has the interval in it */
hiredis_profile_t *profile = switch_core_hash_find(mod_hiredis_globals.profiles, realm);
switch_status_t status = SWITCH_STATUS_SUCCESS;
char *hashkey = NULL, *response = NULL;
@ -298,8 +326,8 @@ SWITCH_LIMIT_INTERVAL_RESET(hiredis_limit_interval_reset)
hashkey = switch_mprintf("set %s 0", resource);
if ( hiredis_profile_execute_sync(profile, hashkey, &response) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: profile[%s] error executing [%s] because [%s]\n", realm, hashkey, response);
if ( hiredis_profile_execute_sync(profile, hashkey, &response, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hiredis: profile[%s] error executing [%s] because [%s]\n", realm, hashkey, response ? response : "");
switch_goto_status(SWITCH_STATUS_GENERR, done);
}

View File

@ -8,17 +8,23 @@
typedef struct mod_hiredis_global_s {
switch_memory_pool_t *pool;
switch_hash_t *profiles;
uint8_t debug;
} mod_hiredis_global_t;
extern mod_hiredis_global_t mod_hiredis_globals;
typedef struct mod_hiredis_context_s {
struct hiredis_connection_s *connection;
redisContext *context;
} hiredis_context_t;
typedef struct hiredis_connection_s {
char *host;
char *password;
uint32_t port;
redisContext *context;
switch_interval_time_t timeout_us;
struct timeval timeout;
switch_memory_pool_t *pool;
switch_queue_t *context_pool;
struct hiredis_connection_s *next;
} hiredis_connection_t;
@ -26,9 +32,8 @@ typedef struct hiredis_connection_s {
typedef struct hiredis_profile_s {
switch_memory_pool_t *pool;
char *name;
int debug;
uint8_t ignore_connect_fail;
hiredis_connection_t *conn;
hiredis_connection_t *conn_head;
} hiredis_profile_t;
@ -41,11 +46,11 @@ typedef struct hiredis_limit_pvt_s {
struct hiredis_limit_pvt_s *next;
} hiredis_limit_pvt_t;
switch_status_t mod_hiredis_do_config();
switch_status_t hiredis_profile_create(hiredis_profile_t **new_profile, char *name, uint8_t port);
switch_status_t mod_hiredis_do_config(void);
switch_status_t hiredis_profile_create(hiredis_profile_t **new_profile, char *name, uint8_t ignore_connect_fail);
switch_status_t hiredis_profile_destroy(hiredis_profile_t **old_profile);
switch_status_t hiredis_profile_connection_add(hiredis_profile_t *profile, char *host, char *password, uint32_t port, uint32_t timeout_ms);
switch_status_t hiredis_profile_connection_add(hiredis_profile_t *profile, char *host, char *password, uint32_t port, uint32_t timeout_ms, uint32_t max_connections);
switch_status_t hiredis_profile_execute_sync(hiredis_profile_t *profile, const char *data, char **response);
switch_status_t hiredis_profile_execute_sync(hiredis_profile_t *profile, const char *data, char **response, switch_core_session_t *session);
#endif /* MOD_HIREDIS_H */

View File

@ -9,7 +9,9 @@
<param name="ssl-verifyhost" value="true"/>
<param name="ssl-verifypeer" value="true"/>
<!-- default is 300 seconds, override here -->
<!--param name="connect-timeout" value="300"/>
<!--param name="connect-timeout" value="300"/-->
<!-- default is 300 seconds, override here -->
<!--param name="download-timeout" value="300"/-->
</settings>
<profiles>

View File

@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2015, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2016, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@ -53,6 +53,8 @@ SWITCH_STANDARD_API(http_cache_remove);
SWITCH_STANDARD_API(http_cache_prefetch);
#define DOWNLOAD_NEEDED "download"
#define DOWNLOAD 1
#define PREFETCH 2
typedef struct url_cache url_cache_t;
@ -201,6 +203,8 @@ struct url_cache {
int enable_file_formats;
/** How long to wait, in seconds, for TCP connection. If 0, use default value of 300 seconds */
long connect_timeout;
/** How long to wait, in seconds, for download of file. If 0, use default value of 300 seconds */
long download_timeout;
};
static url_cache_t gcache;
@ -614,13 +618,14 @@ static void url_cache_clear(url_cache_t *cache, switch_core_session_t *session)
* @param profile optional profile
* @param session the (optional) session requesting the URL
* @param url The URL
* @param download If true, the file will be downloaded if it does not exist in the cache.
* @param download If DOWNLOAD, the file will be downloaded if it does not exist in the cache. If PREFETCH, the file will be downloaded if not in cache and not being downloaded by another thread.
* @param refresh If true, existing cache entry is invalidated
* @param pool The pool to use for allocating the filename
* @return The filename or NULL if there is an error
*/
static char *url_cache_get(url_cache_t *cache, http_profile_t *profile, switch_core_session_t *session, const char *url, int download, int refresh, switch_memory_pool_t *pool)
{
switch_time_t download_timeout_ns = cache->download_timeout * 1000 * 1000;
char *filename = NULL;
cached_url_t *u = NULL;
if (zstr(url)) {
@ -643,6 +648,9 @@ static char *url_cache_get(url_cache_t *cache, http_profile_t *profile, switch_c
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Cached URL manually expired.\n");
url_cache_remove_soft(cache, session, u); /* will get permanently deleted upon replacement */
u = NULL;
} else if (u->status == CACHED_URL_RX_IN_PROGRESS && switch_time_now() >= (u->download_time + download_timeout_ns)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Download of URL has timed out.\n");
u = NULL;
}
}
@ -675,7 +683,7 @@ static char *url_cache_get(url_cache_t *cache, http_profile_t *profile, switch_c
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Failed to download URL %s\n", url);
cache->errors++;
}
} else if (!u || (u->status == CACHED_URL_RX_IN_PROGRESS && !download)) {
} else if (!u || (u->status == CACHED_URL_RX_IN_PROGRESS && download != DOWNLOAD)) {
filename = DOWNLOAD_NEEDED;
} else {
/* Wait until file is downloaded */
@ -683,7 +691,7 @@ static char *url_cache_get(url_cache_t *cache, http_profile_t *profile, switch_c
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Waiting for URL %s to be available\n", url);
u->waiters++;
url_cache_unlock(cache, session);
while(u->status == CACHED_URL_RX_IN_PROGRESS) {
while(u->status == CACHED_URL_RX_IN_PROGRESS && switch_time_now() < (u->download_time + download_timeout_ns)) {
switch_sleep(10 * 1000); /* 10 ms */
}
url_cache_lock(cache, session);
@ -1083,6 +1091,9 @@ static switch_status_t http_get(url_cache_t *cache, http_profile_t *profile, cac
if (cache->connect_timeout > 0) {
switch_curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, cache->connect_timeout);
}
if (cache->download_timeout > 0) {
switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, cache->download_timeout);
}
if (!cache->ssl_verifypeer) {
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
} else {
@ -1174,7 +1185,7 @@ SWITCH_STANDARD_API(http_cache_prefetch)
}
/* send to thread pool */
url = strdup(cmd);
url = switch_mprintf("{prefetch=true}%s", cmd);
if (switch_queue_trypush(gcache.prefetch_queue, url) != SWITCH_STATUS_SUCCESS) {
switch_safe_free(url);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to queue prefetch request\n");
@ -1188,7 +1199,7 @@ SWITCH_STANDARD_API(http_cache_prefetch)
#define HTTP_GET_SYNTAX "{param=val}<url>"
/**
* Get a file from the cache, download if it isn' cached
* Get a file from the cache, download if it isn't cached
*/
SWITCH_STANDARD_API(http_cache_get)
{
@ -1199,6 +1210,8 @@ SWITCH_STANDARD_API(http_cache_get)
char *filename;
switch_event_t *params = NULL;
char *url;
int refresh = SWITCH_FALSE;
int download = DOWNLOAD;
if (zstr(cmd)) {
stream->write_function(stream, "USAGE: %s\n", HTTP_GET_SYNTAX);
@ -1219,9 +1232,13 @@ SWITCH_STANDARD_API(http_cache_get)
}
if (params) {
profile = url_cache_http_profile_find(&gcache, switch_event_get_header(params, "profile"));
if (switch_true(switch_event_get_header(params, "prefetch"))) {
download = PREFETCH;
}
refresh = switch_true(switch_event_get_header(params, "refresh"));
}
filename = url_cache_get(&gcache, profile, session, url, 1, params ? switch_true(switch_event_get_header(params, "refresh")) : SWITCH_FALSE, pool);
filename = url_cache_get(&gcache, profile, session, url, download, refresh, pool);
if (filename) {
stream->write_function(stream, "%s", filename);
@ -1485,7 +1502,8 @@ static switch_status_t do_config(url_cache_t *cache)
cache->ssl_verifyhost = 1;
cache->ssl_verifypeer = 1;
cache->enable_file_formats = 0;
cache->connect_timeout = 0;
cache->connect_timeout = 300;
cache->download_timeout = 300;
/* get params */
settings = switch_xml_child(cfg, "settings");
@ -1523,8 +1541,17 @@ static switch_status_t do_config(url_cache_t *cache)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Setting ssl-verifypeer to %s\n", val);
cache->ssl_verifypeer = !switch_false(val); /* only disable if explicitly set to false */
} else if (!strcasecmp(var, "connect-timeout")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Setting connect-timeout to %s\n", val);
cache->connect_timeout = atoi(val);
int int_val = atoi(val);
if (int_val > 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Setting connect-timeout to %s\n", val);
cache->connect_timeout = int_val;
}
} else if (!strcasecmp(var, "download-timeout")) {
int int_val = atoi(val);
if (int_val > 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Setting download-timeout to %s\n", val);
cache->download_timeout = int_val;
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unsupported param: %s\n", var);
}
@ -1635,11 +1662,6 @@ static switch_status_t do_config(url_cache_t *cache)
status = SWITCH_STATUS_TERM;
goto done;
}
if (cache->connect_timeout < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "connect-timeout must be >= 0\n");
status = SWITCH_STATUS_TERM;
goto done;
}
cache->max_url = max_urls;
cache->default_max_age = (default_max_age_sec * 1000 * 1000); /* convert from seconds to nanoseconds */

View File

@ -165,8 +165,8 @@ static switch_status_t process_event(switch_event_t *event)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_core_session_t *session = NULL;
char *username[4] = { NULL };
char *domain[4] = { NULL };
char *username[5] = { NULL };
char *domain[5] = { NULL };
char key[512];
char *uuid = NULL, *my_uuid = NULL;
int i;
@ -191,6 +191,18 @@ static switch_status_t process_event(switch_event_t *event)
username[3] = switch_event_get_header(event, "variable_sip_to_user");
domain[3] = switch_event_get_header(event, "variable_domain_name");
username[4] = switch_event_get_header(event, "variable_verto_user");
domain[4] = switch_event_get_header(event, "variable_verto_host");
if (username[4] && domain[4]) {
char *argv[5] = { 0 };
int argc = 0;
argc = switch_split(username[4], '@', argv);
if (argc > 0) {
username[4] = argv[0];
}
}
for (i = 0; i < 4; i++) {
if (username[i] && domain[i]) {

View File

@ -1353,9 +1353,6 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r
}
}
}
if (xroot) {
switch_xml_free(xroot);
}
status = SWITCH_STATUS_SUCCESS;
@ -1372,6 +1369,10 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r
keepalive_listener(listener, NULL);
end:
if (xroot) {
switch_xml_free(xroot);
}
if(params) {
switch_event_destroy(&params);
}

View File

@ -1829,7 +1829,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), TAG_END());
} else if (ua && ((switch_stristr("aastra", ua) && !switch_stristr("Intelligate", ua)) ||
(switch_stristr("cisco/spa50", ua) || switch_stristr("cisco/spa525", ua)) ||
switch_stristr("Yealink", ua) ||
switch_stristr("Yealink", ua) || switch_stristr("Mitel", ua) ||
switch_stristr("Panasonic", ua))) {
snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <sip:%s@%s>", name, number, tech_pvt->profile->printable_sipip);
@ -2133,6 +2133,20 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
}
}
break;
case SWITCH_MESSAGE_INDICATE_ALERTING:
{
char *extra_header = sofia_glue_get_extra_headers(channel, SOFIA_SIP_PROGRESS_HEADER_PREFIX);
const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full");
char *cid = generate_pai_str(tech_pvt);
nua_respond(tech_pvt->nh, SIP_180_RINGING,
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
TAG_IF(cid, SIPTAG_HEADER_STR(cid)),
TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
TAG_IF(!zstr(extra_header), SIPTAG_HEADER_STR(extra_header)),
TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),
SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT)), TAG_END());
}
break;
case SWITCH_MESSAGE_INDICATE_RINGING:
{
switch_ring_ready_t ring_ready_val = msg->numeric_arg;

View File

@ -4295,7 +4295,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
profile->paid_type = PAID_DEFAULT;
profile->bind_attempts = 2;
profile->bind_attempt_interval = 5;
profile->dtmf_type = DTMF_2833;
profile->tls_verify_policy = TPTLS_VERIFY_NONE;
/* lib default */
profile->tls_verify_depth = 2;
@ -10558,7 +10558,7 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia
switch_channel_set_variable(channel, "sip_geolocation_error", un->un_value);
} else if (!strcasecmp(un->un_name, "userLocation")) {
switch_channel_set_variable(channel, "sip_user_location", un->un_value);
} else if (!strncasecmp(un->un_name, "X-", 2) || !strncasecmp(un->un_name, "P-", 2) || !strcasecmp(un->un_name, "User-to-User")) {
} else if (!strncasecmp(un->un_name, "X-", 2) || !strncasecmp(un->un_name, "P-", 2) || !strcasecmp(un->un_name, "User-to-User") || !strncasecmp(un->un_name, "On", 2)) {
if (!zstr(un->un_value)) {
char new_name[512] = "";
int reps = 0;

View File

@ -644,7 +644,7 @@ void sofia_glue_set_extra_headers(switch_core_session_t *session, sip_t const *s
}
for (un = sip->sip_unknown; un; un = un->un_next) {
if ((!strncasecmp(un->un_name, "X-", 2) && strncasecmp(un->un_name, "X-FS-", 5)) || !strncasecmp(un->un_name, "P-", 2)) {
if ((!strncasecmp(un->un_name, "X-", 2) && strncasecmp(un->un_name, "X-FS-", 5)) || !strncasecmp(un->un_name, "P-", 2) || !strncasecmp(un->un_name, "On", 2)) {
if (!zstr(un->un_value)) {
switch_snprintf(name, sizeof(name), "%s%s", prefix, un->un_name);
switch_channel_set_variable(channel, name, un->un_value);

View File

@ -2132,7 +2132,8 @@ static switch_status_t verto_on_hangup(switch_core_session_t *session)
cJSON *params = NULL;
cJSON *msg = jrpc_new_req("verto.bye", tech_pvt->call_id, &params);
switch_call_cause_t cause = switch_channel_get_cause(tech_pvt->channel);
switch_channel_set_variable(tech_pvt->channel, "verto_hangup_disposition", "send_bye");
cJSON_AddItemToObject(params, "causeCode", cJSON_CreateNumber(cause));
cJSON_AddItemToObject(params, "cause", cJSON_CreateString(switch_channel_cause2str(cause)));
jsock_queue_event(jsock, &msg, SWITCH_TRUE);
@ -2743,6 +2744,7 @@ static switch_bool_t verto__bye_func(const char *method, cJSON *params, jsock_t
if ((session = switch_core_session_locate(call_id))) {
verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
tech_pvt->remote_hangup_cause = cause;
switch_channel_set_variable(tech_pvt->channel, "verto_hangup_disposition", "recv_bye");
switch_channel_hangup(tech_pvt->channel, cause);
cJSON_AddItemToObject(obj, "message", cJSON_CreateString("CALL ENDED"));

View File

@ -197,7 +197,7 @@ static void flush_listener(listener_t *listener, switch_bool_t flush_log, switch
{
void *pop;
if (listener->log_queue) {
if (flush_log && listener->log_queue) {
while (switch_queue_trypop(listener->log_queue, &pop) == SWITCH_STATUS_SUCCESS) {
switch_log_node_t *dnode = (switch_log_node_t *) pop;
if (dnode) {
@ -206,7 +206,7 @@ static void flush_listener(listener_t *listener, switch_bool_t flush_log, switch
}
}
if (listener->event_queue) {
if (flush_events && listener->event_queue) {
while (switch_queue_trypop(listener->event_queue, &pop) == SWITCH_STATUS_SUCCESS) {
switch_event_t *pevent = (switch_event_t *) pop;
if (!pop)

View File

@ -48,6 +48,10 @@
#define MULTIUNSET_LONG_DESC "Unset many channel variables for the channel calling the application."
#define MULTIUNSET_SYNTAX "[^^<delim>]<varname> <var2> <var3>"
#define EXPORT_SHORT_DESC "Export many channel variables"
#define EXPORT_LONG_DESC "Export many channel variables for the channel calling the application"
#define EXPORT_SYNTAX "[^^<delim>]<varname>=<value> <var2>=<val2>"
static void base_set (switch_core_session_t *session, const char *data, switch_stack_t stack) {
char *var, *val = NULL;
@ -84,6 +88,42 @@ static void base_set (switch_core_session_t *session, const char *data, switch_s
}
}
static void base_export (switch_core_session_t *session, const char *data, switch_stack_t stack) {
char *var, *val = NULL;
if (zstr(data)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No variable name specified.\n");
} else {
switch_channel_t *channel = switch_core_session_get_channel(session);
char *expanded = NULL;
var = switch_core_session_strdup(session, data);
if (!(val = strchr(var, '='))) {
val = strchr(var, ',');
}
if (val) {
*val++ = '\0';
if (zstr(val)) {
val = NULL;
}
}
if (val) {
expanded = switch_channel_expand_variables(channel, val);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s EXPORT [%s]=[%s]\n", switch_channel_get_name(channel), var,
expanded ? expanded : "UNDEF");
switch_channel_export_variable_var_check(channel, var, expanded, SWITCH_EXPORT_VARS_VARIABLE, SWITCH_FALSE);
if (expanded && expanded != val) {
switch_safe_free(expanded);
}
}
}
SWITCH_STANDARD_APP(multiset_function) {
char delim = ' ';
char *arg = (char *) data;
@ -170,6 +210,30 @@ SWITCH_STANDARD_APP(multiunset_function) {
}
}
SWITCH_STANDARD_APP(export_function) {
char delim = ' ';
char *arg = (char *) data;
if (!zstr(arg) && *arg == '^' && *(arg+1) == '^') {
arg += 2;
delim = *arg++;
}
if (arg) {
char *array[256] = {0};
int i, argc;
arg = switch_core_session_strdup(session, arg);
argc = switch_split(arg, delim, array);
for(i = 0; i < argc; i++) {
base_export(session, array[i], SWITCH_STACK_BOTTOM);
}
} else {
base_export(session, data, SWITCH_STACK_BOTTOM);
}
}
void add_kz_dptools(switch_loadable_module_interface_t **module_interface, switch_application_interface_t *app_interface) {
SWITCH_ADD_APP(app_interface, "kz_set", SET_SHORT_DESC, SET_LONG_DESC, set_function, SET_SYNTAX,
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
@ -179,4 +243,6 @@ void add_kz_dptools(switch_loadable_module_interface_t **module_interface, switc
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
SWITCH_ADD_APP(app_interface, "kz_multiunset", MULTISET_SHORT_DESC, MULTISET_LONG_DESC, multiunset_function, MULTIUNSET_SYNTAX,
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
SWITCH_ADD_APP(app_interface, "kz_export", EXPORT_SHORT_DESC, EXPORT_LONG_DESC, export_function, EXPORT_SYNTAX,
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
}

View File

@ -35,7 +35,11 @@
#include <switch.h>
#include "mpg123.h"
#include <shout/shout.h>
#ifdef WIN32
#include <lame.h>
#else
#include <lame/lame.h>
#endif
#include <switch_curl.h>
#define OUTSCALE 8192 * 2

View File

@ -259,7 +259,7 @@ static switch_status_t load_config(JavaVMOption **javaOptions, int *optionCount,
}
++i;
}
(*javaOptions)[i].optionString = "-Djava.library.path=" SWITCH_PREFIX_DIR SWITCH_PATH_SEPARATOR "mod";
(*javaOptions)[i].optionString = switch_core_sprintf(memoryPool, "-Djava.library.path=%s", SWITCH_GLOBAL_dirs.mod_dir);
}
/*

View File

@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 2.0.11
* Version 2.0.12
*
* This file is not intended to be easily readable and contains a number of
* coding conventions designed to improve portability and efficiency. Do not make
@ -5034,93 +5034,6 @@ SWIGEXPORT void SWIGSTDCALL CSharp_delete_switch_rtp_hdr_ext_t(void * jarg1) {
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_rtcp_sdes_unit_t_type_set(void * jarg1, unsigned char jarg2) {
switch_rtcp_sdes_unit_s *arg1 = (switch_rtcp_sdes_unit_s *) 0 ;
unsigned char arg2 ;
arg1 = (switch_rtcp_sdes_unit_s *)jarg1;
arg2 = (unsigned char)jarg2;
if (arg1) (arg1)->type = arg2;
}
SWIGEXPORT unsigned char SWIGSTDCALL CSharp_switch_rtcp_sdes_unit_t_type_get(void * jarg1) {
unsigned char jresult ;
switch_rtcp_sdes_unit_s *arg1 = (switch_rtcp_sdes_unit_s *) 0 ;
unsigned char result;
arg1 = (switch_rtcp_sdes_unit_s *)jarg1;
result = (unsigned char) ((arg1)->type);
jresult = result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_rtcp_sdes_unit_t_length_set(void * jarg1, unsigned char jarg2) {
switch_rtcp_sdes_unit_s *arg1 = (switch_rtcp_sdes_unit_s *) 0 ;
unsigned char arg2 ;
arg1 = (switch_rtcp_sdes_unit_s *)jarg1;
arg2 = (unsigned char)jarg2;
if (arg1) (arg1)->length = arg2;
}
SWIGEXPORT unsigned char SWIGSTDCALL CSharp_switch_rtcp_sdes_unit_t_length_get(void * jarg1) {
unsigned char jresult ;
switch_rtcp_sdes_unit_s *arg1 = (switch_rtcp_sdes_unit_s *) 0 ;
unsigned char result;
arg1 = (switch_rtcp_sdes_unit_s *)jarg1;
result = (unsigned char) ((arg1)->length);
jresult = result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_rtcp_sdes_unit_t_value_set(void * jarg1, char * jarg2) {
switch_rtcp_sdes_unit_s *arg1 = (switch_rtcp_sdes_unit_s *) 0 ;
char *arg2 ;
arg1 = (switch_rtcp_sdes_unit_s *)jarg1;
arg2 = (char *)jarg2;
{
if (arg2) strcpy((char *)arg1->value, (const char *)arg2);
else arg1->value[0] = 0;
}
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_rtcp_sdes_unit_t_value_get(void * jarg1) {
char * jresult ;
switch_rtcp_sdes_unit_s *arg1 = (switch_rtcp_sdes_unit_s *) 0 ;
char *result = 0 ;
arg1 = (switch_rtcp_sdes_unit_s *)jarg1;
result = (char *)(char *) ((arg1)->value);
jresult = SWIG_csharp_string_callback((const char *)result);
return jresult;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_rtcp_sdes_unit_t() {
void * jresult ;
switch_rtcp_sdes_unit_s *result = 0 ;
result = (switch_rtcp_sdes_unit_s *)new switch_rtcp_sdes_unit_s();
jresult = (void *)result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_delete_switch_rtcp_sdes_unit_t(void * jarg1) {
switch_rtcp_sdes_unit_s *arg1 = (switch_rtcp_sdes_unit_s *) 0 ;
arg1 = (switch_rtcp_sdes_unit_s *)jarg1;
delete arg1;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_rtcp_hdr_t_version_set(void * jarg1, unsigned int jarg2) {
switch_rtcp_hdr_s *arg1 = (switch_rtcp_hdr_s *) 0 ;
unsigned int arg2 ;
@ -16290,6 +16203,26 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_expire_registration(int jarg1) {
}
SWIGEXPORT unsigned short SWIGSTDCALL CSharp_switch_core_get_rtp_port_range_start_port() {
unsigned short jresult ;
uint16_t result;
result = (uint16_t)switch_core_get_rtp_port_range_start_port();
jresult = result;
return jresult;
}
SWIGEXPORT unsigned short SWIGSTDCALL CSharp_switch_core_get_rtp_port_range_end_port() {
unsigned short jresult ;
uint16_t result;
result = (uint16_t)switch_core_get_rtp_port_range_end_port();
jresult = result;
return jresult;
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_say_file_handle_get_variable(void * jarg1, char * jarg2) {
char * jresult ;
switch_say_file_handle_t *arg1 = (switch_say_file_handle_t *) 0 ;
@ -25448,6 +25381,28 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_mm_t_vencspd_get(void * jarg1) {
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_mm_t_try_hardware_encoder_set(void * jarg1, unsigned char jarg2) {
switch_mm_s *arg1 = (switch_mm_s *) 0 ;
uint8_t arg2 ;
arg1 = (switch_mm_s *)jarg1;
arg2 = (uint8_t)jarg2;
if (arg1) (arg1)->try_hardware_encoder = arg2;
}
SWIGEXPORT unsigned char SWIGSTDCALL CSharp_switch_mm_t_try_hardware_encoder_get(void * jarg1) {
unsigned char jresult ;
switch_mm_s *arg1 = (switch_mm_s *) 0 ;
uint8_t result;
arg1 = (switch_mm_s *)jarg1;
result = (uint8_t) ((arg1)->try_hardware_encoder);
jresult = result;
return jresult;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_mm_t() {
void * jresult ;
switch_mm_s *result = 0 ;
@ -26613,6 +26568,50 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_switch_file_handle_flag_mutex_get(void * ja
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_file_handle_duration_set(void * jarg1, long long jarg2) {
switch_file_handle *arg1 = (switch_file_handle *) 0 ;
int64_t arg2 ;
arg1 = (switch_file_handle *)jarg1;
arg2 = (int64_t)jarg2;
if (arg1) (arg1)->duration = arg2;
}
SWIGEXPORT long long SWIGSTDCALL CSharp_switch_file_handle_duration_get(void * jarg1) {
long long jresult ;
switch_file_handle *arg1 = (switch_file_handle *) 0 ;
int64_t result;
arg1 = (switch_file_handle *)jarg1;
result = (int64_t) ((arg1)->duration);
jresult = result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_file_handle_vpos_set(void * jarg1, long long jarg2) {
switch_file_handle *arg1 = (switch_file_handle *) 0 ;
int64_t arg2 ;
arg1 = (switch_file_handle *)jarg1;
arg2 = (int64_t)jarg2;
if (arg1) (arg1)->vpos = arg2;
}
SWIGEXPORT long long SWIGSTDCALL CSharp_switch_file_handle_vpos_get(void * jarg1) {
long long jresult ;
switch_file_handle *arg1 = (switch_file_handle *) 0 ;
int64_t result;
arg1 = (switch_file_handle *)jarg1;
result = (int64_t) ((arg1)->vpos);
jresult = result;
return jresult;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_file_handle() {
void * jresult ;
switch_file_handle *result = 0 ;
@ -29703,6 +29702,28 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_video_codec_settings_height_get(void *
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_video_codec_settings_try_hardware_encoder_set(void * jarg1, unsigned char jarg2) {
switch_video_codec_settings *arg1 = (switch_video_codec_settings *) 0 ;
uint8_t arg2 ;
arg1 = (switch_video_codec_settings *)jarg1;
arg2 = (uint8_t)jarg2;
if (arg1) (arg1)->try_hardware_encoder = arg2;
}
SWIGEXPORT unsigned char SWIGSTDCALL CSharp_switch_video_codec_settings_try_hardware_encoder_get(void * jarg1) {
unsigned char jresult ;
switch_video_codec_settings *arg1 = (switch_video_codec_settings *) 0 ;
uint8_t result;
arg1 = (switch_video_codec_settings *)jarg1;
result = (uint8_t) ((arg1)->try_hardware_encoder);
jresult = result;
return jresult;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_video_codec_settings() {
void * jresult ;
switch_video_codec_settings *result = 0 ;
@ -38775,6 +38796,22 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_3p_nomedia(char * jarg1, unsigned l
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_ivr_bg_media(char * jarg1, unsigned long jarg2, int jarg3, int jarg4, unsigned long jarg5) {
char *arg1 = (char *) 0 ;
switch_media_flag_t arg2 ;
switch_bool_t arg3 ;
switch_bool_t arg4 ;
uint32_t arg5 ;
arg1 = (char *)jarg1;
arg2 = (switch_media_flag_t)jarg2;
arg3 = (switch_bool_t)jarg3;
arg4 = (switch_bool_t)jarg4;
arg5 = (uint32_t)jarg5;
switch_ivr_bg_media((char const *)arg1,arg2,arg3,arg4,arg5);
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_hold_uuid(char * jarg1, char * jarg2, int jarg3) {
int jresult ;
char *arg1 = (char *) 0 ;
@ -41281,6 +41318,18 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_rtp_destroy(void * jarg1) {
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_sync_stats(void * jarg1) {
int jresult ;
switch_rtp_t *arg1 = (switch_rtp_t *) 0 ;
switch_status_t result;
arg1 = (switch_rtp_t *)jarg1;
result = (switch_status_t)switch_rtp_sync_stats(arg1);
jresult = result;
return jresult;
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_activate_ice(void * jarg1, char * jarg2, char * jarg3, char * jarg4, char * jarg5, int jarg6, int jarg7, void * jarg8) {
int jresult ;
switch_rtp_t *arg1 = (switch_rtp_t *) 0 ;

File diff suppressed because it is too large Load Diff

View File

@ -120,7 +120,7 @@ static int find_unprintable(const char *s)
const char *p;
for(p = s; p && *p; p++) {
if (*p < 10 || *p == 27) {
if (*p < 9 || *p == 27) {
return 1;
}
}

View File

@ -534,6 +534,7 @@ static abyss_bool http_directory_auth(TSession *r, char *domain_name)
ResponseAddField(r, "freeswitch-user", (box ? box : user));
ResponseAddField(r, "freeswitch-domain", domain_name);
ResponseStatus(r, 200);
rval = TRUE;
goto done;
}
@ -707,6 +708,11 @@ abyss_bool auth_hook(TSession * r)
char *domain_name, *e;
abyss_bool ret = FALSE;
/* Default to 500 status to avoid assert. It should be
overridden later if we actually handle it or if the
default handler in abyss handles it. */
ResponseStatus(r, 500);
if (globals.enable_websocket && !strncmp(r->requestInfo.uri, "/socket", 7)) {
// Chrome has no Authorization support yet
// https://code.google.com/p/chromium/issues/detail?id=123862
@ -827,6 +833,11 @@ abyss_bool handler_hook(TSession * r)
return FALSE;
}
/* Default to 500 status to avoid assert. It should be
overridden later if we actually handle it or if the
default handler in abyss handles it. */
ResponseStatus(r, 500);
stream.data = r;
stream.write_function = http_stream_write;
stream.raw_write_function = http_stream_raw_write;

View File

@ -908,6 +908,11 @@ SWITCH_DECLARE(const char *) switch_get_addr(char *buf, switch_size_t len, switc
return buf;
}
SWITCH_DECLARE(int) switch_socket_fd_get(switch_socket_t *sock)
{
return apr_socket_fd_get(sock);
}
SWITCH_DECLARE(uint16_t) switch_sockaddr_get_port(switch_sockaddr_t *sa)
{
return sa->port;

View File

@ -3883,6 +3883,10 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables_check(switch_channel_t *c
p++;
continue;
} else if (*(p + 1) == '\\') {
if (len + 1 >= olen) {
resize(1);
}
*c++ = *p++;
len++;
continue;
@ -3908,6 +3912,10 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables_check(switch_channel_t *c
}
if (nv) {
if (len + 1 >= olen) {
resize(1);
}
*c++ = *p;
len++;
nv = 0;
@ -4103,11 +4111,12 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables_check(switch_channel_t *c
vname = NULL;
br = 0;
}
if (len + 1 >= olen) {
resize(1);
}
if (sp) {
if (len + 1 >= olen) {
resize(1);
}
*c++ = ' ';
sp = 0;
len++;
@ -4116,6 +4125,10 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables_check(switch_channel_t *c
if (*p == '$') {
p--;
} else {
if (len + 1 >= olen) {
resize(1);
}
*c++ = *p;
len++;
}

View File

@ -3281,6 +3281,28 @@ SWITCH_DECLARE(int) switch_stream_system(const char *cmd, switch_stream_handle_t
}
SWITCH_DECLARE(uint16_t) switch_core_get_rtp_port_range_start_port()
{
uint16_t start_port = 0;
/* By default pass rtp port range start value as zero in order to get actual
* RTP port range start value as configured */
start_port = (uint16_t)switch_rtp_set_start_port((switch_port_t)start_port);
return start_port;
}
SWITCH_DECLARE(uint16_t) switch_core_get_rtp_port_range_end_port()
{
uint16_t end_port = 0;
/* By default pass rtp port range end value as zero in order to get actual
* RTP port range end value as configured */
end_port = (uint16_t)switch_rtp_set_end_port((switch_port_t)end_port);
return end_port;
}
/* For Emacs:
* Local Variables:
* mode:c

View File

@ -1535,6 +1535,30 @@ static void set_stats(switch_core_session_t *session, switch_media_type_t type,
}
}
SWITCH_DECLARE(void) switch_core_media_sync_stats(switch_core_session_t *session)
{
switch_media_handle_t *smh;
switch_rtp_engine_t *a_engine, *v_engine;
switch_assert(session);
if (!(smh = session->media_handle)) {
return;
}
a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
if (a_engine->rtp_session) {
switch_rtp_sync_stats(a_engine->rtp_session);
}
if (v_engine->rtp_session) {
switch_rtp_sync_stats(v_engine->rtp_session);
}
}
SWITCH_DECLARE(void) switch_core_media_set_stats(switch_core_session_t *session)
{
@ -1542,6 +1566,8 @@ SWITCH_DECLARE(void) switch_core_media_set_stats(switch_core_session_t *session)
return;
}
switch_core_media_sync_stats(session);
set_stats(session, SWITCH_MEDIA_TYPE_AUDIO, "audio");
set_stats(session, SWITCH_MEDIA_TYPE_VIDEO, "video");
}

View File

@ -228,10 +228,36 @@ SWITCH_DECLARE(int) switch_img_set_rect(switch_image_t *img,
#endif
}
SWITCH_DECLARE(void) switch_img_flip(switch_image_t *img)
SWITCH_DECLARE(void) switch_img_rotate(switch_image_t **img, switch_image_rotation_mode_t mode)
{
#ifdef SWITCH_HAVE_VPX
vpx_img_flip((vpx_image_t *)img);
#ifdef SWITCH_HAVE_YUV
switch_image_t *tmp_img;
switch_assert(img);
if ((*img)->fmt != SWITCH_IMG_FMT_I420) return;
if (mode == SRM_90 || mode == SRM_270) {
tmp_img = switch_img_alloc(NULL, (*img)->fmt, (*img)->d_h, (*img)->d_w, 1);
} else {
tmp_img = switch_img_alloc(NULL, (*img)->fmt, (*img)->d_w, (*img)->d_h, 1);
}
switch_assert(tmp_img);
I420Rotate((*img)->planes[SWITCH_PLANE_Y], (*img)->stride[SWITCH_PLANE_Y],
(*img)->planes[SWITCH_PLANE_U], (*img)->stride[SWITCH_PLANE_U],
(*img)->planes[SWITCH_PLANE_V], (*img)->stride[SWITCH_PLANE_V],
tmp_img->planes[SWITCH_PLANE_Y], tmp_img->stride[SWITCH_PLANE_Y],
tmp_img->planes[SWITCH_PLANE_U], tmp_img->stride[SWITCH_PLANE_U],
tmp_img->planes[SWITCH_PLANE_V], tmp_img->stride[SWITCH_PLANE_V],
(*img)->d_w, (*img)->d_h, (int)mode);
switch_img_free(img);
*img = tmp_img;
#endif
}
@ -429,6 +455,44 @@ SWITCH_DECLARE(void) switch_img_copy(switch_image_t *img, switch_image_t **new_i
#endif
}
SWITCH_DECLARE(void) switch_img_rotate_copy(switch_image_t *img, switch_image_t **new_img, switch_image_rotation_mode_t mode)
{
switch_assert(img);
switch_assert(new_img);
#ifdef SWITCH_HAVE_YUV
if (img->fmt != SWITCH_IMG_FMT_I420) abort();
if (*new_img != NULL) {
if (img->fmt != (*new_img)->fmt || img->d_w != (*new_img)->d_w || img->d_h != (*new_img)->d_w) {
switch_img_free(new_img);
}
}
if (*new_img == NULL) {
if (mode == SRM_90 || mode == SRM_270) {
*new_img = switch_img_alloc(NULL, img->fmt, img->d_h, img->d_w, 1);
} else {
*new_img = switch_img_alloc(NULL, img->fmt, img->d_w, img->d_h, 1);
}
}
switch_assert(*new_img);
I420Rotate(img->planes[SWITCH_PLANE_Y], img->stride[SWITCH_PLANE_Y],
img->planes[SWITCH_PLANE_U], img->stride[SWITCH_PLANE_U],
img->planes[SWITCH_PLANE_V], img->stride[SWITCH_PLANE_V],
(*new_img)->planes[SWITCH_PLANE_Y], (*new_img)->stride[SWITCH_PLANE_Y],
(*new_img)->planes[SWITCH_PLANE_U], (*new_img)->stride[SWITCH_PLANE_U],
(*new_img)->planes[SWITCH_PLANE_V], (*new_img)->stride[SWITCH_PLANE_V],
img->d_w, img->d_h, (int)mode);
#else
return;
#endif
}
SWITCH_DECLARE(switch_image_t *) switch_img_copy_rect(switch_image_t *img, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
{
#ifdef SWITCH_HAVE_VPX

View File

@ -2240,6 +2240,10 @@ SWITCH_DECLARE(char *) switch_event_expand_headers_check(switch_event_t *event,
p++;
continue;
} else if (*(p + 1) == '\\') {
if (len + 1 >= olen) {
resize(1);
}
*c++ = *p++;
len++;
continue;
@ -2264,6 +2268,10 @@ SWITCH_DECLARE(char *) switch_event_expand_headers_check(switch_event_t *event,
}
if (nv) {
if (len + 1 >= olen) {
resize(1);
}
*c++ = *p;
len++;
nv = 0;
@ -2464,11 +2472,12 @@ SWITCH_DECLARE(char *) switch_event_expand_headers_check(switch_event_t *event,
vtype = 0;
br = 0;
}
if (len + 1 >= olen) {
resize(1);
}
if (sp) {
if (len + 1 >= olen) {
resize(1);
}
*c++ = ' ';
sp = 0;
len++;
@ -2477,6 +2486,10 @@ SWITCH_DECLARE(char *) switch_event_expand_headers_check(switch_event_t *event,
if (*p == '$') {
p--;
} else {
if (len + 1 >= olen) {
resize(1);
}
*c++ = *p;
len++;
}

View File

@ -2576,8 +2576,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_session(switch_core_session_t
out_file = switch_core_session_sprintf(session, "%s-out.%s", file, ext);
rh->in_fh.pre_buffer_datalen = rh->out_fh.pre_buffer_datalen = fh->pre_buffer_datalen;
channels = 1;
switch_set_flag_locked(&rh->in_fh, SWITCH_FILE_NATIVE);
switch_set_flag_locked(&rh->out_fh, SWITCH_FILE_NATIVE);
switch_set_flag(&rh->in_fh, SWITCH_FILE_NATIVE);
switch_set_flag(&rh->out_fh, SWITCH_FILE_NATIVE);
if (switch_core_file_open(&rh->in_fh, in_file, channels, read_impl.actual_samples_per_second, file_flags, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error opening %s\n", in_file);

View File

@ -129,7 +129,11 @@ typedef struct {
#pragma pack(push, r1, 1)
#endif
typedef struct switch_rtcp_sdes_unit_s {
unsigned char type;
unsigned char length;
char value[];
} switch_rtcp_sdes_unit_t;
typedef struct {
uint32_t ssrc;
@ -203,6 +207,9 @@ struct switch_rtp_vad_data {
uint8_t start_count;
uint8_t scan_freq;
time_t next_scan;
switch_time_t start_talking;
switch_time_t stop_talking;
switch_time_t total_talk_time;
int fire_events;
};
@ -553,6 +560,7 @@ static handle_rfc2833_result_t handle_rfc2833(switch_rtp_t *rtp_session, switch_
rtp_session->dtmf_data.last_digit = 0;
rtp_session->dtmf_data.in_digit_ts = 0;
rtp_session->dtmf_data.in_digit_queued = 0;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Failed DTMF sanity check.\n");
}
@ -586,6 +594,7 @@ static handle_rfc2833_result_t handle_rfc2833(switch_rtp_t *rtp_session, switch_
rtp_session->dtmf_data.last_digit = 0;
rtp_session->dtmf_data.in_digit_ts = 0;
rtp_session->dtmf_data.in_digit_sanity = 0;
rtp_session->dtmf_data.in_digit_queued = 0;
}
end = packet[1] & 0x80 ? 1 : 0;
@ -624,6 +633,16 @@ static handle_rfc2833_result_t handle_rfc2833(switch_rtp_t *rtp_session, switch_
ts, duration, rtp_session->last_rtp_hdr.m, end, end && !rtp_session->dtmf_data.in_digit_ts ? "ignored" : "");
#endif
if (rtp_session->dtmf_data.in_digit_ts && rtp_session->dtmf_data.in_digit_ts != ts) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TS changed from last packet, resetting....\n");
rtp_session->dtmf_data.last_digit = 0;
rtp_session->dtmf_data.in_digit_ts = 0;
rtp_session->dtmf_data.in_digit_sanity = 0;
rtp_session->dtmf_data.in_digit_queued = 0;
}
if (!rtp_session->dtmf_data.in_digit_queued && rtp_session->dtmf_data.in_digit_ts) {
if ((rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION)) {
switch_dtmf_t dtmf = { key, switch_core_min_dtmf_duration(0), 0, SWITCH_DTMF_RTP };
@ -4446,6 +4465,29 @@ SWITCH_DECLARE(uint8_t) switch_rtp_ready(switch_rtp_t *rtp_session)
return ret;
}
SWITCH_DECLARE(switch_status_t) switch_rtp_sync_stats(switch_rtp_t *rtp_session)
{
if (!rtp_session) {
return SWITCH_STATUS_FALSE;
}
if (rtp_session->flags[SWITCH_RTP_FLAG_VAD]) {
switch_channel_t *channel = switch_core_session_get_channel(rtp_session->vad_data.session);
switch_channel_set_variable_printf(channel, "vad_total_talk_time_ms", "%u", (uint32_t)rtp_session->vad_data.total_talk_time / 1000);
switch_channel_set_variable_printf(channel, "vad_total_talk_time_sec", "%u", (uint32_t)rtp_session->vad_data.total_talk_time / 1000000);
}
do_mos(rtp_session, SWITCH_TRUE);
if (rtp_session->stats.inbound.error_log && !rtp_session->stats.inbound.error_log->stop) {
rtp_session->stats.inbound.error_log->stop = switch_micro_time_now();
}
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session)
{
void *pop;
@ -4468,10 +4510,8 @@ SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session)
READ_DEC((*rtp_session));
WRITE_DEC((*rtp_session));
do_mos(*rtp_session, SWITCH_TRUE);
if ((*rtp_session)->stats.inbound.error_log && !(*rtp_session)->stats.inbound.error_log->stop) {
(*rtp_session)->stats.inbound.error_log->stop = switch_micro_time_now();
if ((*rtp_session)->flags[SWITCH_RTP_FLAG_VAD]) {
switch_rtp_disable_vad(*rtp_session);
}
switch_mutex_lock((*rtp_session)->flag_mutex);
@ -4533,10 +4573,6 @@ SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session)
}
}
if ((*rtp_session)->flags[SWITCH_RTP_FLAG_VAD]) {
switch_rtp_disable_vad(*rtp_session);
}
#ifdef ENABLE_SRTP
if ((*rtp_session)->flags[SWITCH_RTP_FLAG_SECURE_SEND]) {
for(x = 0; x < 2; x++) {
@ -7314,7 +7350,7 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
uint32_t len = sizeof(decoded);
time_t now = switch_epoch_time_now(NULL);
send = 0;
if (rtp_session->vad_data.scan_freq && rtp_session->vad_data.next_scan <= now) {
rtp_session->vad_data.bg_count = rtp_session->vad_data.bg_level = 0;
rtp_session->vad_data.next_scan = now + rtp_session->vad_data.scan_freq;
@ -7355,7 +7391,7 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
} else {
if (score > rtp_session->vad_data.bg_level && !switch_test_flag(&rtp_session->vad_data, SWITCH_VAD_FLAG_TALKING)) {
uint32_t diff = score - rtp_session->vad_data.bg_level;
if (rtp_session->vad_data.hangover_hits) {
rtp_session->vad_data.hangover_hits--;
}
@ -7363,6 +7399,9 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
if (diff >= rtp_session->vad_data.diff_level || ++rtp_session->vad_data.hangunder_hits >= rtp_session->vad_data.hangunder) {
switch_set_flag(&rtp_session->vad_data, SWITCH_VAD_FLAG_TALKING);
rtp_session->vad_data.start_talking = switch_time_now();
if (!(rtp_session->rtp_bugs & RTP_BUG_NEVER_SEND_MARKER)) {
send_msg->header.m = 1;
}
@ -7384,10 +7423,14 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
}
if (switch_test_flag(&rtp_session->vad_data, SWITCH_VAD_FLAG_TALKING)) {
if (++rtp_session->vad_data.hangover_hits >= rtp_session->vad_data.hangover) {
rtp_session->vad_data.stop_talking = switch_time_now();
rtp_session->vad_data.total_talk_time += (rtp_session->vad_data.stop_talking - rtp_session->vad_data.start_talking);
switch_clear_flag(&rtp_session->vad_data, SWITCH_VAD_FLAG_TALKING);
rtp_session->vad_data.hangover_hits = rtp_session->vad_data.hangunder_hits = rtp_session->vad_data.cng_count = 0;
if (switch_test_flag(&rtp_session->vad_data, SWITCH_VAD_FLAG_EVENTS_NOTALK)) {
if ((rtp_session->vad_data.fire_events & VAD_FIRE_NOT_TALK)) {
switch_event_t *event;
if (switch_event_create(&event, SWITCH_EVENT_NOTALK) == SWITCH_STATUS_SUCCESS) {
@ -7672,6 +7715,9 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_enable_vad(switch_rtp_t *rtp_session,
rtp_session->vad_data.start = 0;
rtp_session->vad_data.next_scan = switch_epoch_time_now(NULL);
rtp_session->vad_data.scan_freq = 0;
if (switch_test_flag(&rtp_session->vad_data, SWITCH_VAD_FLAG_TALKING)) {
rtp_session->vad_data.start_talking = switch_time_now();
}
switch_rtp_set_flag(rtp_session, SWITCH_RTP_FLAG_VAD);
switch_set_flag(&rtp_session->vad_data, SWITCH_VAD_FLAG_CNG);
return SWITCH_STATUS_SUCCESS;