initial public version

This commit is contained in:
Johannes Barthel 2021-08-13 12:53:18 +02:00
parent ebe8636605
commit 6c8525ef54
195 changed files with 15904 additions and 0 deletions

188
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,188 @@
# set up stages
variables:
GIT_STRATEGY: fetch
stages:
- change detection
- get external dependencies
- build
- push packages
# define which docker image to use for builds
default:
image: gitlab.senfcall.de:5050/senfcall-public/docker-bbb-build:v2021-08-10
# This stage uses git to find out since when each package has been unmodified.
# it then checks an API endpoint on the package server to find out for which of
# these versions a build exists. If a viable build (from a commit where the
# package is identical) is found, that package name and .deb-filename are
# written to a file `packages_to_skip.txt` the root of the repo. This file is
# passed to the subsequent stages:
# - The jobs in the build stage check whether "their" package is listed in
# `packages_to_skip.txt` and don't build a new one if it is.
# - The bigbluebutton-build job includes the package versions listed in that
# file as version-pinned dependencies of the `bigbluebutton` package (instead
# of the current commit version)
# - The push_packages job sends the filenames of the packages that can be reused
# to the server, so they are included with the current branch. (Relevant for
# commits that start a new branch and don't change all packages)
change_detection:
stage: change detection
script: build/change_detection.sh
artifacts:
paths:
- packages_to_skip.txt
# replace placeholder files with actual external repos
# (for source and version of the package see the placeholder file)
# this step will be obsolete once dependencies can be tracked as
# git submodules
get_external_dependencies:
stage: get external dependencies
script: build/get_external_dependencies.sh
artifacts:
paths:
- bbb-etherpad
- bbb-webrtc-sfu
- freeswitch
- bbb-playback
expire_in: 1h 30min
# template job for build step
.build_job:
stage: build
artifacts:
paths:
- artifacts/*.deb
expire_in: 1h 30min
cache:
key: $CI_COMMIT_REF_SLUG
paths:
- cache/.gradle
# jobs for all packages in the "build" stage (templated from above)
bbb-activity-report:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-activity-report
bbb-apps-akka-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-apps-akka
bbb-config-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-config
bbb-demo-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-demo
bbb-etherpad-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-etherpad
bbb-freeswitch-core-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-freeswitch-core
bbb-freeswitch-sounds-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-freeswitch-sounds
bbb-fsesl-akka-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-fsesl-akka
bbb-html5-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-html5
bbb-libreoffice-docker-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-libreoffice-docker
bbb-lti-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-lti
bbb-mkclean-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-mkclean
bbb-playback-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-playback
bbb-playback-notes-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-playback-notes
bbb-playback-podcast-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-playback-podcast
bbb-playback-presentation-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-playback-presentation
bbb-playback-screenshare-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-playback-screenshare
bbb-record-core-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-record-core
bbb-web-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-web
bbb-webhooks-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-webhooks
bbb-webrtc-sfu-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bbb-webrtc-sfu
bigbluebutton-build:
extends: .build_job
script:
- build/setup-inside-docker.sh bigbluebutton
# upload packages to repo server
push_packages:
stage: push packages
script: build/push_packages.sh
resource_group: push_packages
# uncomment the lines below if you want one final
# "artifacts" dir with all packages (increases runtime, fills up space on gitlab server)
#artifacts:
# paths:
# - artifacts/*
# expire_in: 2 days

View File

@ -0,0 +1,2 @@
git clone --branch 1.8.13 --depth 1 https://github.com/ether/etherpad-lite bbb-etherpad

View File

@ -0,0 +1 @@
git clone --branch v2.3.3 --depth 1 https://github.com/bigbluebutton/bbb-playback bbb-playback

View File

@ -0,0 +1 @@
git clone --branch v2.5.2 --depth 1 https://github.com/bigbluebutton/bbb-webrtc-sfu bbb-webrtc-sfu

1
build/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
cache/**

35
build/README.md Normal file
View File

@ -0,0 +1,35 @@
# build
build scripts for packaging bigbluebutton.
This directory contains scripts for the new open-source Gitlab-CI based build system, which shall replace the legacy non-public Jenkins based process. The build scripts in `packages-template` have been adapted from the old system, and still have room for improvement / cleanup.
## build locally
You can build packages locally. Docker is required to be installed on your machine.
First, get the external dependencies (this can be migrated to git submodules once the legacy CI system has been retired):
```bash
./build/get_external_dependencies.sh
```
For example, to build the `bbb-html5` package, run the following command from the repository's root directory.
```bash
./build/setup.sh bbb-html5
```
The package will be put into the `artifacts/` subdirectory.
## build using CI
![Diagram showing the CI build process](bbb-ci.png)
The CI is defined by the file `.gitlab-ci.yml` in the root directory of this repo.
In CI, the build process is done in four stages:
1. The first stage determines the last commit that changed each package, and all commits since that made no change to the package. The debian repository server is then queried, to see whether a package is already available for any of those commits. If yes, the package version is written to a file called `packages-to-skip.txt`.
2. The second steps pulls in external dependencies. This could be later changed to use git submodules. As of now, that would break the old CI, therefore this step exists.
3. Debian packages are built in parallel for each component. Packages listed in `packages-to-skip.txt` are not build (see stage 1). A `bigbluebutton` meta-package is also created. This package depends on the exact versions of the other core packages, e.g. either packages with the same commit hash (for those that have been built), or the respective version listed in `packages-to-skip.txt`.
4. Packages are uploaded to the debian repository server. The endpoint on the repo server also receives the branch name, and generates/updates that branch's repository with all relevant (uploaded and reused) packages.
The repo server software can be found at https://gitlab.senfcall.de/senfcall-public/ci-repo-upload .

BIN
build/bbb-ci.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

44
build/change_detection.sh Executable file
View File

@ -0,0 +1,44 @@
#!/bin/bash -e
# TODO:
# - get available packages from repo server
# - actually use the VALID_PACKAGE_VERSIONS
# to check whether to rebuild.
# - export that information and use in
# setup-inside-docker.sh and the push job
cd "$(dirname $0)"
source package-names.inc.sh
cd ..
REQ_JSON=""
for DEBNAME in "${!DEBNAME_TO_SOURCEDIR[@]}"
do
if [ "$DEBNAME" == bigbluebutton ] ; then
# always rebuild the meta package
continue
fi
#echo "package $DEBNAME"
SOURCEDIR="${DEBNAME_TO_SOURCEDIR[$DEBNAME]}"
if [ "$SOURCEDIR" == "do_not_copy_anything" ] ; then
SOURCEDIR=""
fi
LAST_CHANGE="$(git log -n1 --format=format:%H -- ${SOURCEDIR} "build/packages-template/$DEBNAME" .gitlab-ci.yml build/*.sh)"
VALID_PACKAGE_VERSIONS="$(git log --format=%H "${LAST_CHANGE}^..HEAD")"
VALID_PACKAGE_VERSIONS="$(for HASH in $VALID_PACKAGE_VERSIONS; do echo -n "${HASH::10} "; done)"
VALID_PACKAGE_VERSIONS="${VALID_PACKAGE_VERSIONS::-1}"
REQ_JSON="${REQ_JSON} \"$DEBNAME\": [\"${VALID_PACKAGE_VERSIONS//$' '/\",\"}\"],"
done
REQ_JSON="{${REQ_JSON:1:-1}}"
curl \
-u "${PACKAGES_UPLOAD_AUTHENTICATION}" \
-X POST \
--data "$REQ_JSON" \
"${PACKAGES_UPLOAD_BASE_URL}/cgi-bin/get_compatible_packages.py" \
> packages_to_skip.txt
echo "We will re-use the following packages:"
cat packages_to_skip.txt

277
build/deb-helper.sh Executable file
View File

@ -0,0 +1,277 @@
#!/bin/bash -e
############################
### BEGIN DEB-HELPERS.SH ###
############################
#
# Adding service to autostart
# $1 = service name
#
startService() {
app_name=$1
if hash systemctl > /dev/null 2>&1 && [ ! -f /.dockerenv ]; then
# if there no .service or .timer (or any other suffix), it will add .service suffix
if [[ ! $app_name =~ ^.*\.[a-z]*$ ]]; then
app_name="$app_name.service"
fi
echo "Adding $app_name to autostart using systemd"
systemctl enable $app_name
systemctl start $app_name
elif hash update-rc.d > /dev/null 2>&1 && [ ! -f /.dockerenv ]; then
echo "Adding $app_name to autostart using update-rc.d"
update-rc.d $app_name defaults
service $app_name start
elif hash chkconfig > /dev/null 2>&1; then
echo "Adding $app_name to autostart using chkconfig"
chkconfig --add $app_name
chkconfig $app_name on
service $app_name start
else
echo "WARNING: Could not add $app_name to autostart: neither update-rc nor chkconfig found!"
fi
}
#
# Removing service from autostart
# $1 = service name
#
stopService() {
app_name=$1
if hash systemctl > /dev/null 2>&1 && [ ! -f /.dockerenv ]; then
# if there no .service or .timer (or any other suffix), it will add .service suffix
if [[ ! $app_name =~ ^.*\.[a-z]*$ ]]; then
app_name="$app_name.service"
fi
echo "Removing $app_name from autostart using systemd"
if systemctl -q is-active $app_name; then
systemctl stop $app_name
fi
if systemctl is-enabled $app_name > /dev/null 2>&1; then
systemctl disable $app_name
fi
elif hash update-rc.d > /dev/null 2>&1 && [ ! -f /.dockerenv ]; then
echo "Removing $app_name from autostart using update-rc.d"
update-rc.d -f $app_name remove
service $app_name stop
elif hash chkconfig > /dev/null 2>&1; then
echo "Removing $app_name from autostart using chkconfig"
chkconfig $app_name off
chkconfig --del $app_name
service $app_name stop
else
echo "WARNING: Could not remove $app_name from autostart: neither update-rc nor chkconfig found!"
fi
}
#
# Reload service
# $1 = service name
#
reloadService() {
app_name=$1
if hash systemctl > /dev/null 2>&1 && [ ! -f /.dockerenv ]; then
# if there no .service or .timer (or any other suffix), it will add .service suffix
if [[ ! $app_name =~ ^.*\.[a-z]*$ ]]; then
app_name="$app_name.service"
fi
echo "Reloading $app_name using systemd"
if systemctl status $app_name > /dev/null 2>&1; then
systemctl reload-or-restart $app_name
else
startService $app_name
fi
elif hash service > /dev/null 2>&1; then
echo "Reloading $app_name using service"
service $app_name reload
else
echo "WARNING: Could not reload $app_name: neither update-rc nor chkconfig found!"
fi
}
#
# Restart service
# $1 = service name
#
restartService() {
app_name=$1
if hash systemctl > /dev/null 2>&1 && [ ! -f /.dockerenv ]; then
# if there no .service or .timer (or any other suffix), it will add .service suffix
if [[ ! $app_name =~ ^.*\.[a-z]*$ ]]; then
app_name="$app_name.service"
fi
echo "Restart $app_name using systemd"
if systemctl status $app_name > /dev/null 2>&1; then
systemctl restart $app_name
else
startService $app_name
fi
elif hash service > /dev/null 2>&1; then
echo "Restart $app_name using service"
service $app_name restart
else
echo "WARNING: Could not restart $app_name: neither update-rc nor chkconfig found!"
fi
}
#
# Adapted from SBT scripts. See
# https://github.com/sbt/sbt-native-packager/blob/master/src/main/resources/com/typesafe/sbt/packager/linux/control-functions
#
# Adding system user
# $1 = user
# $2 = uid
# $3 = group
# $4 = home directory
# $5 = description
# $6 = shell (defaults to /bin/false)
addUser() {
user="$1"
if [ -z "$user" ]; then
# echo "usage: addUser user [group] [description] [shell]"
exit 1
fi
uid="$2"
if [ -z "$uid" ]; then
uid_flags=""
else
uid_flags="--uid $uid"
fi
if [ -z "$4" ]; then
home_flags="--no-create-home"
else
home_flags="-d $4"
fi
group=${3:-$user}
descr=${5:-No description}
shell=${6:-/bin/false}
if ! getent passwd | grep -q "^$user:";
then
# echo "Creating system user: $user in $group with $descr and shell $shell"
useradd $uid_flags --gid $group $home_flags --system --shell $shell -c "$descr" $user
fi
}
# Adding system group
# $1 = group
# $2 = gid
addGroup() {
group="$1"
gid="$2"
if [ -z "$gid" ]; then
gid_flags=""
else
gid_flags="--gid $gid"
fi
if ! getent group | grep -q "^$group:" ;
then
# echo "Creating system group: $group"
groupadd $gid_flags --system $group
fi
}
# Will return true even if deletion fails
# $1 = user
deleteUser() {
if hash deluser 2>/dev/null; then
deluser --quiet --system $1 > /dev/null || true
elif hash userdel 2>/dev/null; then
userdel $1
else
echo "WARNING: Could not delete user $1 . No suitable program (deluser, userdel) found"
fi
}
# Will return true even if deletion fails
# $1 = group
deleteGroup() {
if hash delgroup 2>/dev/null; then
delgroup --quiet --system $1 > /dev/null || true
elif hash groupdel 2>/dev/null; then
groupdel $1
else
echo "WARNING: Could not delete user $1 . No suitable program (delgroup, groupdel) found"
fi
}
get_yml_properties() {
cat ${1} | grep : | grep -v \# | grep -v :$ | sed -e "s/ //g" -e "s/:.*/ /g" | tr -d '\n'
}
get_yml_value() {
# cat ${1} | tr -d '\r' | sed -n "/^[[:blank:]#]*${2}:[ ]*/{s/^[[:blank:]#]*${2}:[ ]*//;p}"
cat ${1} | tr -d '\r' | sed -n "/${2}/{s/[^:]*:[ ]*//;p}"
}
change_yml_value () {
sed -i "s<^\([[:blank:]#]*\)\(${2}\): .*<\1\2: ${3}<" $1
}
create_keep_file() {
SOURCE=$1
SOURCE_ORIG=$SOURCE.orig
TARGET="/tmp/$(basename $SOURCE).keep"
rm -f $TARGET
if [ -f $SOURCE ] && [ -f $SOURCE_ORIG ]; then
VARS=$(get_yml_properties $SOURCE_ORIG)
for v in $VARS ; do
orig_val=$(get_yml_value $SOURCE_ORIG $v)
val=$(get_yml_value $SOURCE $v)
if [ "$orig_val" != "$val" ]; then
echo "$v: $val" | tee -a $TARGET
fi
done
fi
}
propagate_keep_file() {
TARGET=$1
SOURCE="/tmp/$(basename $TARGET).keep"
if [ -f $SOURCE ] && [ -f $TARGET ]; then
VARS=$(get_yml_properties $SOURCE)
for v in $VARS ; do
old_val=$(get_yml_value $SOURCE $v)
change_yml_value $TARGET $v $old_val
done
fi
}
if LANG=c ifconfig | grep -q 'venet0:0'; then
# IP detection for OpenVZ environment
IP=$(ifconfig | grep -v '127.0.0.1' | grep -E "[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" | tail -1 | cut -d: -f2 | awk '{ print $1}')
else
# use IP address of interface used for primary default route
IP=$(ifconfig $(route | grep ^default | head -1 | sed "s/.* //") | awk '/inet /{ print $2}' | cut -d: -f2)
fi
if [ -f /etc/redhat-release ]; then
TOMCAT_SERVICE=tomcat
else
if grep -q bionic /etc/lsb-release; then
TOMCAT_SERVICE=tomcat8
else
TOMCAT_SERVICE=tomcat7
fi
fi
if [ -f /var/lib/$TOMCAT_SERVICE/webapps/bigbluebutton/WEB-INF/classes/bigbluebutton.properties ]; then
SERVLET_DIR=/var/lib/$TOMCAT_SERVICE/webapps/bigbluebutton
else
SERVLET_DIR=/usr/share/bbb-web
fi
PROTOCOL=http
if [ -f $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties ]; then
SERVER_URL=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | sed -n '/^bigbluebutton.web.serverURL/{s/.*\///;p}')
if cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep bigbluebutton.web.serverURL | grep -q https; then
PROTOCOL=https
fi
fi
##########################
### END DEB-HELPERS.SH ###
##########################

View File

@ -0,0 +1,22 @@
#!/bin/bash -xe
cd "$(dirname "$0")/.."
# get the list of stuff that needs to be downloaded from
# .gitlab-ci.yml, so we don't need to maintain it in two places.
DEPENDENCIES=$(python3 -c 'import yaml; print(" ".join(yaml.load(open(".gitlab-ci.yml"), Loader=yaml.SafeLoader)["get_external_dependencies"]["artifacts"]["paths"]))')
for DEPENDENCY in $DEPENDENCIES; do
DOWNLOAD_COMMAND_FILE="${DEPENDENCY}.placeholder.sh"
echo "getting component ${DOWNLOAD_COMMAND_FILE}..."
bash -xe "$DOWNLOAD_COMMAND_FILE" &
done
wait
set +x
echo "downloaded external dependencies:"
for DEPENDENCY in $DEPENDENCIES; do
du --summarize -h "$DEPENDENCY"
done

2
build/opts-global.sh Normal file
View File

@ -0,0 +1,2 @@
OPTS="--vendor BigBlueButon -m ffdixon@bigbluebutton.org --url http://bigbluebutton.org/"

View File

@ -0,0 +1,26 @@
declare -A DEBNAME_TO_SOURCEDIR
DEBNAME_TO_SOURCEDIR[bbb-activity-report]="bbb-activity-report"
DEBNAME_TO_SOURCEDIR[bbb-apps-akka]="akka-bbb-apps bbb-common-message"
DEBNAME_TO_SOURCEDIR[bbb-config]="bigbluebutton-config"
DEBNAME_TO_SOURCEDIR[bbb-demo]="bbb-api-demo"
DEBNAME_TO_SOURCEDIR[bbb-etherpad]="bbb-etherpad"
DEBNAME_TO_SOURCEDIR[bbb-freeswitch-core]="freeswitch"
DEBNAME_TO_SOURCEDIR[bbb-freeswitch-sounds]="do_not_copy_anything"
DEBNAME_TO_SOURCEDIR[bbb-fsesl-akka]="akka-bbb-fsesl bbb-common-message bbb-fsesl-client"
DEBNAME_TO_SOURCEDIR[bbb-html5]="bigbluebutton-html5"
DEBNAME_TO_SOURCEDIR[bbb-libreoffice-docker]="bbb-libreoffice"
DEBNAME_TO_SOURCEDIR[bbb-lti]="bbb-lti"
DEBNAME_TO_SOURCEDIR[bbb-mkclean]="do_not_copy_anything"
DEBNAME_TO_SOURCEDIR[bbb-playback]="bbb-playback"
DEBNAME_TO_SOURCEDIR[bbb-playback-notes]="record-and-playback/notes"
DEBNAME_TO_SOURCEDIR[bbb-playback-podcast]="record-and-playback/podcast"
DEBNAME_TO_SOURCEDIR[bbb-playback-presentation]="record-and-playback/presentation"
DEBNAME_TO_SOURCEDIR[bbb-playback-screenshare]="record-and-playback/screenshare"
DEBNAME_TO_SOURCEDIR[bbb-record-core]="record-and-playback/core"
DEBNAME_TO_SOURCEDIR[bbb-web]="bigbluebutton-web bbb-common-web bbb-common-message"
DEBNAME_TO_SOURCEDIR[bbb-webhooks]="bbb-webhooks"
DEBNAME_TO_SOURCEDIR[bbb-webrtc-sfu]="bbb-webrtc-sfu"
DEBNAME_TO_SOURCEDIR[bigbluebutton]="do_not_copy_anything"
export DEBNAME_TO_SOURCEDIR

View File

@ -0,0 +1,11 @@
#!/bin/bash -e
BIGBLUEBUTTON_USER=bigbluebutton
# set ownership of activity directory
chown -R $BIGBLUEBUTTON_USER:$BIGBLUEBUTTON_USER /var/bigbluebutton/activity-report/
#
# Restart nginx to take advantage of the updates to /etc/bigbluebutton/nginx
#
reloadService nginx

View File

@ -0,0 +1,7 @@
#!/bin/bash -e
if [ "$1" = "remove" ]; then
rm -fr /var/bigbluebutton/activity-report
rm -f /etc/bigbluebutton/nginx/activity-report.nginx
fi

View File

@ -0,0 +1,47 @@
#!/bin/bash -ex
TARGET=`basename $(pwd)`
BUILD=$1
PACKAGE=$(echo $TARGET | cut -d'_' -f1)
VERSION=$(echo $TARGET | cut -d'_' -f2)
DISTRO=$(echo $TARGET | cut -d'_' -f3)
#
# Clean up directories
rm -rf staging
#
# Create directory for fpm to process
DIRS=""
for dir in $DIRS; do
mkdir -p staging$dir
DIRECTORIES="$DIRECTORIES --directories $dir"
done
##
mkdir -p staging/var/bigbluebutton/activity-report
mkdir -p staging/etc/bigbluebutton/nginx
cp activity-report.nginx staging/etc/bigbluebutton/nginx
# install dependencies, create build, copy build over to destinatino
npm install
npm run build
cp -r build/* staging/var/bigbluebutton/activity-report
##
. ./opts-$DISTRO.sh
fpm -s dir -C ./staging -n $PACKAGE \
--version $VERSION --epoch $EPOCH \
--after-install after-install.sh \
--after-remove after-remove.sh \
--depends unzip \
--description "BigBlueButton bbb-activity-report" \
$DIRECTORIES \
$OPTS

View File

@ -0,0 +1,3 @@
. ./opts-global.sh
OPTS="$OPTS -t deb -d nginx"

View File

@ -0,0 +1,42 @@
#!/bin/bash -ex
TARGET=`basename $(pwd)`
PACKAGE=$(echo $TARGET | cut -d'_' -f1)
DISTRO=$(echo $TARGET | cut -d'_' -f3)
##
EPHEMERAL_VERSION=0.0.$(date +%s)-SNAPSHOT
sed -i "s|\(version := \)\".*|\1\"$EPHEMERAL_VERSION\"|g" bbb-common-message/build.sbt
find -name build.gradle -exec sed -i "s|\(.*org.bigbluebutton.*bbb-common-message[^:]*\):.*|\1:$EPHEMERAL_VERSION'|g" {} \;
find -name build.sbt -exec sed -i "s|\(.*org.bigbluebutton.*bbb-common-message[^\"]*\"[ ]*%[ ]*\)\"[^\"]*\"\(.*\)|\1\"$EPHEMERAL_VERSION\"\2|g" {} \;
export JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF8
cd bbb-common-message
sbt publish
sbt publishLocal
cd ..
cd akka-bbb-apps
sed -i 's/\r$//' project/Dependencies.scala
sed -i 's|\(val bbbCommons = \)"[^"]*"$|\1"EPHEMERAL_VERSION"|g' project/Dependencies.scala
sed -i "s/EPHEMERAL_VERSION/$EPHEMERAL_VERSION/g" project/Dependencies.scala
echo "enablePlugins(SystemdPlugin)" >> build.sbt
echo "serverLoading in Debian := Some(com.typesafe.sbt.packager.archetypes.systemloader.ServerLoader.Systemd)" >> build.sbt
mkdir -p src/templates
echo '#JAVA_OPTS="-Dconfig.file=/usr/share/bbb-apps-akka/conf/application.conf $JAVA_OPTS"' > src/templates/etc-default
sed -i "s/^version .*/version := \"$VERSION\"/g" build.sbt
# set epoch if its greater than 0
if [[ -n $EPOCH && $EPOCH -gt 0 ]] ; then
echo 'version in Debian := "'$EPOCH:$VERSION'"' >> build.sbt
fi
sbt debian:packageBin
cp ./target/*.deb ..
##

View File

@ -0,0 +1 @@
Placeholder so the build scripts work

View File

@ -0,0 +1,118 @@
#!/bin/bash -e
set +x
BIGBLUEBUTTON_USER=bigbluebutton
if ! id freeswitch >/dev/null 2>&1; then
echo "Error: FreeSWITCH not installed"
exit 1
fi
if lsb_release -d | grep -q CentOS; then
DISTRO=centos
FREESWITCH=freeswitch
FREESWITCH_GROUP=daemon
else
DISTRO=ubuntu
FREESWITCH=freeswitch
FREESWITCH_GROUP=freeswitch
fi
#
# Set the permissions to /var/bigbluebutton so both red5 and tomcat can write
#
if [ -d /var/bigbluebutton ]; then
echo -n "."
chown -R $BIGBLUEBUTTON_USER:$BIGBLUEBUTTON_USER /var/bigbluebutton
echo -n "."
chmod o+rx /var/bigbluebutton
#
# Setup for recordings XXX
#
mkdir -p /var/bigbluebutton/recording
mkdir -p /var/bigbluebutton/recording/raw
mkdir -p /var/bigbluebutton/recording/process
mkdir -p /var/bigbluebutton/recording/publish
mkdir -p /var/bigbluebutton/recording/status
mkdir -p /var/bigbluebutton/recording/status/recorded
mkdir -p /var/bigbluebutton/recording/status/archived
mkdir -p /var/bigbluebutton/recording/status/processed
mkdir -p /var/bigbluebutton/recording/status/sanity
echo -n "."
chown -R $BIGBLUEBUTTON_USER:$BIGBLUEBUTTON_USER /var/bigbluebutton/recording
mkdir -p /var/bigbluebutton/published
echo -n "."
chown -R $BIGBLUEBUTTON_USER:$BIGBLUEBUTTON_USER /var/bigbluebutton/published
mkdir -p /var/bigbluebutton/deleted
echo -n "."
chown -R $BIGBLUEBUTTON_USER:$BIGBLUEBUTTON_USER /var/bigbluebutton/deleted
mkdir -p /var/bigbluebutton/unpublished
echo -n "."
chown -R $BIGBLUEBUTTON_USER:$BIGBLUEBUTTON_USER /var/bigbluebutton/unpublished
echo
else
echo "Warning: BigBlueButton not installed"
fi
if [ -f /usr/share/bbb-apps-akka/conf/application.conf ]; then
if [ "$(cat /usr/share/bbb-apps-akka/conf/application.conf | sed -n '/sharedSecret.*/{s/[^"]*"//;s/".*//;p}')" == "changeme" ]; then
SECRET=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | tr -d '\r' | sed -n '/securitySalt/{s/.*=//;p}')
sed -i "s/sharedSecret[ ]*=[ ]*\"[^\"]*\"/sharedSecret=\"$SECRET\"/g" \
/usr/share/bbb-apps-akka/conf/application.conf
HOST=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*\///;p}')
sed -i "s/bbbWebAPI[ ]*=[ ]*\"[^\"]*\"/bbbWebAPI=\"http:\/\/$HOST\/bigbluebutton\/api\"/g" \
/usr/share/bbb-apps-akka/conf/application.conf
sed -i "s/bbbWebHost[ ]*=[ ]*\"[^\"]*\"/bbbWebHost=\"$HOST\"/g" \
/usr/share/bbb-apps-akka/conf/application.conf
sed -i "s/deskshareip[ ]*=[ ]*\"[^\"]*\"/deskshareip=\"$HOST\"/g" \
/usr/share/bbb-apps-akka/conf/application.conf
sed -i "s/defaultPresentationURL[ ]*=[ ]*\"[^\"]*\"/defaultPresentationURL=\"http:\/\/$HOST\/default.pdf\"/g" \
/usr/share/bbb-apps-akka/conf/application.conf
fi
fi
if [ -d /var/bigbluebutton/screenshare ]; then
chown red5:red5 /var/bigbluebutton/screenshare
fi
#
# Added to enable bbb-record-core to move files #8901
#
usermod bigbluebutton -a -G freeswitch
chmod 0775 /var/freeswitch/meetings
if ! id kurento >/dev/null 2>&1; then
useradd --home-dir "/var/lib/kurento" --system kurento
fi
usermod bigbluebutton -a -G kurento
chown kurento:kurento /var/kurento
chmod 0775 /var/kurento
if [ -d /var/kurento/recordings ]; then
chmod 0775 /var/kurento/recordings
fi
if [ -d /var/kurento/screenshare ]; then
chmod 0775 /var/kurento/screenshare
fi
if [ -f /usr/lib/systemd/system/red5.service ]; then
chown root:root /usr/lib/systemd/system/red5.service
fi
sed -i 's/worker_connections 768/worker_connections 4000/g' /etc/nginx/nginx.conf
if ! grep "worker_rlimit_nofile 10000;" /etc/nginx/nginx.conf; then
sed -i 's/events {/worker_rlimit_nofile 10000;\n\nevents {/g' /etc/nginx/nginx.conf
fi
# Load the overrides
systemctl daemon-reload

View File

@ -0,0 +1,4 @@
#if [ -L /etc/nginx/sites-enabled/bigbluebutton ]; then
# rm /etc/nginx/sites-enabled/bigbluebutton
#fi

View File

@ -0,0 +1,82 @@
#!/bin/bash -ex
TARGET=`basename $(pwd)`
PACKAGE=$(echo $TARGET | cut -d'_' -f1)
VERSION=$(echo $TARGET | cut -d'_' -f2)
DISTRO=$(echo $TARGET | cut -d'_' -f3)
#
# Clear staging directory for build
rm -rf staging
#
# Create build directories for markign by fpm
DIRS="/etc/bigbluebutton \
/var/bigbluebutton/blank \
/usr/share/bigbluebutton/blank \
/var/www/bigbluebutton-default"
for dir in $DIRS; do
mkdir -p staging$dir
DIRECTORIES="$DIRECTORIES --directories $dir"
done
cp bigbluebutton-release staging/etc/bigbluebutton
cp slides/nopdfmark.ps staging/etc/bigbluebutton
# XXX remove /var/bigbluebutton
cp slides/blank* staging/var/bigbluebutton/blank
cp slides/blank* staging/usr/share/bigbluebutton/blank
cp -r web/* staging/var/www/bigbluebutton-default
mkdir -p staging/usr/bin
cp bin/bbb-conf bin/bbb-record staging/usr/bin
chmod +x staging/usr/bin/bbb-conf
mkdir -p staging/etc/bigbluebutton/bbb-conf
cp bin/apply-lib.sh staging/etc/bigbluebutton/bbb-conf
mkdir -p staging/etc/cron.daily
cp cron.daily/* staging/etc/cron.daily
mkdir -p staging/etc/cron.hourly
cp cron.hourly/bbb-resync-freeswitch staging/etc/cron.hourly
# Overrides
mkdir -p staging/etc/systemd/system/bbb-apps-akka.service.d
cat > staging/etc/systemd/system/bbb-apps-akka.service.d/override.conf <<HERE
[Unit]
Wants=redis-server.service
After=redis-server.service
HERE
mkdir -p staging/etc/systemd/system/bbb-fsesl-akka.service.d
cat > staging/etc/systemd/system/bbb-fsesl-akka.service.d/override.conf <<HERE
[Unit]
Wants=redis-server.service
After=redis-server.service
HERE
mkdir -p staging/etc/systemd/system/bbb-transcode-akka.service.d
cat > staging/etc/systemd/system/bbb-transcode-akka.service.d/override.conf <<HERE
[Unit]
Wants=redis-server.service
After=redis-server.service
HERE
. ./opts-$DISTRO.sh
#
# Build package
fpm -s dir -C ./staging -n $PACKAGE \
--version $VERSION --epoch $EPOCH \
--after-install after-install.sh \
--after-remove after-remove.sh \
--description "BigBlueButton configuration utilities" \
$DIRECTORIES \
$OPTS

View File

@ -0,0 +1,4 @@
. ./opts-global.sh
AKKA_APPS="bbb-fsesl-akka,bbb-apps-akka"
OPTS="$OPTS -t deb -d netcat-openbsd,bbb-html5,bbb-playback-presentation,bbb-playback,bbb-freeswitch-core,stuntman-client,$AKKA_APPS"

View File

@ -0,0 +1,3 @@
. ./opts-global.sh
OPTS="$OPTS -t deb -d monit,netcat-openbsd,bbb-web,bbb-client,bbb-apps,bbb-apps-sip,bbb-apps-video,bbb-apps-screenshare,bbb-playback-presentation,bbb-fsesl-akka,bbb-apps-akka,openssl"

View File

@ -0,0 +1,47 @@
#!/bin/bash -e
#
# Restart nginx to take advantage of the updates to /etc/bigbluebutton/nginx
#
DEPLOY_DIR=/var/lib/$TOMCAT_SERVICE/webapps
rm -rf /tmp/demo
unzip /var/tmp/demo.war -d /tmp/demo > /dev/null
if [ -f $DEPLOY_DIR/demo/bbb_api_conf.jsp ]; then
cp ${DEPLOY_DIR}/demo/bbb_api_conf.jsp /tmp/demo
else
if [ -f $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties ]; then
if grep -q securitySalt $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties; then
SALT=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | tr -d '\r' | sed -n '/securitySalt/{s/.*=//;p}')
HOST=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | sed -n '/^bigbluebutton.web.serverURL/{s/.*\///;p}')
echo -n "<%" > /tmp/demo/bbb_api_conf.jsp
echo "!
// This is the security salt that must match the value set in the BigBlueButton server
String salt = \"$SALT\";
// This is the URL for the BigBlueButton server
String BigBlueButtonURL = \"http://$HOST/bigbluebutton/\";
%>
" >> /tmp/demo/bbb_api_conf.jsp
fi
else
echo "#"
echo "# Warning: Unable to set shared secret (salt) and URL for API demos."
echo "#"
fi
fi
cd /tmp/demo
zip -r demo * > /dev/null
mv -f demo.zip $DEPLOY_DIR/demo.war
touch $DEPLOY_DIR/demo.war
mkdir -p /var/www/bigbluebutton/client/images
cp /tmp/demo/images/headset* /var/www/bigbluebutton/client/images
cp /tmp/demo/demo11.html /var/www/bigbluebutton/client
reloadService nginx

View File

@ -0,0 +1,8 @@
#!/bin/bash -e
if [ "$1" = "remove" ]; then
rm -f /var/lib/$TOMCAT_SERVICE/webapps/demo.war
rm -f /var/www/bigbluebutton/client/demo11.html
rm -f /var/www/bigbluebutton/client/images/headset*
fi

View File

@ -0,0 +1,45 @@
#!/bin/bash -ex
TARGET=`basename $(pwd)`
PACKAGE=$(echo $TARGET | cut -d'_' -f1)
VERSION=$(echo $TARGET | cut -d'_' -f2)
DISTRO=$(echo $TARGET | cut -d'_' -f3)
#
# Clean up directories
rm -rf staging
#
# Create directory for fpm to process
DIRS=""
for dir in $DIRS; do
mkdir -p staging$dir
DIRECTORIES="$DIRECTORIES --directories $dir"
done
##
gradle resolveDeps
gradle build
mkdir -p staging/var/tmp
cp build/libs/demo.war staging/var/tmp
mkdir -p staging/etc/bigbluebutton/nginx
cp demo.nginx staging/etc/bigbluebutton/nginx
##
. ./opts-$DISTRO.sh
fpm -s dir -C ./staging -n $PACKAGE \
--version $VERSION --epoch $EPOCH \
--after-install after-install.sh \
--after-remove after-remove.sh \
--depends unzip \
--description "BigBlueButton API demos" \
$DIRECTORIES \
$OPTS

View File

@ -0,0 +1,3 @@
. ./opts-global.sh
OPTS="$OPTS -t deb -d tomcat8"

View File

@ -0,0 +1,3 @@
. ./opts-global.sh
OPTS="$OPTS -t deb"

View File

@ -0,0 +1,14 @@
#!/bin/bash -e
chown -R etherpad:etherpad /usr/share/etherpad-lite
chown root:root /usr/lib/systemd/system/etherpad.service
SOURCE=/tmp/settings.json
TARGET=/usr/share/etherpad-lite/settings.json
if [ ! -f /.dockerenv ]; then
systemctl enable etherpad.service
systemctl daemon-reload
startService etherpad.service || echo "bbb-etherpad service could not be registered or started"
fi

View File

@ -0,0 +1,15 @@
#!/bin/bash -e
case "$1" in
remove|failed-upgrade|abort-upgrade|abort-install|disappear)
;;
purge)
deleteUser etherpad
deleteGroup etherpad
;;
upgrade)
;;
*)
echo "postinst called with unknown argument \`\$1'" >&2
;;
esac

View File

@ -0,0 +1,25 @@
#!/bin/bash -e
addGroup etherpad ""
addUser etherpad "" etherpad /usr/share/etherpad-lite "etherpad user-daemon" "/bin/false"
if [ ! -f /usr/share/etherpad-lite/APIKEY.txt ]; then
mkdir -p /usr/share/etherpad-lite
openssl rand -base64 64 | head -n 1 | sed 's/=//g' | sed 's/+//g' | sed 's/\///g' | tr -d '\n' > /usr/share/etherpad-lite/APIKEY.txt
chown etherpad:etherpad /usr/share/etherpad-lite/
chown etherpad:etherpad /usr/share/etherpad-lite/APIKEY.txt
chmod 644 /usr/share/etherpad-lite/APIKEY.txt
fi
if [ -d /usr/share/etherpad-lite/node_modules ]; then
rm -r /usr/share/etherpad-lite/node_modules
fi
# Clean out old pads before upgrade
redis-cli keys pad:* | xargs -r redis-cli del
redis-cli keys sessionstorage:* | xargs -r redis-cli del
redis-cli keys globalAuthor:* | xargs -r redis-cli del
redis-cli keys token2author:* | xargs -r redis-cli del
redis-cli keys pad2readonly:* | xargs -r redis-cli del
redis-cli keys readonly2pad:* | xargs -r redis-cli del
redis-cli keys ueberDB:* | xargs -r redis-cli del

View File

@ -0,0 +1,4 @@
#!/bin/bash -e
stopService etherpad || echo "etherpad could not be unregistered or stopped"

View File

@ -0,0 +1,74 @@
#!/bin/bash -ex
TARGET=`basename $(pwd)`
PACKAGE=$(echo $TARGET | cut -d'_' -f1)
VERSION=$(echo $TARGET | cut -d'_' -f2)
DISTRO=$(echo $TARGET | cut -d'_' -f3)
TAG=$(echo $TARGET | cut -d'_' -f4)
#
# Clean up directories
rm -rf staging
#
# package
set +e
bin/installDeps.sh
set -e
git clone https://github.com/pedrobmarin/ep_pad_ttl.git
npm pack ./ep_pad_ttl
npm install ./ep_pad_ttl-*.tgz
git clone https://github.com/alangecker/bbb-etherpad-plugin.git
npm pack ./bbb-etherpad-plugin
npm install ./ep_bigbluebutton_patches-*.tgz
git clone https://github.com/mconf/ep_redis_publisher.git
npm pack ./ep_redis_publisher
npm install ./ep_redis_publisher-*.tgz
npm install ep_cursortrace
npm install ep_disable_chat
# For some reason installing from github using npm 7.5.2 gives
# fatal: could not create leading directories of '/root/.npm/_cacache/tmp/git-clone-76b94572': Permission denied
#
# npm install git+https://git@github.com/alangecker/bbb-etherpad-plugin.git
# npm install git+https://git@github.com/mconf/ep_redis_publisher.git
mkdir -p staging/usr/share/etherpad-lite
cp -r CHANGELOG.md CONTRIBUTING.md LICENSE README.md bin doc src tests var node_modules staging/usr/share/etherpad-lite
cp settings.json staging/usr/share/etherpad-lite
git clone https://github.com/alangecker/bbb-etherpad-skin.git staging/usr/share/etherpad-lite/src/static/skins/bigbluebutton
mkdir -p staging/usr/lib/systemd/system
cp etherpad.service staging/usr/lib/systemd/system
mkdir -p staging/etc/bigbluebutton/nginx
cp notes.nginx staging/etc/bigbluebutton/nginx
rm -rf staging/usr/share/etherpad-lite/src/static/skins/bigbluebutton/.git
##
. ./opts-$DISTRO.sh
#
# Build RPM package
fpm -s dir -C ./staging -n $PACKAGE \
--version $VERSION --epoch $EPOCH \
--before-install before-install.sh \
--after-install after-install.sh \
--before-remove before-remove.sh \
--after-remove after-remove.sh \
--description "The EtherPad Lite components for BigBlueButton" \
$DIRECTORIES \
$OPTS

View File

@ -0,0 +1,18 @@
[Unit]
Description=Etherpad Server
Wants=redis-server.service
After=syslog.target network.target
[Service]
Type=simple
User=etherpad
Group=etherpad
WorkingDirectory=/usr/share/etherpad-lite
Environment=NODE_ENV=production
ExecStart=/usr/bin/node node_modules/ep_etherpad-lite/node/server.js
Restart=always
# use mysql plus a complete settings.json to avoid Service hold-off time over, scheduling restart.
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,61 @@
# https://github.com/ether/etherpad-lite/wiki/How-to-put-Etherpad-Lite-behind-a-reverse-Proxy
location /pad/p/ {
rewrite /pad/p/(.*) /p/$1 break;
rewrite ^/pad/p$ /pad/p/ permanent;
proxy_pass http://127.0.0.1:9001/p;
proxy_pass_header Server;
proxy_redirect /p /pad/p;
proxy_set_header Host $host;
proxy_buffering off;
proxy_set_header X-Real-IP $remote_addr; # http://wiki.nginx.org/HttpProxyModule
proxy_set_header X-Forwarded-For $remote_addr; # EP logs to show the actual remote IP
proxy_set_header X-Forwarded-Proto $scheme; # for EP to set secure cookie flag when https is used
proxy_http_version 1.1;
auth_request /bigbluebutton/connection/validatePad;
auth_request_set $auth_status $upstream_status;
}
location /pad {
rewrite /pad/(.*) /$1 break;
rewrite ^/pad$ /pad/ permanent;
proxy_pass http://127.0.0.1:9001/;
proxy_pass_header Server;
proxy_redirect / /pad/;
proxy_set_header Host $host;
proxy_buffering off;
}
location /pad/socket.io/socket.io.js {
rewrite /pad/socket.io/socket.io.js /socket.io/socket.io.js break;
proxy_pass http://127.0.0.1:9001/;
proxy_set_header Host $host;
proxy_buffering off;
}
location /pad/socket.io {
rewrite /pad/socket.io/(.*) /socket.io/$1 break;
proxy_pass http://127.0.0.1:9001/;
proxy_redirect / /pad/;
proxy_set_header Host $host;
proxy_buffering off;
proxy_set_header X-Real-IP $remote_addr; # http://wiki.nginx.org/HttpProxyModule
proxy_set_header X-Forwarded-For $remote_addr; # EP logs to show the actual remote IP
proxy_set_header X-Forwarded-Proto $scheme; # for EP to set secure cookie flag when https is used
proxy_set_header Host $host; # pass the host header
proxy_http_version 1.1; # recommended with keepalive connections
# WebSocket proxying - from http://nginx.org/en/docs/http/websocket.html
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
auth_request /bigbluebutton/connection/checkAuthorization;
auth_request_set $auth_status $upstream_status;
}
location /static {
rewrite /static/(.*) /static/$1 break;
proxy_pass http://127.0.0.1:9001/;
proxy_set_header Host $host;
proxy_buffering off;
}

View File

@ -0,0 +1,47 @@
# https://github.com/ether/etherpad-lite/wiki/How-to-put-Etherpad-Lite-behind-a-reverse-Proxy
location ~ "^\/pad\/p\/(\w+)$" {
rewrite /pad/(.*) /$1 break;
rewrite ^/pad$ /pad/ permanent;
proxy_pass http://127.0.0.1:9001;
proxy_pass_header Server;
proxy_redirect / /pad;
proxy_set_header Host $host;
proxy_buffering off;
auth_request /bigbluebutton/connection/checkAuthorization;
auth_request_set $auth_status $upstream_status;
}
location /pad {
rewrite /pad/(.*) /$1 break;
rewrite ^/pad$ /pad/ permanent;
proxy_pass http://127.0.0.1:9001/;
proxy_pass_header Server;
proxy_redirect / /pad/;
proxy_set_header Host $host;
proxy_buffering off;
}
location /pad/socket.io {
rewrite /pad/socket.io/(.*) /socket.io/$1 break;
proxy_pass http://127.0.0.1:9001/;
proxy_redirect / /pad/;
proxy_set_header Host $host;
proxy_buffering off;
proxy_set_header X-Real-IP $remote_addr; # http://wiki.nginx.org/HttpProxyModule
proxy_set_header X-Forwarded-For $remote_addr; # EP logs to show the actual remote IP
proxy_set_header X-Forwarded-Proto $scheme; # for EP to set secure cookie flag when https is used
proxy_set_header Host $host; # pass the host header
proxy_http_version 1.1; # recommended with keepalive connections
# WebSocket proxying - from http://nginx.org/en/docs/http/websocket.html
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location /static {
rewrite /static/(.*) /static/$1 break;
proxy_pass http://127.0.0.1:9001/;
proxy_set_header Host $host;
proxy_buffering off;
}

View File

@ -0,0 +1,5 @@
. ./opts-global.sh
OPTS="$OPTS -d yq,tidy -t deb --deb-user etherpad --deb-group etherpad --deb-use-file-permissions"
# OPTS="$OPTS -d yq,redis-server,libreoffice,tidy -t deb --deb-user etherpad --deb-group etherpad --deb-use-file-permissions"

View File

@ -0,0 +1,436 @@
<%
var settings = require("ep_etherpad-lite/node/utils/Settings")
, hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks')
, langs = require("ep_etherpad-lite/node/hooks/i18n").availableLangs
;
%>
<!doctype html>
<% e.begin_block("htmlHead"); %>
<html>
<% e.end_block(); %>
<title><%=settings.title%></title>
<script>
/*
|@licstart The following is the entire license notice for the
JavaScript code in this page.|
Copyright 2011 Peter Martischka, Primary Technology.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
|@licend The above is the entire license notice
for the JavaScript code in this page.|
*/
</script>
<meta charset="utf-8">
<meta name="robots" content="noindex, nofollow">
<meta name="referrer" content="no-referrer">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
<link rel="shortcut icon" href="<%=settings.faviconPad%>">
<% e.begin_block("styles"); %>
<link href="../static/css/pad.css" rel="stylesheet">
<% e.begin_block("customStyles"); %>
<link href="../static/custom/pad.css" rel="stylesheet">
<% e.end_block(); %>
<style title="dynamicsyntax"></style>
<% e.end_block(); %>
<link rel="localizations" type="application/l10n+json" href="../locales.json" />
<script type="text/javascript" src="../static/js/html10n.js"></script>
<script type="text/javascript" src="../static/js/l10n.js"></script>
<!-- head and body had been removed intentionally -->
<% e.begin_block("body"); %>
<div id="editbar" class="toolbar" title="Toolbar (Alt F9)">
<div id="overlay">
<div id="overlay-inner"></div>
</div>
<ul class="menu_left" role="toolbar">
<% e.begin_block("editbarMenuLeft"); %>
<%- toolbar.menu(settings.toolbar.left, isReadOnly) %>
<% e.end_block(); %>
</ul>
<ul class="menu_right" role="toolbar">
<% e.begin_block("editbarMenuRight"); %>
<%- toolbar.menu(settings.toolbar.right, isReadOnly) %>
<% e.end_block(); %>
</ul>
</div>
<% e.begin_block("afterEditbar"); %><% e.end_block(); %>
<div id="users">
<% e.begin_block("userlist"); %>
<div id="connectionstatus"></div>
<div id="myuser">
<div id="mycolorpicker">
<div id="colorpicker"></div>
<button id="mycolorpickersave" data-l10n-id="pad.colorpicker.save"></button>
<button id="mycolorpickercancel" data-l10n-id="pad.colorpicker.cancel"></button>
<span id="mycolorpickerpreview" class="myswatchboxhoverable"></span>
</div>
<div id="myswatchbox"><div id="myswatch"></div></div>
<div id="myusernameform"><input type="text" id="myusernameedit" disabled="disabled" data-l10n-id="pad.userlist.entername"></div>
<div id="mystatusform"><input type="text" id="mystatusedit" disabled="disabled"></div>
</div>
<div id="otherusers" aria-role="document">
<div id="guestprompts"></div>
<table id="otheruserstable" cellspacing="0" cellpadding="0" border="0">
<tr><td></td></tr>
</table>
<div id="nootherusers"></div>
</div>
<div id="userlistbuttonarea"></div>
<% e.end_block(); %>
</div>
<div id="editorcontainerbox">
<div id="editorcontainer" class="editorcontainer"></div>
<div id="editorloadingbox">
<div id="passwordRequired">
<p data-l10n-id="pad.passwordRequired">You need a password to access this pad</p>
<form class='passForm' method='POST'>
<input id='passwordinput' type='password' name='password'><input type='submit' value='Submit'>
</form>
</div>
<div id="permissionDenied">
<p data-l10n-id="pad.permissionDenied">You do not have permission to access this pad</p>
</div>
<div id="wrongPassword">
<p data-l10n-id="pad.wrongPassword">Your password was wrong</p>
</div>
<div id="noCookie">
<p data-l10n-id="pad.noCookie">Cookie could not be found. Please allow cookies in your browser!</p>
</div>
<% e.begin_block("loading"); %>
<div class="spinner">
<div class="bounce1"></div>
<div class="bounce2"></div>
<div class="bounce3"></div>
</div>
<% e.end_block(); %>
<noscript><strong>Sorry, you have to enable Javascript in order to use this.</strong></noscript>
</div>
</div>
<div id="settings" class="popup">
<h1 data-l10n-id="pad.settings.padSettings"></h1>
<div class="column">
<% e.begin_block("mySettings"); %>
<h2 data-l10n-id="pad.settings.myView"></h2>
<p>
<input type="checkbox" id="options-stickychat" onClick="chat.stickToScreen();">
<label for="options-stickychat" data-l10n-id="pad.settings.stickychat"></label>
</p>
<p>
<input type="checkbox" id="options-chatandusers" onClick="chat.chatAndUsers();">
<label for="options-chatandusers" data-l10n-id="pad.settings.chatandusers"></label>
</p>
<p>
<input type="checkbox" id="options-colorscheck">
<label for="options-colorscheck" data-l10n-id="pad.settings.colorcheck"></label>
</p>
<p>
<input type="checkbox" id="options-linenoscheck" checked>
<label for="options-linenoscheck" data-l10n-id="pad.settings.linenocheck"></label>
</p>
<p>
<input type="checkbox" id="options-rtlcheck">
<label for="options-rtlcheck" data-l10n-id="pad.settings.rtlcheck"></label>
</p>
<% e.end_block(); %>
<table>
<% e.begin_block("mySettings.dropdowns"); %>
<tr>
<td>
<label for="viewfontmenu" data-l10n-id="pad.settings.fontType">Font type:</label>
</td>
<td>
<select id="viewfontmenu">
<option value="normal" data-l10n-id="pad.settings.fontType.normal"></option>
<option value="monospace" data-l10n-id="pad.settings.fontType.monospaced"></option>
<option value="montserrat" data-l10n-id="pad.settings.fontType.montserrat"></option>
<option value="opendyslexic" data-l10n-id="pad.settings.fontType.opendyslexic"></option>
<option value="comicsans" data-l10n-id="pad.settings.fontType.comicsans"></option>
<option value="georgia" data-l10n-id="pad.settings.fontType.georgia"></option>
<option value="impact" data-l10n-id="pad.settings.fontType.impact"></option>
<option value="lucida" data-l10n-id="pad.settings.fontType.lucida"></option>
<option value="lucidasans" data-l10n-id="pad.settings.fontType.lucidasans"></option>
<option value="palatino" data-l10n-id="pad.settings.fontType.palatino"></option>
<option value="robotomono" data-l10n-id="pad.settings.fontType.robotomono"></option>
<option value="tahoma" data-l10n-id="pad.settings.fontType.tahoma"></option>
<option value="timesnewroman" data-l10n-id="pad.settings.fontType.timesnewroman"></option>
<option value="trebuchet" data-l10n-id="pad.settings.fontType.trebuchet"></option>
<option value="verdana" data-l10n-id="pad.settings.fontType.verdana"></option>
<option value="symbol" data-l10n-id="pad.settings.fontType.symbol"></option>
<option value="webdings" data-l10n-id="pad.settings.fontType.webdings"></option>
<option value="wingdings" data-l10n-id="pad.settings.fontType.wingdings"></option>
<option value="sansserif" data-l10n-id="pad.settings.fontType.sansserif"></option>
<option value="serif" data-l10n-id="pad.settings.fontType.serif"></option>
</select>
</td>
</tr>
<tr>
<td>
<label for="languagemenu" data-l10n-id="pad.settings.language">Language:</label>
</td>
<td>
<select id="languagemenu">
<% for (lang in langs) { %>
<option value="<%=lang%>"><%=langs[lang].nativeName%></option>
<% } %>
</select>
</td>
</tr>
<% e.end_block(); %>
</table>
</div>
<div class="column">
<% e.begin_block("globalSettings"); %>
<h2 data-l10n-id="pad.settings.globalView"></h2>
<% e.end_block(); %>
</div>
</div>
<div id="import_export" class="popup">
<h1 data-l10n-id="pad.importExport.import_export"></h1>
<div class="column acl-write">
<!--
<% e.begin_block("importColumn"); %>
<h2 data-l10n-id="pad.importExport.import"></h2>
<div class="importmessage" id="importmessageabiword" data-l10n-id="pad.importExport.abiword.innerHTML"></div>
<form id="importform" method="post" action="" target="importiframe" enctype="multipart/form-data">
<div class="importformdiv" id="importformfilediv">
<input type="file" name="file" size="10" id="importfileinput">
<div class="importmessage" id="importmessagefail"></div>
</div>
<div id="import"></div>
<div class="importmessage" id="importmessagesuccess" data-l10n-id="pad.importExport.importSuccessful"></div>
<div class="importformdiv" id="importformsubmitdiv">
<span class="nowrap">
<input type="submit" name="submit" value="Import Now" disabled="disabled" id="importsubmitinput">
<div alt="" id="importstatusball" class="loadingAnimation" align="top"></div>
</span>
</div>
</form>
<% e.end_block(); %>
-->
<% e.begin_block("exportColumn"); %>
<h2 data-l10n-id="pad.importExport.export"></h2>
<!--
<a id="exportetherpada" target="_blank" class="exportlink"><div class="exporttype" id="exportetherpad" data-l10n-id="pad.importExport.exportetherpad"></div></a>
-->
<a id="exporthtmla" target="_blank" class="exportlink"><div class="exporttype" id="exporthtml" data-l10n-id="pad.importExport.exporthtml"></div></a>
<a id="exportplaina" target="_blank" class="exportlink"><div class="exporttype" id="exportplain" data-l10n-id="pad.importExport.exportplain"></div></a>
<a id="exportworda" target="_blank" class="exportlink"><div class="exporttype" id="exportword" data-l10n-id="pad.importExport.exportword"></div></a>
<a id="exportpdfa" target="_blank" class="exportlink"><div class="exporttype" id="exportpdf" data-l10n-id="pad.importExport.exportpdf"></div></a>
<a id="exportopena" target="_blank" class="exportlink"><div class="exporttype" id="exportopen" data-l10n-id="pad.importExport.exportopen"></div></a>
<% e.end_block(); %>
</div>
</div>
<div id="connectivity" class="popup">
<% e.begin_block("modals"); %>
<div class="connected visible">
<h2 data-l10n-id="pad.modals.connected"></h2>
</div>
<div class="reconnecting">
<h1 data-l10n-id="pad.modals.reconnecting"></h1>
<p class='loadingAnimation'></p>
</div>
<div class="userdup">
<h1 data-l10n-id="pad.modals.userdup"></h1>
<h2 data-l10n-id="pad.modals.userdup.explanation"></h2>
<p id="defaulttext" data-l10n-id="pad.modals.userdup.advice"></p>
<button id="forcereconnect" data-l10n-id="pad.modals.forcereconnect"></button>
</div>
<div class="unauth">
<h1 data-l10n-id="pad.modals.unauth"></h1>
<p id="defaulttext" data-l10n-id="pad.modals.unauth.explanation"></p>
<button id="forcereconnect" data-l10n-id="pad.modals.forcereconnect"></button>
</div>
<div class="looping">
<h1 data-l10n-id="pad.modals.disconnected"></h1>
<h2 data-l10n-id="pad.modals.looping.explanation"></h2>
<p data-l10n-id="pad.modals.looping.cause"></p>
</div>
<div class="initsocketfail">
<h1 data-l10n-id="pad.modals.initsocketfail"></h1>
<h2 data-l10n-id="pad.modals.initsocketfail.explanation"></h2>
<p data-l10n-id="pad.modals.initsocketfail.cause"></p>
</div>
<div class="slowcommit with_reconnect_timer">
<h1 data-l10n-id="pad.modals.disconnected"></h1>
<h2 data-l10n-id="pad.modals.slowcommit.explanation"></h2>
<p id="defaulttext" data-l10n-id="pad.modals.slowcommit.cause"></p>
<button id="forcereconnect" data-l10n-id="pad.modals.forcereconnect"></button>
</div>
<div class="badChangeset with_reconnect_timer">
<h1 data-l10n-id="pad.modals.disconnected"></h1>
<h2 data-l10n-id="pad.modals.badChangeset.explanation"></h2>
<p id="defaulttext" data-l10n-id="pad.modals.badChangeset.cause"></p>
<button id="forcereconnect" data-l10n-id="pad.modals.forcereconnect"></button>
</div>
<div class="corruptPad">
<h1 data-l10n-id="pad.modals.disconnected"></h1>
<h2 data-l10n-id="pad.modals.corruptPad.explanation"></h2>
<p data-l10n-id="pad.modals.corruptPad.cause"></p>
</div>
<div class="deleted">
<h1 data-l10n-id="pad.modals.deleted"></h1>
<p data-l10n-id="pad.modals.deleted.explanation"></p>
</div>
<div class="disconnected with_reconnect_timer">
<% e.begin_block("disconnected"); %>
<h1 data-l10n-id="pad.modals.disconnected"></h1>
<h2 data-l10n-id="pad.modals.disconnected.explanation"></h2>
<p id="defaulttext" data-l10n-id="pad.modals.disconnected.cause"></p>
<button id="forcereconnect" data-l10n-id="pad.modals.forcereconnect"></button>
<% e.end_block(); %>
</div>
<form id="reconnectform" method="post" action="/ep/pad/reconnect" accept-charset="UTF-8" style="display: none;">
<input type="hidden" class="padId" name="padId">
<input type="hidden" class="diagnosticInfo" name="diagnosticInfo">
<input type="hidden" class="missedChanges" name="missedChanges">
</form>
<% e.end_block(); %>
</div>
<div id="embed" class="popup">
<% e.begin_block("embedPopup"); %>
<div id="embedreadonly" class="right acl-write">
<input type="checkbox" id="readonlyinput">
<label for="readonlyinput" data-l10n-id="pad.share.readonly"></label>
</div>
<h1 data-l10n-id="pad.share"></h1>
<div id="linkcode">
<h2 data-l10n-id="pad.share.link"></h2>
<input id="linkinput" type="text" value="" onclick="this.select()">
</div>
<br>
<div id="embedcode">
<h2 data-l10n-id="pad.share.emebdcode"></h2>
<input id="embedinput" type="text" value="" onclick="this.select()">
</div>
<% e.end_block(); %>
</div>
<div id="chaticon" onclick="chat.show();return false;" title="Chat (Alt C)">
<span id="chatlabel" data-l10n-id="pad.chat"></span>
<span class="buttonicon buttonicon-chat"></span>
<span id="chatcounter">0</span>
</div>
<div id="chatbox">
<div id="titlebar"><span id ="titlelabel" data-l10n-id="pad.chat"></span>
<a id="titlecross" onClick="chat.hide();return false;">-&nbsp;</a>
<a id="titlesticky" onClick="chat.stickToScreen(true);$('#options-stickychat').prop('checked', true);return false;" title="Stick chat to screen">&nbsp;&nbsp;</a>
</div>
<div id="chattext" class="authorColors" aria-live="polite" aria-relevant="additions removals text" role="log" aria-atomic="false">
<div alt="loading.." id="chatloadmessagesball" class="chatloadmessages loadingAnimation" align="top"></div>
<button id="chatloadmessagesbutton" class="chatloadmessages" data-l10n-id="pad.chat.loadmessages"></button>
</div>
<div id="chatinputbox">
<form>
<input id="chatinput" type="text" maxlength="999">
</form>
</div>
</div>
<div id="focusprotector">&nbsp;</div>
<% e.end_block(); %>
<% e.begin_block("scripts"); %>
<script type="text/javascript">
// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7&dn=apache-2.0.txt
(function() {
// Display errors on page load to the user
// (Gets overridden by padutils.setupGlobalExceptionHandler)
var originalHandler = window.onerror;
window.onerror = function(msg, url, line) {
var box = document.getElementById('editorloadingbox');
box.innerHTML = '<p><b>An error occurred while loading the pad</b></p>'
+ '<p><b>'+msg+'</b> '
+ '<small>in '+ url +' (line '+ line +')</small></p>';
// call original error handler
if(typeof(originalHandler) == 'function') originalHandler.call(null, arguments);
};
})();
// @license-end
</script>
<script type="text/javascript" src="../static/js/require-kernel.js"></script>
<script type="text/javascript" src="../socket.io/socket.io.js"></script>
<!-- Include base packages manually (this help with debugging) -->
<script type="text/javascript" src="../javascripts/lib/ep_etherpad-lite/static/js/pad.js?callback=require.define"></script>
<script type="text/javascript" src="../javascripts/lib/ep_etherpad-lite/static/js/ace2_common.js?callback=require.define"></script>
<% e.begin_block("customScripts"); %>
<script type="text/javascript" src="../static/custom/pad.js"></script>
<% e.end_block(); %>
<!-- Bootstrap page -->
<script type="text/javascript">
// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7&dn=apache-2.0.txt
var clientVars = {};
(function () {
var pathComponents = location.pathname.split('/');
// Strip 'p' and the padname from the pathname and set as baseURL
var baseURL = pathComponents.slice(0,pathComponents.length-2).join('/') + '/';
require.setRootURI(baseURL + "javascripts/src");
require.setLibraryURI(baseURL + "javascripts/lib");
require.setGlobalKeyPath("require");
$ = jQuery = require('ep_etherpad-lite/static/js/rjquery').jQuery; // Expose jQuery #HACK
browser = require('ep_etherpad-lite/static/js/browser');
var plugins = require('ep_etherpad-lite/static/js/pluginfw/client_plugins');
var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
plugins.baseURL = baseURL;
plugins.update(function () {
hooks.plugins = plugins;
// Call documentReady hook
$(function() {
hooks.aCallAll('documentReady');
});
var pad = require('ep_etherpad-lite/static/js/pad');
pad.baseURL = baseURL;
pad.init();
});
/* TODO: These globals shouldn't exist. */
pad = require('ep_etherpad-lite/static/js/pad').pad;
chat = require('ep_etherpad-lite/static/js/chat').chat;
padeditbar = require('ep_etherpad-lite/static/js/pad_editbar').padeditbar;
padimpexp = require('ep_etherpad-lite/static/js/pad_impexp').padimpexp;
}());
// @license-end
</script>
<div style="display:none"><a href="/javascript" data-jslicense="1">JavaScript license information</a></div>
<% e.end_block(); %>
</html>

View File

@ -0,0 +1,610 @@
/*
* This file must be valid JSON. But comments are allowed
*
* Please edit settings.json, not settings.json.template
*
* Please note that starting from Etherpad 1.6.0 you can store DB credentials in
* a separate file (credentials.json).
*
*
* ENVIRONMENT VARIABLE SUBSTITUTION
* =================================
*
* All the configuration values can be read from environment variables using the
* syntax "${ENV_VAR}" or "${ENV_VAR:default_value}".
*
* This is useful, for example, when running in a Docker container.
*
* EXAMPLE:
* "port": "${PORT:9001}"
* "minify": "${MINIFY}"
* "skinName": "${SKIN_NAME:colibris}"
*
* Would read the configuration values for those items from the environment
* variables PORT, MINIFY and SKIN_NAME.
*
* If PORT and SKIN_NAME variables were not defined, the default values 9001 and
* "colibris" would be used.
* The configuration value "minify", on the other hand, does not have a
* designated default value. Thus, if the environment variable MINIFY were
* undefined, "minify" would be null.
*
* REMARKS:
* 1) please note that variable substitution always needs to be quoted.
*
* "port": 9001, <-- Literal values. When not using
* "minify": false substitution, only strings must be
* "skinName": "colibris" quoted. Booleans and numbers must not.
*
* "port": "${PORT:9001}" <-- CORRECT: if you want to use a variable
* "minify": "${MINIFY:true}" substitution, put quotes around its name,
* "skinName": "${SKIN_NAME}" even if the required value is a number or
* a boolean.
* Etherpad will take care of rewriting it
* to the proper type if necessary.
*
* "port": ${PORT:9001} <-- ERROR: this is not valid json. Quotes
* "minify": ${MINIFY} around variable names are missing.
* "skinName": ${SKIN_NAME}
*
* 2) Beware of undefined variables and default values: nulls and empty strings
* are different!
*
* This is particularly important for user's passwords (see the relevant
* section):
*
* "password": "${PASSW}" // if PASSW is not defined would result in password === null
* "password": "${PASSW:}" // if PASSW is not defined would result in password === ''
*
* If you want to use an empty value (null) as default value for a variable,
* simply do not set it, without putting any colons: "${ABIWORD}".
*
* 3) if you want to use newlines in the default value of a string parameter,
* use "\n" as usual.
*
* "defaultPadText" : "${DEFAULT_PAD_TEXT}Line 1\nLine 2"
*/
{
/*
* Name your instance!
*/
"title": "Etherpad",
/*
* favicon default name
* alternatively, set up a fully specified Url to your own favicon
*/
"favicon": "favicon.ico",
/*
* Skin name.
*
* Its value has to be an existing directory under src/static/skins.
* You can write your own, or use one of the included ones:
*
* - "no-skin": an empty skin (default). This yields the unmodified,
* traditional Etherpad theme.
* - "colibris": the new experimental skin (since Etherpad 1.8), candidate to
* become the default in Etherpad 2.0
*/
"skinName": "bigbluebutton",
/*
* Skin Variants
*
* Use the UI skin variants builder at /p/test#skinvariantsbuilder
*
* For the colibris skin only, you can choose how to render the three main
* containers:
* - toolbar (top menu with icons)
* - editor (containing the text of the pad)
* - background (area outside of editor, mostly visible when using page style)
*
* For each of the 3 containers you can choose 4 color combinations:
* super-light, light, dark, super-dark.
*
* For example, to make the toolbar dark, you will include "dark-toolbar" into
* skinVariants.
*
* You can provide multiple skin variants separated by spaces. Default
* skinVariant is "super-light-toolbar super-light-editor light-background".
*
* For the editor container, you can also make it full width by adding
* "full-width-editor" variant (by default editor is rendered as a page, with
* a max-width of 900px).
*/
"skinVariants": "super-light-toolbar super-light-editor light-background",
/*
* IP and port which Etherpad should bind at.
*
* Binding to a Unix socket is also supported: just use an empty string for
* the ip, and put the full path to the socket in the port parameter.
*
* EXAMPLE USING UNIX SOCKET:
* "ip": "", // <-- has to be an empty string
* "port" : "/somepath/etherpad.socket", // <-- path to a Unix socket
*/
"ip": "127.0.0.1",
"port": 9001,
/*
* Option to hide/show the settings.json in admin page.
*
* Default option is set to true
*/
"showSettingsInAdminPage": true,
/*
* Node native SSL support
*
* This is disabled by default.
* Make sure to have the minimum and correct file access permissions set so
* that the Etherpad server can access them
*/
/*
"ssl" : {
"key" : "/path-to-your/epl-server.key",
"cert" : "/path-to-your/epl-server.crt",
"ca": ["/path-to-your/epl-intermediate-cert1.crt", "/path-to-your/epl-intermediate-cert2.crt"]
},
*/
/*
* The type of the database.
*
* You can choose between many DB drivers, for example: dirty, postgres,
* sqlite, mysql.
*
* You shouldn't use "dirty" for for anything else than testing or
* development.
*
*
* Database specific settings are dependent on dbType, and go in dbSettings.
* Remember that since Etherpad 1.6.0 you can also store these informations in
* credentials.json.
*
* For a complete list of the supported drivers, please refer to:
* https://www.npmjs.com/package/ueberdb2
*/
"dbType": "redis",
"dbSettings": {
"host": "localhost",
"port": 6379
},
/*
* An Example of MySQL Configuration (commented out).
*
* See: https://github.com/ether/etherpad-lite/wiki/How-to-use-Etherpad-Lite-with-MySQL
*/
/*
"dbType" : "redis",
"dbSettings" : {
"host": "localhost",
"port": 6379,
"client_options": {
"password": "PASSWORD"
}
},
*/
/*
* The default text of a pad
*/
"defaultPadText" : "",
/*
* Default Pad behavior.
*
* Change them if you want to override.
*/
"padOptions": {
"noColors": true,
"showControls": true,
"showChat": false,
"showLineNumbers": false,
"useMonospaceFont": false,
"userName": false,
"userColor": false,
"rtl": false,
"alwaysShowChat": false,
"chatAndUsers": false,
"lang": "en-gb"
},
/*
* Pad Shortcut Keys
*/
"padShortcutEnabled" : {
"altF9": true, /* focus on the File Menu and/or editbar */
"altC": false, /* focus on the Chat window */
"cmdShift2": true, /* shows a gritter popup showing a line author */
"delete": true,
"return": true,
"esc": true, /* in mozilla versions 14-19 avoid reconnecting pad */
"cmdS": true, /* save a revision */
"tab": true, /* indent */
"cmdZ": true, /* undo/redo */
"cmdY": true, /* redo */
"cmdI": true, /* italic */
"cmdB": true, /* bold */
"cmdU": true, /* underline */
"cmd5": true, /* strike through */
"cmdShiftL": true, /* unordered list */
"cmdShiftN": true, /* ordered list */
"cmdShift1": true, /* ordered list */
"cmdShiftC": true, /* clear authorship */
"cmdH": true, /* backspace */
"ctrlHome": true, /* scroll to top of pad */
"pageUp": true,
"pageDown": true
},
/*
* Should we suppress errors from being visible in the default Pad Text?
*/
"suppressErrorsInPadText": true,
/*
* If this option is enabled, a user must have a session to access pads.
* This effectively allows only group pads to be accessed.
*/
"requireSession": false,
/*
* Users may edit pads but not create new ones.
*
* Pad creation is only via the API.
* This applies both to group pads and regular pads.
*/
"editOnly": false,
/*
* If true, all css & js will be minified before sending to the client.
*
* This will improve the loading performance massively, but makes it difficult
* to debug the javascript/css
*/
"minify": true,
/*
* How long may clients use served javascript code (in seconds)?
*
* Not setting this may cause problems during deployment.
* Set to 0 to disable caching.
*/
"maxAge": 21600, // 60 * 60 * 6 = 6 hours
/*
* Absolute path to the Abiword executable.
*
* Abiword is needed to get advanced import/export features of pads. Setting
* it to null disables Abiword and will only allow plain text and HTML
* import/exports.
*/
"abiword": null,
/*
* This is the absolute path to the soffice executable.
*
* LibreOffice can be used in lieu of Abiword to export pads.
* Setting it to null disables LibreOffice exporting.
*/
"soffice": null,
/*
* Path to the Tidy executable.
*
* Tidy is used to improve the quality of exported pads.
* Setting it to null disables Tidy.
*/
"tidyHtml": null,
/*
* Allow import of file types other than the supported ones:
* txt, doc, docx, rtf, odt, html & htm
*/
"allowUnknownFileEnds": false,
/*
* This setting is used if you require authentication of all users.
*
* Note: "/admin" always requires authentication.
*/
"requireAuthentication": false,
/*
* Require authorization by a module, or a user with is_admin set, see below.
*/
"requireAuthorization": false,
/*
* When you use NGINX or another proxy/load-balancer set this to true.
*
* This is especially necessary when the reverse proxy performs SSL
* termination, otherwise the cookies will not have the "secure" flag.
*
* The other effect will be that the logs will contain the real client's IP,
* instead of the reverse proxy's IP.
*/
"trustProxy": true,
/*
* Settings controlling the session cookie issued by Etherpad.
*/
"cookie": {
/*
* Value of the SameSite cookie property. "Lax" is recommended unless
* Etherpad will be embedded in an iframe from another site, in which case
* this must be set to "None". Note: "None" will not work (the browser will
* not send the cookie to Etherpad) unless https is used to access Etherpad
* (either directly or via a reverse proxy with "trustProxy" set to true).
*
* "Strict" is not recommended because it has few security benefits but
* significant usability drawbacks vs. "Lax". See
* https://stackoverflow.com/q/41841880 for discussion.
*/
"sameSite": "None"
},
/*
* Privacy: disable IP logging
*/
"disableIPlogging": false,
/*
* Time (in seconds) to automatically reconnect pad when a "Force reconnect"
* message is shown to user.
*
* Set to 0 to disable automatic reconnection.
*/
"automaticReconnectionTimeout": 0,
/*
* By default, when caret is moved out of viewport, it scrolls the minimum
* height needed to make this line visible.
*/
"scrollWhenFocusLineIsOutOfViewport": {
/*
* Percentage of viewport height to be additionally scrolled.
*
* E.g.: use "percentage.editionAboveViewport": 0.5, to place caret line in
* the middle of viewport, when user edits a line above of the
* viewport
*
* Set to 0 to disable extra scrolling
*/
"percentage": {
"editionAboveViewport": 0,
"editionBelowViewport": 0
},
/*
* Time (in milliseconds) used to animate the scroll transition.
* Set to 0 to disable animation
*/
"duration": 0,
/*
* Flag to control if it should scroll when user places the caret in the
* last line of the viewport
*/
"scrollWhenCaretIsInTheLastLineOfViewport": false,
/*
* Percentage of viewport height to be additionally scrolled when user
* presses arrow up in the line of the top of the viewport.
*
* Set to 0 to let the scroll to be handled as default by Etherpad
*/
"percentageToScrollWhenUserPressesArrowUp": 0
},
/*
* User accounts. These accounts are used by:
* - default HTTP basic authentication if no plugin handles authentication
* - some but not all authentication plugins
* - some but not all authorization plugins
*
* User properties:
* - password: The user's password. Some authentication plugins will ignore
* this.
* - is_admin: true gives access to /admin. Defaults to false. If you do not
* uncomment this, /admin will not be available!
* - readOnly: If true, this user will not be able to create new pads or
* modify existing pads. Defaults to false.
* - canCreate: If this is true and readOnly is false, this user can create
* new pads. Defaults to true.
*
* Authentication and authorization plugins may define additional properties.
*
* WARNING: passwords should not be stored in plaintext in this file.
* If you want to mitigate this, please install ep_hash_auth and
* follow the section "secure your installation" in README.md
*/
/*
"users": {
"admin": {
// 1) "password" can be replaced with "hash" if you install ep_hash_auth
// 2) please note that if password is null, the user will not be created
"password": "changeme1",
"is_admin": true
},
"user": {
// 1) "password" can be replaced with "hash" if you install ep_hash_auth
// 2) please note that if password is null, the user will not be created
"password": "changeme1",
"is_admin": false
}
},
*/
/*
* Restrict socket.io transport methods
*/
"socketTransportProtocols" : ["xhr-polling", "jsonp-polling", "htmlfile"],
/*
* Allow Load Testing tools to hit the Etherpad Instance.
*
* WARNING: this will disable security on the instance.
*/
"loadTest": false,
/*
* Disable indentation on new line when previous line ends with some special
* chars (':', '[', '(', '{')
*/
/*
"indentationOnNewLine": false,
*/
"ep_pad_ttl": {
"ttl": 86400, // 24 hours
"timeout": 30,
"interval": 21600 // 6 hours
},
/*
* Redis publisher plugin configuration.
* npm i git+https://git@github.com/mconf/ep_redis_publisher.git
*/
"ep_redis_publisher": {
"host": "localhost",
"port": 6379
},
/*
* From Etherpad 1.8.3 onwards, import and export of pads is always rate
* limited.
*
* The default is to allow at most 10 requests per IP in a 90 seconds window.
* After that the import/export request is rejected.
*
* See https://github.com/nfriedly/express-rate-limit for more options
*/
"importExportRateLimiting": {
// duration of the rate limit window (milliseconds)
"windowMs": 90000,
// maximum number of requests per IP to allow during the rate limit window
"max": 10
},
/*
* From Etherpad 1.8.3 onwards, the maximum allowed size for a single imported
* file is always bounded.
*
* File size is specified in bytes. Default is 50 MB.
*/
"importMaxFileSize": 52428800, // 50 * 1024 * 1024
/*
* From Etherpad 1.9.0 onwards, when Etherpad is in production mode commits from individual users are rate limited
*
* The default is to allow at most 10 changes per IP in a 1 second window.
* After that the change is rejected.
*
* See https://github.com/animir/node-rate-limiter-flexible/wiki/Overall-example#websocket-single-connection-prevent-flooding for more options
*/
"commitRateLimiting": {
// duration of the rate limit window (seconds)
"duration": 1,
// maximum number of chanes per IP to allow during the rate limit window
"points": 100
},
/*
* Toolbar buttons configuration.
*
* Uncomment to customize.
*/
"toolbar": {
"left": [
["bold", "italic", "underline", "strikethrough"],
["orderedlist", "unorderedlist", "undo", "redo"]
],
"right": [["importexport"]]
},
/*
* Expose Etherpad version in the web interface and in the Server http header.
*
* Do not enable on production machines.
*/
"exposeVersion": false,
/*
* The log level we are using.
*
* Valid values: DEBUG, INFO, WARN, ERROR
*/
"loglevel": "INFO",
/*
* Logging configuration. See log4js documentation for further information:
* https://github.com/nomiddlename/log4js-node
*
* You can add as many appenders as you want here.
*/
"logconfig" :
{ "appenders": [
{ "type": "console"
//, "category": "access"// only logs pad access
}
/*
, { "type": "file"
, "filename": "your-log-file-here.log"
, "maxLogSize": 1024
, "backups": 3 // how many log files there're gonna be at max
//, "category": "test" // only log a specific category
}
*/
/*
, { "type": "logLevelFilter"
, "level": "warn" // filters out all log messages that have a lower level than "error"
, "appender":
{ Use whatever appender you want here }
}
*/
/*
, { "type": "logLevelFilter"
, "level": "error" // filters out all log messages that have a lower level than "error"
, "appender":
{ "type": "smtp"
, "subject": "An error occurred in your EPL instance!"
, "recipients": "bar@blurdybloop.com, baz@blurdybloop.com"
, "sendInterval": 300 // 60 * 5 = 5 minutes -- will buffer log messages; set to 0 to send a mail for every message
, "transport": "SMTP", "SMTP": { // see https://github.com/andris9/Nodemailer#possible-transport-methods
"host": "smtp.example.com", "port": 465,
"secureConnection": true,
"auth": {
"user": "foo@example.com",
"pass": "bar_foo"
}
}
}
}
*/
]
}, // logconfig
/* Override any strings found in locale directories */
"customLocaleStrings": {}
}

View File

@ -0,0 +1,605 @@
/*
* This file must be valid JSON. But comments are allowed
*
* Please edit settings.json, not settings.json.template
*
* Please note that starting from Etherpad 1.6.0 you can store DB credentials in
* a separate file (credentials.json).
*
*
* ENVIRONMENT VARIABLE SUBSTITUTION
* =================================
*
* All the configuration values can be read from environment variables using the
* syntax "${ENV_VAR}" or "${ENV_VAR:default_value}".
*
* This is useful, for example, when running in a Docker container.
*
* EXAMPLE:
* "port": "${PORT:9001}"
* "minify": "${MINIFY}"
* "skinName": "${SKIN_NAME:colibris}"
*
* Would read the configuration values for those items from the environment
* variables PORT, MINIFY and SKIN_NAME.
*
* If PORT and SKIN_NAME variables were not defined, the default values 9001 and
* "colibris" would be used.
* The configuration value "minify", on the other hand, does not have a
* designated default value. Thus, if the environment variable MINIFY were
* undefined, "minify" would be null.
*
* REMARKS:
* 1) please note that variable substitution always needs to be quoted.
*
* "port": 9001, <-- Literal values. When not using
* "minify": false substitution, only strings must be
* "skinName": "colibris" quoted. Booleans and numbers must not.
*
* "port": "${PORT:9001}" <-- CORRECT: if you want to use a variable
* "minify": "${MINIFY:true}" substitution, put quotes around its name,
* "skinName": "${SKIN_NAME}" even if the required value is a number or
* a boolean.
* Etherpad will take care of rewriting it
* to the proper type if necessary.
*
* "port": ${PORT:9001} <-- ERROR: this is not valid json. Quotes
* "minify": ${MINIFY} around variable names are missing.
* "skinName": ${SKIN_NAME}
*
* 2) Beware of undefined variables and default values: nulls and empty strings
* are different!
*
* This is particularly important for user's passwords (see the relevant
* section):
*
* "password": "${PASSW}" // if PASSW is not defined would result in password === null
* "password": "${PASSW:}" // if PASSW is not defined would result in password === ''
*
* If you want to use an empty value (null) as default value for a variable,
* simply do not set it, without putting any colons: "${ABIWORD}".
*
* 3) if you want to use newlines in the default value of a string parameter,
* use "\n" as usual.
*
* "defaultPadText" : "${DEFAULT_PAD_TEXT}Line 1\nLine 2"
*/
{
/*
* Name your instance!
*/
"title": "Etherpad",
/*
* favicon default name
* alternatively, set up a fully specified Url to your own favicon
*/
"favicon": "favicon.ico",
/*
* Skin name.
*
* Its value has to be an existing directory under src/static/skins.
* You can write your own, or use one of the included ones:
*
* - "no-skin": an empty skin (default). This yields the unmodified,
* traditional Etherpad theme.
* - "colibris": the new experimental skin (since Etherpad 1.8), candidate to
* become the default in Etherpad 2.0
*/
"skinName": "colibris",
/*
* Skin Variants
*
* Use the UI skin variants builder at /p/test#skinvariantsbuilder
*
* For the colibris skin only, you can choose how to render the three main
* containers:
* - toolbar (top menu with icons)
* - editor (containing the text of the pad)
* - background (area outside of editor, mostly visible when using page style)
*
* For each of the 3 containers you can choose 4 color combinations:
* super-light, light, dark, super-dark.
*
* For example, to make the toolbar dark, you will include "dark-toolbar" into
* skinVariants.
*
* You can provide multiple skin variants separated by spaces. Default
* skinVariant is "super-light-toolbar super-light-editor light-background".
*
* For the editor container, you can also make it full width by adding
* "full-width-editor" variant (by default editor is rendered as a page, with
* a max-width of 900px).
*/
"skinVariants": "super-light-toolbar super-light-editor light-background",
/*
* IP and port which Etherpad should bind at.
*
* Binding to a Unix socket is also supported: just use an empty string for
* the ip, and put the full path to the socket in the port parameter.
*
* EXAMPLE USING UNIX SOCKET:
* "ip": "", // <-- has to be an empty string
* "port" : "/somepath/etherpad.socket", // <-- path to a Unix socket
*/
"ip": "0.0.0.0",
"port": 9001,
/*
* Option to hide/show the settings.json in admin page.
*
* Default option is set to true
*/
"showSettingsInAdminPage": true,
/*
* Node native SSL support
*
* This is disabled by default.
* Make sure to have the minimum and correct file access permissions set so
* that the Etherpad server can access them
*/
/*
"ssl" : {
"key" : "/path-to-your/epl-server.key",
"cert" : "/path-to-your/epl-server.crt",
"ca": ["/path-to-your/epl-intermediate-cert1.crt", "/path-to-your/epl-intermediate-cert2.crt"]
},
*/
/*
* The type of the database.
*
* You can choose between many DB drivers, for example: dirty, postgres,
* sqlite, mysql.
*
* You shouldn't use "dirty" for for anything else than testing or
* development.
*
*
* Database specific settings are dependent on dbType, and go in dbSettings.
* Remember that since Etherpad 1.6.0 you can also store these informations in
* credentials.json.
*
* For a complete list of the supported drivers, please refer to:
* https://www.npmjs.com/package/ueberdb2
*/
"dbType": "dirty",
"dbSettings": {
"filename": "var/dirty.db"
},
/*
* An Example of MySQL Configuration (commented out).
*
* See: https://github.com/ether/etherpad-lite/wiki/How-to-use-Etherpad-Lite-with-MySQL
*/
/*
"dbType" : "mysql",
"dbSettings" : {
"user": "etherpaduser",
"host": "localhost",
"port": 3306,
"password": "PASSWORD",
"database": "etherpad_lite_db",
"charset": "utf8mb4"
},
*/
/*
* The default text of a pad
*/
"defaultPadText" : "Welcome to Etherpad!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nGet involved with Etherpad at https:\/\/etherpad.org\n",
/*
* Default Pad behavior.
*
* Change them if you want to override.
*/
"padOptions": {
"noColors": false,
"showControls": true,
"showChat": true,
"showLineNumbers": true,
"useMonospaceFont": false,
"userName": false,
"userColor": false,
"rtl": false,
"alwaysShowChat": false,
"chatAndUsers": false,
"lang": "en-gb"
},
/*
* Pad Shortcut Keys
*/
"padShortcutEnabled" : {
"altF9": true, /* focus on the File Menu and/or editbar */
"altC": true, /* focus on the Chat window */
"cmdShift2": true, /* shows a gritter popup showing a line author */
"delete": true,
"return": true,
"esc": true, /* in mozilla versions 14-19 avoid reconnecting pad */
"cmdS": true, /* save a revision */
"tab": true, /* indent */
"cmdZ": true, /* undo/redo */
"cmdY": true, /* redo */
"cmdI": true, /* italic */
"cmdB": true, /* bold */
"cmdU": true, /* underline */
"cmd5": true, /* strike through */
"cmdShiftL": true, /* unordered list */
"cmdShiftN": true, /* ordered list */
"cmdShift1": true, /* ordered list */
"cmdShiftC": true, /* clear authorship */
"cmdH": true, /* backspace */
"ctrlHome": true, /* scroll to top of pad */
"pageUp": true,
"pageDown": true
},
/*
* Should we suppress errors from being visible in the default Pad Text?
*/
"suppressErrorsInPadText": false,
/*
* If this option is enabled, a user must have a session to access pads.
* This effectively allows only group pads to be accessed.
*/
"requireSession": false,
/*
* Users may edit pads but not create new ones.
*
* Pad creation is only via the API.
* This applies both to group pads and regular pads.
*/
"editOnly": false,
/*
* If true, all css & js will be minified before sending to the client.
*
* This will improve the loading performance massively, but makes it difficult
* to debug the javascript/css
*/
"minify": true,
/*
* How long may clients use served javascript code (in seconds)?
*
* Not setting this may cause problems during deployment.
* Set to 0 to disable caching.
*/
"maxAge": 21600, // 60 * 60 * 6 = 6 hours
/*
* Absolute path to the Abiword executable.
*
* Abiword is needed to get advanced import/export features of pads. Setting
* it to null disables Abiword and will only allow plain text and HTML
* import/exports.
*/
"abiword": null,
/*
* This is the absolute path to the soffice executable.
*
* LibreOffice can be used in lieu of Abiword to export pads.
* Setting it to null disables LibreOffice exporting.
*/
"soffice": null,
/*
* Path to the Tidy executable.
*
* Tidy is used to improve the quality of exported pads.
* Setting it to null disables Tidy.
*/
"tidyHtml": null,
/*
* Allow import of file types other than the supported ones:
* txt, doc, docx, rtf, odt, html & htm
*/
"allowUnknownFileEnds": true,
/*
* This setting is used if you require authentication of all users.
*
* Note: "/admin" always requires authentication.
*/
"requireAuthentication": false,
/*
* Require authorization by a module, or a user with is_admin set, see below.
*/
"requireAuthorization": false,
/*
* When you use NGINX or another proxy/load-balancer set this to true.
*
* This is especially necessary when the reverse proxy performs SSL
* termination, otherwise the cookies will not have the "secure" flag.
*
* The other effect will be that the logs will contain the real client's IP,
* instead of the reverse proxy's IP.
*/
"trustProxy": false,
/*
* Settings controlling the session cookie issued by Etherpad.
*/
"cookie": {
/*
* Value of the SameSite cookie property. "Lax" is recommended unless
* Etherpad will be embedded in an iframe from another site, in which case
* this must be set to "None". Note: "None" will not work (the browser will
* not send the cookie to Etherpad) unless https is used to access Etherpad
* (either directly or via a reverse proxy with "trustProxy" set to true).
*
* "Strict" is not recommended because it has few security benefits but
* significant usability drawbacks vs. "Lax". See
* https://stackoverflow.com/q/41841880 for discussion.
*/
"sameSite": "Lax"
},
/*
* Privacy: disable IP logging
*/
"disableIPlogging": false,
/*
* Time (in seconds) to automatically reconnect pad when a "Force reconnect"
* message is shown to user.
*
* Set to 0 to disable automatic reconnection.
*/
"automaticReconnectionTimeout": 0,
/*
* By default, when caret is moved out of viewport, it scrolls the minimum
* height needed to make this line visible.
*/
"scrollWhenFocusLineIsOutOfViewport": {
/*
* Percentage of viewport height to be additionally scrolled.
*
* E.g.: use "percentage.editionAboveViewport": 0.5, to place caret line in
* the middle of viewport, when user edits a line above of the
* viewport
*
* Set to 0 to disable extra scrolling
*/
"percentage": {
"editionAboveViewport": 0,
"editionBelowViewport": 0
},
/*
* Time (in milliseconds) used to animate the scroll transition.
* Set to 0 to disable animation
*/
"duration": 0,
/*
* Flag to control if it should scroll when user places the caret in the
* last line of the viewport
*/
"scrollWhenCaretIsInTheLastLineOfViewport": false,
/*
* Percentage of viewport height to be additionally scrolled when user
* presses arrow up in the line of the top of the viewport.
*
* Set to 0 to let the scroll to be handled as default by Etherpad
*/
"percentageToScrollWhenUserPressesArrowUp": 0
},
/*
* User accounts. These accounts are used by:
* - default HTTP basic authentication if no plugin handles authentication
* - some but not all authentication plugins
* - some but not all authorization plugins
*
* User properties:
* - password: The user's password. Some authentication plugins will ignore
* this.
* - is_admin: true gives access to /admin. Defaults to false. If you do not
* uncomment this, /admin will not be available!
* - readOnly: If true, this user will not be able to create new pads or
* modify existing pads. Defaults to false.
* - canCreate: If this is true and readOnly is false, this user can create
* new pads. Defaults to true.
*
* Authentication and authorization plugins may define additional properties.
*
* WARNING: passwords should not be stored in plaintext in this file.
* If you want to mitigate this, please install ep_hash_auth and
* follow the section "secure your installation" in README.md
*/
/*
"users": {
"admin": {
// 1) "password" can be replaced with "hash" if you install ep_hash_auth
// 2) please note that if password is null, the user will not be created
"password": "changeme1",
"is_admin": true
},
"user": {
// 1) "password" can be replaced with "hash" if you install ep_hash_auth
// 2) please note that if password is null, the user will not be created
"password": "changeme1",
"is_admin": false
}
},
*/
/*
* Restrict socket.io transport methods
*/
"socketTransportProtocols" : ["xhr-polling", "jsonp-polling", "htmlfile"],
/*
* Allow Load Testing tools to hit the Etherpad Instance.
*
* WARNING: this will disable security on the instance.
*/
"loadTest": false,
/*
* Disable indentation on new line when previous line ends with some special
* chars (':', '[', '(', '{')
*/
/*
"indentationOnNewLine": false,
*/
/*
* From Etherpad 1.8.3 onwards, import and export of pads is always rate
* limited.
*
* The default is to allow at most 10 requests per IP in a 90 seconds window.
* After that the import/export request is rejected.
*
* See https://github.com/nfriedly/express-rate-limit for more options
*/
"importExportRateLimiting": {
// duration of the rate limit window (milliseconds)
"windowMs": 90000,
// maximum number of requests per IP to allow during the rate limit window
"max": 10
},
/*
* From Etherpad 1.8.3 onwards, the maximum allowed size for a single imported
* file is always bounded.
*
* File size is specified in bytes. Default is 50 MB.
*/
"importMaxFileSize": 52428800, // 50 * 1024 * 1024
/*
* From Etherpad 1.9.0 onwards, when Etherpad is in production mode commits from individual users are rate limited
*
* The default is to allow at most 10 changes per IP in a 1 second window.
* After that the change is rejected.
*
* See https://github.com/animir/node-rate-limiter-flexible/wiki/Overall-example#websocket-single-connection-prevent-flooding for more options
*/
"commitRateLimiting": {
// duration of the rate limit window (seconds)
"duration": 1,
// maximum number of chanes per IP to allow during the rate limit window
"points": 10
},
/*
* Toolbar buttons configuration.
*
* Uncomment to customize.
*/
/*
"toolbar": {
"left": [
["bold", "italic", "underline", "strikethrough"],
["orderedlist", "unorderedlist", "indent", "outdent"],
["undo", "redo"],
["clearauthorship"]
],
"right": [
["importexport", "timeslider", "savedrevision"],
["settings", "embed"],
["showusers"]
],
"timeslider": [
["timeslider_export", "timeslider_returnToPad"]
]
},
*/
/*
* Expose Etherpad version in the web interface and in the Server http header.
*
* Do not enable on production machines.
*/
"exposeVersion": false,
/*
* The log level we are using.
*
* Valid values: DEBUG, INFO, WARN, ERROR
*/
"loglevel": "INFO",
/*
* Logging configuration. See log4js documentation for further information:
* https://github.com/nomiddlename/log4js-node
*
* You can add as many appenders as you want here.
*/
"logconfig" :
{ "appenders": [
{ "type": "console"
//, "category": "access"// only logs pad access
}
/*
, { "type": "file"
, "filename": "your-log-file-here.log"
, "maxLogSize": 1024
, "backups": 3 // how many log files there're gonna be at max
//, "category": "test" // only log a specific category
}
*/
/*
, { "type": "logLevelFilter"
, "level": "warn" // filters out all log messages that have a lower level than "error"
, "appender":
{ Use whatever appender you want here }
}
*/
/*
, { "type": "logLevelFilter"
, "level": "error" // filters out all log messages that have a lower level than "error"
, "appender":
{ "type": "smtp"
, "subject": "An error occurred in your EPL instance!"
, "recipients": "bar@blurdybloop.com, baz@blurdybloop.com"
, "sendInterval": 300 // 60 * 5 = 5 minutes -- will buffer log messages; set to 0 to send a mail for every message
, "transport": "SMTP", "SMTP": { // see https://github.com/andris9/Nodemailer#possible-transport-methods
"host": "smtp.example.com", "port": 465,
"secureConnection": true,
"auth": {
"user": "foo@example.com",
"pass": "bar_foo"
}
}
}
}
*/
]
}, // logconfig
/* Override any strings found in locale directories */
"customLocaleStrings": {}
}

View File

@ -0,0 +1,74 @@
#!/bin/bash -e
case "$1" in
configure|upgrade|1|2)
if [ -f /tmp/vars.xml ]; then
cp /tmp/vars.xml /opt/freeswitch/etc/freeswitch/vars.xml
# Needed for bbb-webrtc-sfu
sed -i 's/,VP8//g' /opt/freeswitch/etc/freeswitch/vars.xml
mv -f /tmp/vars.xml /tmp/_vars.xml
else
sed -i "s@<X-PRE-PROCESS cmd=\"set\" data=\"local_ip_v4=.*\"/>@<X-PRE-PROCESS cmd=\"set\" data=\"local_ip_v4=$IP\"/>@g" /opt/freeswitch/etc/freeswitch/vars.xml
fi
sed -n 's/,VP8//g' /opt/freeswitch/etc/freeswitch/vars.xml
SOURCE=/tmp/external.xml
TARGET=/opt/freeswitch/etc/freeswitch/sip_profiles/external.xml
# Determine if there are ws-binding and wss-binding values to propagate
if [ -f $SOURCE ]; then
if xmlstarlet sel -t -v '//param[@name="ws-binding"]/@value' $SOURCE > /dev/null 2>&1; then
WS_BINDING=$(xmlstarlet sel -t -v '//param[@name="ws-binding"]/@value' $SOURCE)
xmlstarlet edit --inplace --update '//param[@name="ws-binding"]/@value' --value "$WS_BINDING" $TARGET
fi
if xmlstarlet sel -t -v '//param[@name="wss-binding"]/@value' $SOURCE > /dev/null 2>&1; then
WSS_BINDING=$(xmlstarlet sel -t -v '//param[@name="wss-binding"]/@value' $SOURCE)
xmlstarlet edit --inplace --update '//param[@name="wss-binding"]/@value' --value "$WSS_BINDING" $TARGET
fi
mv -f $SOURCE "${SOURCE}_"
fi
if [ -f /tmp/verto.conf.xml ]; then
cp /tmp/verto.conf.xml /opt/freeswitch/conf/autoload_configs/verto.conf.xml
mv -f /tmp/verto.conf.xml /tmp/_verto.conf.xml
fi
if [ -f /tmp/event_socket.conf.xml ]; then
ESL_PASSWORD=$(xmlstarlet sel -t -m 'configuration/settings/param[@name="password"]' -v @value /tmp/event_socket.conf.xml)
if [ ! -z "$ESL_PASSWORD" ]; then
xmlstarlet edit --inplace --update '//param[@name="password"]/@value' --value "$ESL_PASSWORD" /opt/freeswitch/etc/freeswitch/autoload_configs/event_socket.conf.xml
fi
mv -f /tmp/event_socket.conf.xml /tmp/event_socket.conf.xml_
fi
chown freeswitch:daemon /var/freeswitch/meetings
chown -R freeswitch:daemon /opt/freeswitch
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "## postinst called with unknown argument \`$1'" >&2
;;
esac
ldconfig
if [ -f /.dockerenv ]; then
# To make it easier to run within Docker, disable IPV6
sed -i 's/::/0.0.0.0/g' /opt/freeswitch/etc/freeswitch/autoload_configs/event_socket.conf.xml
if [ -f /opt/freeswitch/conf/sip_profiles/external-ipv6.xml ]; then
mv /opt/freeswitch/conf/sip_profiles/external-ipv6.xml /opt/freeswitch/conf/sip_profiles/external-ipv6.xml_
fi
if [ -f /opt/freeswitch/conf/sip_profiles/internal-ipv6.xml ]; then
mv /opt/freeswitch/conf/sip_profiles/internal-ipv6.xml /opt/freeswitch/conf/sip_profiles/internal-ipv6.xml_
fi
else
startService freeswitch.service || echo "freeswitch.service could not be registered or started"
fi

View File

@ -0,0 +1,15 @@
#!/bin/bash -e
# Deleting user: bigbluebutton and group: bigbluebutton
case "$1" in
remove|failed-upgrade|abort-upgrade|abort-install|disappear|0)
;;
purge)
deleteUser freeswitch
;;
upgrade)
;;
*)
echo "postrm called with unknown argument \`\$1'" >&2
;;
esac

View File

@ -0,0 +1,49 @@
#!/bin/bash -e
case "$1" in
install|upgrade|1|2)
addGroup freeswitch ""
addUser freeswitch "" freeswitch /opt/freeswitch "freeswitch" /bin/bash
rm -f /tmp/external.xml
if [ -f /opt/freeswitch/etc/freeswitch/sip_profiles/external.xml ]; then
cp /opt/freeswitch/etc/freeswitch/sip_profiles/external.xml /tmp/external.xml
fi
rm -f /tmp/vars.xml
if [ -f /opt/freeswitch/etc/freeswitch/vars.xml ]; then
cp /opt/freeswitch/etc/freeswitch/vars.xml /tmp/vars.xml
fi
rm -f /tmp/verto.conf.xml
if [ -f /opt/freeswitch/conf/autoload_configs/verto.conf.xml ]; then
cp /opt/freeswitch/conf/autoload_configs/verto.conf.xml /tmp/verto.conf.xml
fi
rm -f /tmp/event_socket.conf.xml
if [ -f /opt/freeswitch/etc/freeswitch/autoload_configs/event_socket.conf.xml ]; then
cp /opt/freeswitch/etc/freeswitch/autoload_configs/event_socket.conf.xml /tmp/event_socket.conf.xml
fi
if [ -f /.dockerenv ]; then
# To make it easier, we'll override how systemd runs freeswitch
mkdir -p /etc/systemd/system/freeswitch.service.d
cat <<HERE > /etc/systemd/system/freeswitch.service.d/override.conf
[Service]
Type=simple
Environment="DAEMON_OPTS=-nonat -nf"
HERE
fi
;;
abort-upgrade)
;;
*)
echo "## preinst called with unknown argument \`$1'" >&2
;;
esac

View File

@ -0,0 +1,4 @@
#!/bin/bash -e
stopService freeswitch || echo "FreeSWITCH could not be unregistered or stopped"

View File

@ -0,0 +1,260 @@
#!/bin/bash -ex
TARGET=`basename $(pwd)`
PACKAGE=$(echo $TARGET | cut -d'_' -f1)
VERSION=$(echo $TARGET | cut -d'_' -f2)
DISTRO=$(echo $TARGET | cut -d'_' -f3)
#
# Clear staging directory for build
rm -rf staging
#
# Create directory for fpm to process
#DIRS="/opt/freeswitch \
# /var/freeswitch/meetings"
#for dir in $DIRS; do
# mkdir -p staging$dir
# DIRECTORIES="$DIRECTORIES --directories $dir"
#done
##
. ./opts-$DISTRO.sh
#cp modules.conf freeswitch
#cd freeswitch
#
# Need to figure out how to build with mod_av
if [ $DISTRO == "centos7" ] || [ $DISTRO == "amzn2" ]; then
sed -i 's/applications\/mod_av/#applications\/mod_av/g' modules.conf
else
apt-get update
apt-get install -y software-properties-common
add-apt-repository -y ppa:bigbluebutton/support
fi
if [ "$DISTRO" == "xenial" ]; then
apt-get update
apt-get install -y libopusfile-dev opus-tools libopusenc-dev
fi
if [ "$DISTRO" == "bionic" ]; then
add-apt-repository ppa:bigbluebutton/support -y
# cat > /etc/apt/sources.list.d/kepstin-ubuntu-opus-bionic.list << HERE
#deb http://ppa.launchpad.net/kepstin/opus/ubuntu xenial main
# deb-src http://ppa.launchpad.net/kepstin/opus/ubuntu xenial main
#HERE
apt-get update
apt-get install -y libopusfile-dev opus-tools libopusenc-dev
fi
mkdir -p staging
pushd .
if [ ! -d sofia-sip ]; then
git clone https://github.com/freeswitch/sofia-sip.git
fi
cd sofia-sip/
git pull
./bootstrap.sh
./configure
#make DESTDIR=/var/tmp/bbb-freeswitch-core_2.3.0_bionic_develop/staging install
make -j $(nproc)
make install
cd ..
if [ ! -d spandsp ]; then
git clone https://github.com/freeswitch/spandsp.git
fi
cd spandsp/
git pull
./bootstrap.sh
./configure
make -j $(nproc)
make install
if [ $DISTRO == "centos7" ] || [ $DISTRO == "amzn2" ]; then
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
yum install -y opusfile-devel
git clone https://github.com/xiph/libopusenc.git
cd libopusenc/
./autogen.sh
./configure
make -j $(nproc)
make install
fi
popd
#cat > /etc/ld.so.conf.d/myapp.conf << HERE
#/var/tmp/bbb-freeswitch-core_2.3.0_bionic_develop/staging/usr/local/lib
#HERE
ldconfig
#pushd /tmp
#git clone https://git.xiph.org/libopusenc.git
#cd libopusenc
#./autogen.sh
#./configure
#make install
#popd
# Checkout the latest release in 1.6.x branch
git fetch
git fetch --tags
git reset --hard
#git checkout v1.8.5
#git checkout master
git checkout tags/v1.10.6
#git pull
#git checkout e1f63ce5b18a83793c0af4bfe85e9de05a00e18a
#git checkout 4bef44b7b0aca79c27b6b208b5e0011e048a30c1
#
# good
#git checkout 6d8e8f35b4b2e2de6aad27b4d5f3b1bc2a4b9e11
#git checkout 89379c3
#git checkout v1.10.5
#git checkout master
#git apply ../crash-fix2.patch
# Fix websocket lock
#cp ../websocket-fix/tport.c libs/sofia-sip/libsofia-sip-ua/tport/tport.c
#cp ../websocket-fix/tport_type_ws.c libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c
#cp ../opus-fix/mod_opusfile.c src/mod/formats/mod_opusfile/mod_opusfile.c
#cp ../opus-fix/Makefile.am src/mod/formats/mod_opusfile/Makefile.am
#if [ "$DISTRO" == "bionic" ];then
# sed -i 's/formats\/mod_opusfile//g' modules.conf
# sed -i 's/<load module="mod_opusfile"\/>//g' ../conf/modules.conf.xml
#fi
patch -p0 < floor.patch
./bootstrap.sh
./configure --disable-core-odbc-support --disable-core-pgsql-support \
--without-python --without-erlang --without-java \
--prefix=/opt/freeswitch CFLAGS="-Wno-error -Og -ggdb" CXXFLAGS="-Wno-error -Og -ggdb"
# --prefix=/opt/freeswitch CFLAGS="-Wno-error -O3 -ggdb" CXXFLAGS="-Wno-error -Og -ggdb"
make -j $(nproc)
make install
DESTDIR=staging
CONFDIR=$DESTDIR/opt/freeswitch/etc/freeswitch
mkdir -p $DESTDIR/opt
cp -r /opt/freeswitch staging/opt
mkdir -p $DESTDIR/lib/systemd/system
cp freeswitch.service.${DISTRO} $DESTDIR/lib/systemd/system/freeswitch.service
mkdir -p $DESTDIR/lib/systemd/system
cp freeswitch.conf $DESTDIR/lib/systemd/system
mkdir -p $DESTDIR/var/freeswitch/meetings
echo "This directory holds *.wav files for FreeSWITCH" > $DESTDIR/var/freeswitch/meetings/readme.txt
#mkdir -p $DESTDIR/etc/default
#cp freeswitch.default $DESTDIR/etc/default/freeswitch
if [ 1 == 0 ]; then
cp conf/acl.conf.xml $CONFDIR/autoload_configs
cp conf/opus.conf.xml $CONFDIR/autoload_configs
# Leave these here in case administrator wants to try other settings for Opus
#
# find $(DESTDIR)/opt/freeswitch/sounds -type d -name 32000 -exec rm -rf '{}' \;
# find $(DESTDIR)/opt/freeswitch/sounds -type d -name 48000 -exec rm -rf '{}' \;
cp conf/vars.xml $CONFDIR
cp conf/external.xml $CONFDIR/sip_profiles
cp conf/external-ipv6.xml $CONFDIR/sip_profiles
cp conf/internal-ipv6.xml $CONFDIR/sip_profiles
cp conf/internal.xml $CONFDIR/sip_profiles
cp conf/public.xml $CONFDIR/dialplan
rm -rf $CONFDIR/directory/default/*
cp conf/bbbuser.xml $CONFDIR/directory/default
cp conf/modules.conf.xml $CONFDIR/autoload_configs
cp conf/conference.conf.xml $CONFDIR/autoload_configs
cp conf/switch.conf.xml $CONFDIR/autoload_configs
# cp conf/verto.conf.xml $CONFDIR/autoload_configs
rm -rf $CONFDIR/dialplan/default/*
rm -rf $CONFDIR/dialplan/public/*
cp conf/bbb_conference.xml $CONFDIR/dialplan/default
cp conf/bbb_echo_test.xml $CONFDIR/dialplan/default
cp conf/bbb_echo_to_conference.xml $CONFDIR/dialplan/default
cp conf/default.xml $CONFDIR/dialplan
cp conf/bbb_sip.xml $CONFDIR/dialplan/public
cp conf/bbb_webrtc.xml $CONFDIR/dialplan/public
mkdir -p $CONFDIR/tls
else
rm -rf $CONFDIR/*
cp -r config/freeswitch/conf/* $CONFDIR
fi
pushd $DESTDIR/opt/freeswitch
ln -s ./etc/freeswitch conf
ln -s ./var/log/freeswitch log
popd
# Install libraries for sofia-sip and spandsp
mkdir -p $DESTDIR/etc/ld.so.conf.d
cat > $DESTDIR/etc/ld.so.conf.d/freeswitch.conf << HERE
/opt/freeswitch/lib
HERE
files="sip-date sip-dig sip-options stunc addrinfo localinfo"
for file in $files; do
cp /usr/local/bin/$file $DESTDIR/opt/freeswitch/bin
done
cp -P /usr/local/lib/lib* $DESTDIR/opt/freeswitch/lib
if [ -f /etc/system-release ]; then
cp /usr/lib64/libopusfile.so.0.4.4 $DESTDIR/opt/freeswitch/lib
cp /usr/lib64/libopusurl.so.0.4.4 $DESTDIR/opt/freeswitch/lib
pushd $DESTDIR/opt/freeswitch/lib
ln -s libopusfile.so.0.4.4 libopusfile.so
ln -s libopusurl.so.0.4.4 libopusurl.so
popd
fi
mkdir -p $DESTDIR/usr/local/bin
cp fs_clibbb $DESTDIR/usr/local/bin
chmod +x $DESTDIR/usr/local/bin/fs_clibbb
rm -rf $DESTDIR/usr/lib/tmpfiles.d
# Needed for Edge
# find $DESTDIR/etc/freeswitch -name "*.xml" -exec sed -i 's/ <param name="nonce-ttl" value="60"\/>/ <!--<param name="nonce-ttl" value="60"\/>-->/g' '{}' \;
fpm -s dir -C $DESTDIR -n $PACKAGE \
--version $VERSION --epoch 2 \
--before-install before-install.sh \
--after-install after-install.sh \
--before-remove before-remove.sh \
--after-remove after-remove.sh \
--description "BigBlueButton build of FreeSWITCH" \
$DIRECTORIES \
$OPTS

View File

@ -0,0 +1,37 @@
<configuration name="acl.conf" description="Network Lists">
<network-lists>
<!--
These ACL's are automatically created on startup.
rfc1918.auto - RFC1918 Space
nat.auto - RFC1918 Excluding your local lan.
localnet.auto - ACL for your local lan.
loopback.auto - ACL for your local lan.
-->
<list name="lan" default="allow">
<node type="allow" cidr="127.0.0.1/32"/>
<node type="allow" cidr="10.130.218.147/32"/>
</list>
<list name="deny_private_v6" default="allow">
<node type="deny" cidr="0.0.0.0/0"/>
<node type="deny" cidr="fe80::/10"/>
<node type="deny" cidr="fc00::/7"/>
</list>
<!--
This will traverse the directory adding all users
with the cidr= tag to this ACL, when this ACL matches
the users variables and params apply as if they
digest authenticated.
-->
<list name="domains" default="allow">
<!-- domain= is special it scans the domain from the directory to build the ACL -->
<node type="allow" domain="$${domain}"/>
<!-- use cidr= if you wish to allow ip ranges to this domains acl. -->
<!-- <node type="allow" cidr="192.168.0.0/24"/> -->
</list>
</network-lists>
</configuration>

View File

@ -0,0 +1,19 @@
<include>
<extension name="bbb_conferences_ws">
<condition field="${bbb_authorized}" expression="true" break="on-false"/>
<condition field="${sip_via_protocol}" expression="^wss?$"/>
<condition field="destination_number" expression="^(\d{5,11})$">
<action application="jitterbuffer" data="60:120"/>
<action application="answer"/>
<action application="conference" data="$1@cdquality"/>
</condition>
</extension>
<extension name="bbb_conferences">
<condition field="${bbb_authorized}" expression="true" break="on-false"/>
<condition field="destination_number" expression="^(\d{5,11})$">
<action application="jitterbuffer" data="60:120"/>
<action application="answer"/>
<action application="conference" data="$1@cdquality"/>
</condition>
</extension>
</include>

View File

@ -0,0 +1,13 @@
<include>
<extension name="bbb_echo_test_direct">
<condition field="${bbb_authorized}" expression="true" break="on-false"/>
<condition field="destination_number" expression="^echo(\d{5,11})$">
<action application="set" data="vbridge=$1"/>
<action application="answer"/>
<action application="set" data="bbb_from_echo=true"/>
<action application="bind_digit_action" data="direct_from_echo,1,exec:execute_extension,ECHO_TO_CONFERENCE XML default"/>
<action application="sleep" data="500"/>
<action application="echo"/>
</condition>
</extension>
</include>

View File

@ -0,0 +1,10 @@
<include>
<extension name="ECHO_TO_CONFERENCE">
<condition field="${bbb_from_echo}" expression="true" break="on-false"/>
<condition field="destination_number" expression="^(ECHO_TO_CONFERENCE)$">
<action application="jitterbuffer" data="60:120"/>
<action application="answer"/>
<action application="conference" data="${vbridge}@cdquality"/>
</condition>
</extension>
</include>

View File

@ -0,0 +1,9 @@
<include>
<extension name="bbb_sp_call" continue="true">
<condition field="network_addr" expression="${domain}" break="on-false">
<action application="set" data="bbb_authorized=true"/>
<action application="transfer" data="${destination_number} XML default"/>
</condition>
</extension>
</include>

View File

@ -0,0 +1,12 @@
<include>
<extension name="bbb_webrtc_call" continue="true">
<condition field="${sip_via_protocol}" expression="^wss?$" break="on-false">
<action application="set" data="bbb_authorized=true"/>
<action application="set" data="jb_use_timestamps=true"/>
<action application="transfer" data="${destination_number} XML default"/>
</condition>
</extension>
</include>

View File

@ -0,0 +1,29 @@
<include>
<!--
ipauth if you have an cidr= in the user attributes ie cidr="1.2.3.4/32"
see <node type="allow" domain="$${domain}"/> in default acl.conf.xml
-->
<user id="bbbuser">
<params>
<!-- omit password for authless registration -->
<param name="password" value="secret"/>
<!-- What this user is allowed to acces -->
<!--<param name="http-allowed-api" value="jsapi,voicemail,status"/> -->
</params>
<variables>
<!--all variables here will be set on all inbound calls that originate from this user -->
<variable name="user_context" value="default"/>
<variable name="effective_caller_id_name" value="BigBlueButton"/>
<variable name="effective_caller_id_number" value="1000"/>
<!-- Don't write a CDR if this is false valid values are: true, false, a_leg and b_leg -->
<variable name="process_cdr" value="true"/>
<!-- sip_secure_media will offer mandatory SRTP on invite AES_CM_128_HMAC_SHA1_32, AES_CM_128_HMAC_SHA1_80 or true-->
<variable name="rtp_secure_media" value="false"/>
</variables>
<vcard>
<!-- insert optional compliant vcard xml here-->
</vcard>
</user>
</include>

View File

@ -0,0 +1,279 @@
<!-- http://wiki.freeswitch.org/wiki/Mod_conference -->
<!-- None of these paths are real if you want any of these options you need to really set them up -->
<configuration name="conference.conf" description="Audio Conference">
<!-- Advertise certain presence on startup . -->
<advertise>
<room name="3001@$${domain}" status="FreeSWITCH"/>
</advertise>
<!-- These are the default keys that map when you do not specify a caller control group -->
<!-- Note: none and default are reserved names for group names. Disabled if dist-dtmf member flag is set. -->
<caller-controls>
<group name="default">
<control action="mute" digits="0"/>
<control action="deaf mute" digits="*"/>
<control action="energy up" digits="9"/>
<control action="energy equ" digits="8"/>
<control action="energy dn" digits="7"/>
<control action="vol talk up" digits="3"/>
<control action="vol talk zero" digits="2"/>
<control action="vol talk dn" digits="1"/>
<control action="vol listen up" digits="6"/>
<control action="vol listen zero" digits="5"/>
<control action="vol listen dn" digits="4"/>
<!--control action="hangup" digits="#"/ -->
</group>
</caller-controls>
<!-- Profiles are collections of settings you can reference by name. -->
<profiles>
<!--If no profile is specified it will default to "default"-->
<profile name="default">
<!-- Directory to drop CDR's
'auto' means $PREFIX/logs/conference_cdr/<confernece_uuid>.cdr.xml
a non-absolute path means $PREFIX/logs/<value>/<confernece_uuid>.cdr.xml
absolute path means <value>/<confernece_uuid>.cdr.xml
-->
<!-- <param name="cdr-log-dir" value="auto"/> -->
<!-- Domain (for presence) -->
<param name="domain" value="$${domain}"/>
<!-- Sample Rate-->
<param name="rate" value="8000"/>
<!-- Number of milliseconds per frame -->
<param name="interval" value="20"/>
<!-- Energy level required for audio to be sent to the other users -->
<param name="energy-level" value="100"/>
<!--Can be | delim of waste|mute|deaf|dist-dtmf waste will always transmit data to each channel
even during silence. dist-dtmf propagates dtmfs to all other members, but channel controls
via dtmf will be disabled. -->
<!-- <param name="member-flags" value="waste"/> -->
<!-- Name of the caller control group to use for this profile -->
<!-- <param name="caller-controls" value="some name"/> -->
<!-- Name of the caller control group to use for the moderator in this profile -->
<!-- <param name="moderator-controls" value="some name"/> -->
<!-- TTS Engine to use -->
<!-- <param name="tts-engine" value="cepstral"/> -->
<!-- TTS Voice to use -->
<!-- <param name="tts-voice" value="david"/> -->
<!-- If TTS is enabled all audio-file params beginning with -->
<!-- 'say:' will be considered text to say with TTS -->
<!-- Override the default path here, after which you use relative paths in the other sound params -->
<!-- Note: The default path is the conference's first caller's sound_prefix -->
<!-- <param name="sound-prefix" value="$${sounds_dir}/en/us/callie"/> -->
<!-- File to play to acknowledge succees -->
<!-- <param name="ack-sound" value="beep.wav"/> -->
<!-- File to play to acknowledge failure -->
<!-- <param name="nack-sound" value="beeperr.wav"/> -->
<!-- File to play to acknowledge muted -->
<param name="muted-sound" value="conference/conf-muted.wav"/>
<!-- File to play to acknowledge unmuted -->
<param name="unmuted-sound" value="conference/conf-unmuted.wav"/>
<!-- File to play if you are alone in the conference -->
<param name="alone-sound" value="conference/conf-alone.wav"/>
<!-- File to play endlessly (nobody will ever be able to talk) -->
<!-- <param name="perpetual-sound" value="perpetual.wav"/> -->
<!-- File to play when you're alone (music on hold)-->
<param name="moh-sound" value="$${hold_music}"/>
<!-- File to play when you join the conference -->
<param name="enter-sound" value="tone_stream://%(200,0,500,600,700)"/>
<!-- File to play when you leave the conference -->
<param name="exit-sound" value="tone_stream://%(500,0,300,200,100,50,25)"/>
<!-- File to play when you are ejected from the conference -->
<param name="kicked-sound" value="conference/conf-kicked.wav"/>
<!-- File to play when the conference is locked -->
<param name="locked-sound" value="conference/conf-locked.wav"/>
<!-- File to play when the conference is locked during the call-->
<param name="is-locked-sound" value="conference/conf-is-locked.wav"/>
<!-- File to play when the conference is unlocked during the call-->
<param name="is-unlocked-sound" value="conference/conf-is-unlocked.wav"/>
<!-- File to play to prompt for a pin -->
<param name="pin-sound" value="conference/conf-pin.wav"/>
<!-- File to play to when the pin is invalid -->
<param name="bad-pin-sound" value="conference/conf-bad-pin.wav"/>
<!-- Conference pin -->
<!-- <param name="pin" value="12345"/> -->
<!-- <param name="moderator-pin" value="54321"/> -->
<!-- Max number of times the user can be prompted for PIN -->
<!-- <param name="pin-retries" value="3"/> -->
<!-- Default Caller ID Name for outbound calls -->
<param name="caller-id-name" value="$${outbound_caller_name}"/>
<!-- Default Caller ID Number for outbound calls -->
<param name="caller-id-number" value="$${outbound_caller_id}"/>
<!-- Suppress start and stop talking events -->
<!-- <param name="suppress-events" value="start-talking,stop-talking"/> -->
<!-- enable comfort noise generation -->
<param name="comfort-noise" value="true"/>
<!-- Uncomment auto-record to toggle recording every conference call. -->
<!-- Another valid value is shout://user:pass@server.com/live.mp3 -->
<!--
<param name="auto-record" value="$${recordings_dir}/${conference_name}_${strftime(%Y-%m-%d-%H-%M-%S)}.wav"/>
-->
<!-- IVR digit machine timeouts -->
<!-- How much to wait between DTMF digits to match caller-controls -->
<!-- <param name="ivr-dtmf-timeout" value="500"/> -->
<!-- How much to wait for the first DTMF, 0 forever -->
<!-- <param name="ivr-input-timeout" value="0" /> -->
<!-- Delay before a conference is asked to be terminated -->
<!-- <param name="endconf-grace-time" value="120" /> -->
<!-- Can be | delim of wait-mod|audio-always|video-bridge|video-floor-only
wait_mod will wait until the moderator in,
audio-always will always mix audio from all members regardless they are talking or not -->
<!-- <param name="conference-flags" value="audio-always"/> -->
<!-- Allow live array sync for Verto -->
<!-- <param name="conference-flags" value="livearray-sync"/> -->
</profile>
<profile name="wideband">
<param name="domain" value="$${domain}"/>
<param name="rate" value="16000"/>
<param name="interval" value="20"/>
<param name="energy-level" value="100"/>
<!-- <param name="sound-prefix" value="$${sounds_dir}/en/us/callie"/> -->
<param name="muted-sound" value="conference/conf-muted.wav"/>
<param name="unmuted-sound" value="conference/conf-unmuted.wav"/>
<param name="alone-sound" value="conference/conf-alone.wav"/>
<param name="moh-sound" value="$${hold_music}"/>
<param name="enter-sound" value="tone_stream://%(200,0,500,600,700)"/>
<param name="exit-sound" value="tone_stream://%(500,0,300,200,100,50,25)"/>
<param name="kicked-sound" value="conference/conf-kicked.wav"/>
<param name="locked-sound" value="conference/conf-locked.wav"/>
<param name="is-locked-sound" value="conference/conf-is-locked.wav"/>
<param name="is-unlocked-sound" value="conference/conf-is-unlocked.wav"/>
<param name="pin-sound" value="conference/conf-pin.wav"/>
<param name="bad-pin-sound" value="conference/conf-bad-pin.wav"/>
<param name="caller-id-name" value="$${outbound_caller_name}"/>
<param name="caller-id-number" value="$${outbound_caller_id}"/>
<param name="comfort-noise" value="true"/>
<!-- <param name="tts-engine" value="flite"/> -->
<!-- <param name="tts-voice" value="kal16"/> -->
</profile>
<profile name="ultrawideband">
<param name="domain" value="$${domain}"/>
<param name="rate" value="32000"/>
<param name="interval" value="20"/>
<param name="energy-level" value="100"/>
<!-- <param name="sound-prefix" value="$${sounds_dir}/en/us/callie"/> -->
<param name="muted-sound" value="conference/conf-muted.wav"/>
<param name="unmuted-sound" value="conference/conf-unmuted.wav"/>
<param name="alone-sound" value="conference/conf-alone.wav"/>
<param name="moh-sound" value="$${hold_music}"/>
<param name="enter-sound" value="tone_stream://%(200,0,500,600,700)"/>
<param name="exit-sound" value="tone_stream://%(500,0,300,200,100,50,25)"/>
<param name="kicked-sound" value="conference/conf-kicked.wav"/>
<param name="locked-sound" value="conference/conf-locked.wav"/>
<param name="is-locked-sound" value="conference/conf-is-locked.wav"/>
<param name="is-unlocked-sound" value="conference/conf-is-unlocked.wav"/>
<param name="pin-sound" value="conference/conf-pin.wav"/>
<param name="bad-pin-sound" value="conference/conf-bad-pin.wav"/>
<param name="caller-id-name" value="$${outbound_caller_name}"/>
<param name="caller-id-number" value="$${outbound_caller_id}"/>
<param name="comfort-noise" value="true"/>
<!-- <param name="conference-flags" value="video-floor-only|rfc-4579|livearray-sync|auto-3d-position|transcode-video|minimize-video-encoding"/> -->
<!-- <param name="video-mode" value="mux"/> -->
<!-- <param name="video-layout-name" value="3x3"/> -->
<!-- <param name="video-layout-name" value="group:grid"/> -->
<!-- <param name="video-canvas-size" value="1280x720"/> -->
<!-- <param name="video-canvas-bgcolor" value="#333333"/> -->
<!-- <param name="video-layout-bgcolor" value="#000000"/> -->
<!-- <param name="video-codec-bandwidth" value="2mb"/> -->
<!-- <param name="video-fps" value="15"/> -->
<!-- <param name="video-auto-floor-msec" value="100"/> -->
<!-- <param name="tts-engine" value="flite"/> -->
<!-- <param name="tts-voice" value="kal16"/> -->
</profile>
<profile name="cdquality">
<param name="domain" value="$${domain}"/>
<param name="rate" value="48000"/>
<param name="interval" value="20"/>
<param name="energy-level" value="100"/>
<!-- <param name="sound-prefix" value="$${sounds_dir}/en/us/callie"/> -->
<param name="muted-sound" value="conference/conf-muted.wav"/>
<param name="unmuted-sound" value="conference/conf-unmuted.wav"/>
<param name="alone-sound" value="conference/conf-alone.wav"/>
<!--
<param name="moh-sound" value="$${hold_music}"/>
<param name="enter-sound" value="tone_stream://%(200,0,500,600,700)"/>
<param name="exit-sound" value="tone_stream://%(500,0,300,200,100,50,25)"/>
<param name="kicked-sound" value="conference/conf-kicked.wav"/>
-->
<param name="locked-sound" value="conference/conf-locked.wav"/>
<param name="is-locked-sound" value="conference/conf-is-locked.wav"/>
<param name="is-unlocked-sound" value="conference/conf-is-unlocked.wav"/>
<param name="pin-sound" value="conference/conf-pin.wav"/>
<param name="bad-pin-sound" value="conference/conf-bad-pin.wav"/>
<param name="caller-id-name" value="$${outbound_caller_name}"/>
<param name="caller-id-number" value="$${outbound_caller_id}"/>
<!-- param name="comfort-noise" value="true"/ -->
<param name="comfort-noise" value="1400"/>
<!-- <param name="conference-flags" value="video-floor-only|rfc-4579|livearray-sync|auto-3d-position|minimize-video-encoding"/> -->
<!-- <param name="video-mode" value="mux"/> -->
<!-- <param name="video-layout-name" value="3x3"/> -->
<!-- <param name="video-layout-name" value="group:grid"/> -->
<!-- <param name="video-canvas-size" value="1920x1080"/> -->
<!-- <param name="video-canvas-bgcolor" value="#333333"/> -->
<!-- <param name="video-layout-bgcolor" value="#000000"/> -->
<!-- <param name="video-codec-bandwidth" value="2mb"/> -->
<!-- <param name="video-fps" value="15"/> -->
</profile>
<profile name="video-mcu-stereo">
<param name="domain" value="$${domain}"/>
<param name="rate" value="48000"/>
<param name="channels" value="2"/>
<param name="interval" value="20"/>
<param name="energy-level" value="100"/>
<!-- <param name="tts-engine" value="flite"/> -->
<!-- <param name="tts-voice" value="kal16"/> -->
<param name="muted-sound" value="conference/conf-muted.wav"/>
<param name="unmuted-sound" value="conference/conf-unmuted.wav"/>
<param name="alone-sound" value="conference/conf-alone.wav"/>
<param name="moh-sound" value="local_stream://stereo"/>
<param name="enter-sound" value="tone_stream://%(200,0,500,600,700)"/>
<param name="exit-sound" value="tone_stream://%(500,0,300,200,100,50,25)"/>
<param name="kicked-sound" value="conference/conf-kicked.wav"/>
<param name="locked-sound" value="conference/conf-locked.wav"/>
<param name="is-locked-sound" value="conference/conf-is-locked.wav"/>
<param name="is-unlocked-sound" value="conference/conf-is-unlocked.wav"/>
<param name="pin-sound" value="conference/conf-pin.wav"/>
<param name="bad-pin-sound" value="conference/conf-bad-pin.wav"/>
<param name="caller-id-name" value="$${outbound_caller_name}"/>
<param name="caller-id-number" value="$${outbound_caller_id}"/>
<param name="comfort-noise" value="false"/>
<param name="conference-flags" value="video-floor-only|rfc-4579|livearray-sync|minimize-video-encoding"/>
<param name="video-mode" value="mux"/>
<param name="video-layout-name" value="3x3"/>
<param name="video-layout-name" value="group:grid"/>
<param name="video-canvas-size" value="1920x1080"/>
<param name="video-canvas-bgcolor" value="#333333"/>
<param name="video-layout-bgcolor" value="#000000"/>
<param name="video-codec-bandwidth" value="1mb"/>
<param name="video-fps" value="15"/>
</profile>
<profile name="sla">
<param name="domain" value="$${domain}"/>
<param name="rate" value="16000"/>
<param name="interval" value="20"/>
<param name="caller-controls" value="none"/>
<param name="energy-level" value="200"/>
<param name="moh-sound" value="silence"/>
<param name="comfort-noise" value="true"/>
</profile>
</profiles>
</configuration>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
NOTICE:
This context is usually accessed via authenticated callers on the sip profile on port 5060
or transfered callers from the public context which arrived via the sip profile on port 5080.
Authenticated users will use the user_context variable on the user to determine what context
they can access. You can also add a user in the directory with the cidr= attribute acl.conf.xml
will build the domains ACL using this value.
-->
<!-- http://wiki.freeswitch.org/wiki/Dialplan_XML -->
<include>
<context name="default">
<extension name="unloop">
<condition field="${unroll_loops}" expression="^true$"/>
<condition field="${sip_looped_call}" expression="^true$">
<action application="deflect" data="${destination_number}"/>
</condition>
</extension>
<!--
You can place files in the default directory to get included.
-->
<X-PRE-PROCESS cmd="include" data="default/*.xml"/>
</context>
</include>

View File

@ -0,0 +1,113 @@
<profile name="external-ipv6">
<!-- http://wiki.freeswitch.org/wiki/Sofia_Configuration_Files -->
<!-- This profile is only for outbound registrations to providers -->
<gateways>
<X-PRE-PROCESS cmd="include" data="external-ipv6/*.xml"/>
</gateways>
<aliases>
<!--
<alias name="outbound"/>
<alias name="nat"/>
-->
</aliases>
<domains>
<!--<domain name="all" alias="false" parse="true"/>-->
</domains>
<settings>
<param name="debug" value="0"/>
<!-- If you want FreeSWITCH to shutdown if this profile fails to load, uncomment the next line. -->
<!-- <param name="shutdown-on-fail" value="true"/> -->
<param name="sip-trace" value="no"/>
<param name="sip-capture" value="no"/>
<param name="rfc2833-pt" value="101"/>
<!-- RFC 5626 : Send reg-id and sip.instance -->
<!--<param name="enable-rfc-5626" value="true"/> -->
<param name="sip-port" value="$${external_sip_port}"/>
<param name="dialplan" value="XML"/>
<param name="context" value="public"/>
<param name="dtmf-duration" value="2000"/>
<param name="inbound-codec-prefs" value="$${global_codec_prefs}"/>
<param name="outbound-codec-prefs" value="$${outbound_codec_prefs}"/>
<param name="hold-music" value="$${hold_music}"/>
<param name="rtp-timer-name" value="soft"/>
<!--<param name="enable-100rel" value="true"/>-->
<!--<param name="disable-srv503" value="true"/>-->
<!-- This could be set to "passive" -->
<param name="local-network-acl" value="none"/>
<param name="manage-presence" value="false"/>
<!-- Added for Microsoft Edge support
<param name="apply-candidate-acl" value="wan_v6.auto"/>
<param name="apply-candidate-acl" value="rfc1918.auto"/>
<param name="apply-candidate-acl" value="any_v6.auto"/>
<param name="apply-candidate-acl" value="wan_v4.auto"/>
<param name="apply-candidate-acl" value="any_v4.auto"/>
-->
<param name="apply-candidate-acl" value="deny_private_v6"/>
<!-- used to share presence info across sofia profiles
manage-presence needs to be set to passive on this profile
if you want it to behave as if it were the internal profile
for presence.
-->
<!-- Name of the db to use for this profile -->
<!--<param name="dbname" value="share_presence"/>-->
<!--<param name="presence-hosts" value="$${domain}"/>-->
<!--<param name="force-register-domain" value="$${domain}"/>-->
<!--all inbound reg will stored in the db using this domain -->
<!--<param name="force-register-db-domain" value="$${domain}"/>-->
<!-- ************************************************* -->
<!--<param name="aggressive-nat-detection" value="true"/>-->
<param name="inbound-codec-negotiation" value="generous"/>
<param name="nonce-ttl" value="60"/>
<param name="auth-calls" value="false"/>
<param name="inbound-late-negotiation" value="true"/>
<param name="inbound-zrtp-passthru" value="true"/> <!-- (also enables late negotiation) -->
<!--
DO NOT USE HOSTNAMES, ONLY IP ADDRESSES IN THESE SETTINGS!
-->
<param name="rtp-ip" value="$${local_ip_v6}"/>
<param name="sip-ip" value="$${local_ip_v6}"/>
<!-- Shouldn't set these on IPv6 -->
<!--<param name="ext-rtp-ip" value="auto-nat"/>-->
<!--<param name="ext-sip-ip" value="auto-nat"/>-->
<param name="rtp-timeout-sec" value="300"/>
<param name="rtp-hold-timeout-sec" value="1800"/>
<!--<param name="enable-3pcc" value="true"/>-->
<!-- TLS: disabled by default, set to "true" to enable -->
<param name="tls" value="$${external_ssl_enable}"/>
<!-- Set to true to not bind on the normal sip-port but only on the TLS port -->
<param name="tls-only" value="false"/>
<!-- additional bind parameters for TLS -->
<param name="tls-bind-params" value="transport=tls"/>
<!-- Port to listen on for TLS requests. (5081 will be used if unspecified) -->
<param name="tls-sip-port" value="$${external_tls_port}"/>
<!-- Location of the agent.pem and cafile.pem ssl certificates (needed for TLS server) -->
<!--<param name="tls-cert-dir" value=""/>-->
<!-- Optionally set the passphrase password used by openSSL to encrypt/decrypt TLS private key files -->
<param name="tls-passphrase" value=""/>
<!-- Verify the date on TLS certificates -->
<param name="tls-verify-date" value="true"/>
<!-- TLS verify policy, when registering/inviting gateways with other servers (outbound) or handling inbound registration/invite requests how should we verify their certificate -->
<!-- set to 'in' to only verify incoming connections, 'out' to only verify outgoing connections, 'all' to verify all connections, also 'subjects_in', 'subjects_out' and 'subjects_all' for subject validation. Multiple policies can be split with a '|' pipe -->
<param name="tls-verify-policy" value="none"/>
<!-- Certificate max verify depth to use for validating peer TLS certificates when the verify policy is not none -->
<param name="tls-verify-depth" value="2"/>
<!-- If the tls-verify-policy is set to subjects_all or subjects_in this sets which subjects are allowed, multiple subjects can be split with a '|' pipe -->
<param name="tls-verify-in-subjects" value=""/>
<!-- TLS version ("sslv23" (default), "tlsv1"). NOTE: Phones may not work with TLSv1 -->
<param name="tls-version" value="$${sip_tls_version}"/>
<param name="ws-binding" value=":5066"/>
<param name="wss-binding" value=":7443"/>
<param name="rtcp-audio-interval-msec" value="5000"/>
<param name="rtcp-video-interval-msec" value="5000"/>
<param name="dtmf-type" value="info"/>
<param name="liberal-dtmf" value="true"/>
</settings>
</profile>

View File

@ -0,0 +1,119 @@
<profile name="external">
<!-- http://wiki.freeswitch.org/wiki/Sofia_Configuration_Files -->
<!-- This profile is only for outbound registrations to providers -->
<gateways>
<X-PRE-PROCESS cmd="include" data="external/*.xml"/>
</gateways>
<aliases>
<!--
<alias name="outbound"/>
<alias name="nat"/>
-->
</aliases>
<domains>
<domain name="all" alias="false" parse="true"/>
</domains>
<settings>
<param name="debug" value="0"/>
<!-- If you want FreeSWITCH to shutdown if this profile fails to load, uncomment the next line. -->
<!-- <param name="shutdown-on-fail" value="true"/> -->
<param name="sip-trace" value="no"/>
<param name="sip-capture" value="no"/>
<param name="rfc2833-pt" value="101"/>
<!-- RFC 5626 : Send reg-id and sip.instance -->
<!--<param name="enable-rfc-5626" value="true"/> -->
<param name="sip-port" value="$${external_sip_port}"/>
<param name="dialplan" value="XML"/>
<param name="context" value="public"/>
<param name="dtmf-duration" value="2000"/>
<param name="inbound-codec-prefs" value="$${global_codec_prefs}"/>
<param name="outbound-codec-prefs" value="$${outbound_codec_prefs}"/>
<param name="hold-music" value="$${hold_music}"/>
<param name="rtp-timer-name" value="soft"/>
<!--<param name="enable-100rel" value="true"/>-->
<!--<param name="disable-srv503" value="true"/>-->
<!-- This could be set to "passive" -->
<param name="local-network-acl" value="none"/>
<param name="manage-presence" value="false"/>
<!-- Added for Microsoft Edge browser -->
<param name="apply-candidate-acl" value="localnet.auto"/>
<param name="apply-candidate-acl" value="wan_v4.auto"/>
<param name="apply-candidate-acl" value="rfc1918.auto"/>
<param name="apply-candidate-acl" value="any_v4.auto"/>
<!-- used to share presence info across sofia profiles
manage-presence needs to be set to passive on this profile
if you want it to behave as if it were the internal profile
for presence.
-->
<!-- Name of the db to use for this profile -->
<!--<param name="dbname" value="share_presence"/>-->
<!--<param name="presence-hosts" value="$${domain}"/>-->
<!--<param name="force-register-domain" value="$${domain}"/>-->
<!--all inbound reg will stored in the db using this domain -->
<!--<param name="force-register-db-domain" value="$${domain}"/>-->
<!-- ************************************************* -->
<!--<param name="aggressive-nat-detection" value="true"/>-->
<param name="inbound-codec-negotiation" value="generous"/>
<param name="nonce-ttl" value="60"/>
<param name="auth-calls" value="false"/>
<param name="inbound-late-negotiation" value="true"/>
<param name="inbound-zrtp-passthru" value="true"/> <!-- (also enables late negotiation) -->
<!--
DO NOT USE HOSTNAMES, ONLY IP ADDRESSES IN THESE SETTINGS!
<param name="rtp-ip" value="$${local_ip_v4}"/>
<param name="sip-ip" value="$${local_ip_v4}"/>
<param name="ext-rtp-ip" value="auto-nat"/>
<param name="ext-sip-ip" value="auto-nat"/>
-->
<param name="rtp-ip" value="$${local_ip_v4}"/>
<param name="sip-ip" value="$${local_ip_v4}"/>
<param name="ext-rtp-ip" value="$${local_ip_v4}"/>
<param name="ext-sip-ip" value="$${local_ip_v4}"/>
<param name="rtp-timeout-sec" value="300"/>
<param name="rtp-hold-timeout-sec" value="1800"/>
<param name="enable-3pcc" value="proxy"/>
<!-- TLS: disabled by default, set to "true" to enable -->
<param name="tls" value="$${external_ssl_enable}"/>
<!-- Set to true to not bind on the normal sip-port but only on the TLS port -->
<param name="tls-only" value="false"/>
<!-- additional bind parameters for TLS -->
<param name="tls-bind-params" value="transport=tls"/>
<!-- Port to listen on for TLS requests. (5081 will be used if unspecified) -->
<param name="tls-sip-port" value="$${external_tls_port}"/>
<!-- Location of the agent.pem and cafile.pem ssl certificates (needed for TLS server) -->
<!--<param name="tls-cert-dir" value=""/>-->
<!-- Optionally set the passphrase password used by openSSL to encrypt/decrypt TLS private key files -->
<param name="tls-passphrase" value=""/>
<!-- Verify the date on TLS certificates -->
<param name="tls-verify-date" value="true"/>
<!-- TLS verify policy, when registering/inviting gateways with other servers (outbound) or handling inbound registration/invite requests how should we verify their certificate -->
<!-- set to 'in' to only verify incoming connections, 'out' to only verify outgoing connections, 'all' to verify all connections, also 'in_subjects', 'out_subjects' and 'all_subjects' for subject validation. Multiple policies can be split with a '|' pipe -->
<param name="tls-verify-policy" value="none"/>
<!-- Certificate max verify depth to use for validating peer TLS certificates when the verify policy is not none -->
<param name="tls-verify-depth" value="2"/>
<!-- If the tls-verify-policy is set to subjects_all or subjects_in this sets which subjects are allowed, multiple subjects can be split with a '|' pipe -->
<param name="tls-verify-in-subjects" value=""/>
<!-- TLS version ("sslv23" (default), "tlsv1"). NOTE: Phones may not work with TLSv1 -->
<param name="tls-version" value="$${sip_tls_version}"/>
<param name="ws-binding" value=":5066"/>
<param name="wss-binding" value=":7443"/>
<!-- enable rtcp on every channel also can be done per leg basis with rtcp_audio_interval_msec variable set to passthru to pass it across a call-->
<param name="rtcp-audio-interval-msec" value="5000"/>
<param name="rtcp-video-interval-msec" value="5000"/>
<!-- Cut down in the join time -->
<param name="dtmf-type" value="info"/>
<param name="liberal-dtmf" value="true"/>
</settings>
</profile>

View File

@ -0,0 +1,143 @@
<profile name="internal-ipv6">
<!--
This is an example of a sofia profile setup to listen on IPv6.
-->
<!-- http://wiki.freeswitch.org/wiki/Sofia_Configuration_Files -->
<!--aliases are other names that will work as a valid profile name for this profile-->
<settings>
<!-- Can be set to "_undef_" to remove the User-Agent header -->
<!-- <param name="user-agent-string" value="FreeSWITCH Rocks!"/> -->
<param name="debug" value="0"/>
<param name="sip-trace" value="no"/>
<param name="context" value="public"/>
<param name="rfc2833-pt" value="101"/>
<!-- port to bind to for sip traffic -->
<param name="sip-port" value="$${internal_sip_port}"/>
<param name="dialplan" value="XML"/>
<param name="dtmf-duration" value="2000"/>
<param name="inbound-codec-prefs" value="$${global_codec_prefs}"/>
<param name="outbound-codec-prefs" value="$${global_codec_prefs}"/>
<param name="use-rtp-timer" value="true"/>
<param name="rtp-timer-name" value="soft"/>
<!-- ip address to use for rtp -->
<param name="rtp-ip" value="$${local_ip_v6}"/>
<!-- ip address to bind to -->
<param name="sip-ip" value="$${local_ip_v6}"/>
<param name="hold-music" value="$${hold_music}"/>
<!--<param name="enable-100rel" value="false"/>-->
<!--<param name="disable-srv503" value="true"/>-->
<param name="apply-inbound-acl" value="domains"/>
<!-- Added for Microsoft Edge support -->
<param name="apply-candidate-acl" value="wan_v6.auto"/>
<param name="apply-candidate-acl" value="rfc1918.auto"/>
<param name="apply-candidate-acl" value="any_v6.auto"/>
<param name="apply-candidate-acl" value="wan_v4.auto"/>
<param name="apply-candidate-acl" value="any_v4.auto"/>
<!--<param name="apply-register-acl" value="domains"/>-->
<!--<param name="dtmf-type" value="info"/>-->
<param name="record-template" value="$${recordings_dir}/${caller_id_number}.${strftime(%Y-%m-%d-%H-%M-%S)}.wav"/>
<!--enable to use presence and mwi -->
<param name="manage-presence" value="true"/>
<!-- This setting is for AAL2 bitpacking on G726 -->
<!-- <param name="bitpacking" value="aal2"/> -->
<!--max number of open dialogs in proceeding -->
<!--<param name="max-proceeding" value="1000"/>-->
<!--session timers for all call to expire after the specified seconds -->
<!--<param name="session-timeout" value="1800"/>-->
<!--<param name="multiple-registrations" value="true"/>-->
<!--set to 'greedy' if you want your codec list to take precedence -->
<param name="inbound-codec-negotiation" value="generous"/>
<!-- if you want to send any special bind params of your own -->
<!--<param name="bind-params" value="transport=udp"/>-->
<!--<param name="unregister-on-options-fail" value="true"/>-->
<!-- TLS: disabled by default, set to "true" to enable -->
<param name="tls" value="$${internal_ssl_enable}"/>
<!-- additional bind parameters for TLS -->
<param name="tls-bind-params" value="transport=tls"/>
<!-- Port to listen on for TLS requests. (5061 will be used if unspecified) -->
<param name="tls-sip-port" value="$${internal_tls_port}"/>
<!-- Location of the agent.pem and cafile.pem ssl certificates (needed for TLS server) -->
<param name="tls-cert-dir" value="$${internal_ssl_dir}"/>
<!-- TLS version ("sslv23" (default), "tlsv1"). NOTE: Phones may not work with TLSv1 -->
<param name="tls-version" value="$${sip_tls_version}"/>
<!--If you don't want to pass through timestampes from 1 RTP call to another (on a per call basis with rtp_rewrite_timestamps chanvar)-->
<!--<param name="rtp-rewrite-timestamps" value="true"/>-->
<!--<param name="pass-rfc2833" value="true"/>-->
<!--If you have ODBC support and a working dsn you can use it instead of SQLite-->
<!--<param name="odbc-dsn" value="dsn:user:pass"/>-->
<!--Uncomment to set all inbound calls to no media mode-->
<!--<param name="inbound-bypass-media" value="true"/>-->
<!--Uncomment to set all inbound calls to proxy media mode-->
<!--<param name="inbound-proxy-media" value="true"/>-->
<!-- Let calls hit the dialplan before selecting codec for the a-leg -->
<param name="inbound-late-negotiation" value="true"/>
<!-- Allow ZRTP clients to negotiate end-to-end security associations (also enables late negotiation) -->
<param name="inbound-zrtp-passthru" value="true"/>
<!-- this lets anything register -->
<!-- comment the next line and uncomment one or both of the other 2 lines for call authentication -->
<!-- <param name="accept-blind-reg" value="true"/> -->
<!-- accept any authentication without actually checking (not a good feature for most people) -->
<!-- <param name="accept-blind-auth" value="true"/> -->
<!-- suppress CNG on this profile or per call with the 'suppress_cng' variable -->
<!-- <param name="suppress-cng" value="true"/> -->
<!--TTL for nonce in sip auth-->
<param name="nonce-ttl" value="60"/>
<!--Uncomment if you want to force the outbound leg of a bridge to only offer the codec
that the originator is using-->
<!--<param name="disable-transcoding" value="true"/>-->
<!-- Used for when phones respond to a challenged ACK with method INVITE in the hash -->
<!--<param name="NDLB-broken-auth-hash" value="true"/>-->
<!-- add a ;received="<ip>:<port>" to the contact when replying to register for nat handling -->
<!--<param name="NDLB-received-in-nat-reg-contact" value="true"/>-->
<param name="auth-calls" value="$${internal_auth_calls}"/>
<!-- on authed calls, authenticate *all* the packets not just invite -->
<param name="auth-all-packets" value="false"/>
<!-- Shouldn't set these on IPv6 -->
<!-- <param name="ext-rtp-ip" value="$${external_rtp_ip}"/> -->
<!-- <param name="ext-sip-ip" value="$${external_sip_ip}"/> -->
<!-- rtp inactivity timeout -->
<param name="rtp-timeout-sec" value="300"/>
<param name="rtp-hold-timeout-sec" value="1800"/>
<!-- VAD choose one (out is a good choice); -->
<!-- <param name="vad" value="in"/> -->
<!-- <param name="vad" value="out"/> -->
<!-- <param name="vad" value="both"/> -->
<!--<param name="alias" value="sip:10.0.1.251:5555"/>-->
<!--
These are enabled to make the default config work better out of the box.
If you need more than ONE domain you'll need to not use these options.
-->
<!--all inbound reg will look in this domain for the users -->
<param name="force-register-domain" value="$${domain}"/>
<!--all inbound reg will stored in the db using this domain -->
<param name="force-register-db-domain" value="$${domain}"/>
<!-- disable register and transfer which may be undesirable in a public switch -->
<!--<param name="disable-transfer" value="true"/>-->
<!--<param name="disable-register" value="true"/>-->
<!--<param name="enable-3pcc" value="true"/>-->
<!-- use stun when specified (default is true) -->
<!--<param name="stun-enabled" value="true"/>-->
<!-- use stun when specified (default is true) -->
<!-- set to true to have the profile determine stun is not useful and turn it off globally-->
<!--<param name="stun-auto-disable" value="true"/>-->
<!-- the following can be used as workaround with bogus SRV/NAPTR records -->
<!--<param name="disable-srv" value="false" />-->
<!--<param name="disable-naptr" value="false" />-->
</settings>
</profile>

View File

@ -0,0 +1,428 @@
<profile name="internal">
<!--
This is a sofia sip profile/user agent. This will service exactly one ip and port.
In FreeSWITCH you can run multiple sip user agents on their own ip and port.
When you hear someone say "sofia profile" this is what they are talking about.
-->
<!-- http://wiki.freeswitch.org/wiki/Sofia_Configuration_Files -->
<!--aliases are other names that will work as a valid profile name for this profile-->
<aliases>
<!--
<alias name="default"/>
-->
</aliases>
<!-- Outbound Registrations -->
<gateways>
</gateways>
<domains>
<!-- indicator to parse the directory for domains with parse="true" to get gateways-->
<!--<domain name="$${domain}" parse="true"/>-->
<!-- indicator to parse the directory for domains with parse="true" to get gateways and alias every domain to this profile -->
<!--<domain name="all" alias="true" parse="true"/>-->
<domain name="all" alias="true" parse="false"/>
</domains>
<settings>
<!-- inject delay between dtmf digits on send to help some slow interpreters (also per channel with rtp_digit_delay var -->
<!-- <param name="rtp-digit-delay" value="40"/>-->
<!--
When calls are in no media this will bring them back to media
when you press the hold button.
-->
<!--<param name="media-option" value="resume-media-on-hold"/> -->
<!--
This will allow a call after an attended transfer go back to
bypass media after an attended transfer.
-->
<!--<param name="media-option" value="bypass-media-after-att-xfer"/>-->
<!-- Can be set to "_undef_" to remove the User-Agent header -->
<!-- <param name="user-agent-string" value="FreeSWITCH Rocks!"/> -->
<param name="debug" value="0"/>
<!-- If you want FreeSWITCH to shutdown if this profile fails to load, uncomment the next line. -->
<!-- <param name="shutdown-on-fail" value="true"/> -->
<param name="sip-trace" value="no"/>
<param name="sip-capture" value="no"/>
<!-- Use presence_map.conf.xml to convert extension regex to presence protos for routing -->
<!-- <param name="presence-proto-lookup" value="true"/> -->
<!-- Don't be picky about negotiated DTMF just always offer 2833 and accept both 2833 and INFO -->
<!--<param name="liberal-dtmf" value="true"/>-->
<!--
Sometimes, in extremely rare edge cases, the Sofia SIP stack may stop
responding. These options allow you to enable and control a watchdog
on the Sofia SIP stack so that if it stops responding for the
specified number of milliseconds, it will cause FreeSWITCH to crash
immediately. This is useful if you run in an HA environment and
need to ensure automated recovery from such a condition. Note that if
your server is idle a lot, the watchdog may fire due to not receiving
any SIP messages. Thus, if you expect your system to be idle, you
should leave the watchdog disabled. It can be toggled on and off
through the FreeSWITCH CLI either on an individual profile basis or
globally for all profiles. So, if you run in an HA environment with a
master and slave, you should use the CLI to make sure the watchdog is
only enabled on the master.
If such crash occurs, FreeSWITCH will dump core if allowed. The
stacktrace will include function watchdog_triggered_abort().
-->
<param name="watchdog-enabled" value="no"/>
<param name="watchdog-step-timeout" value="30000"/>
<param name="watchdog-event-timeout" value="30000"/>
<param name="log-auth-failures" value="false"/>
<param name="forward-unsolicited-mwi-notify" value="false"/>
<param name="context" value="public"/>
<param name="rfc2833-pt" value="101"/>
<!-- port to bind to for sip traffic -->
<param name="sip-port" value="$${internal_sip_port}"/>
<param name="dialplan" value="XML"/>
<param name="dtmf-duration" value="2000"/>
<param name="inbound-codec-prefs" value="$${global_codec_prefs}"/>
<param name="outbound-codec-prefs" value="$${global_codec_prefs}"/>
<param name="rtp-timer-name" value="soft"/>
<!-- ip address to use for rtp, DO NOT USE HOSTNAMES ONLY IP ADDRESSES -->
<param name="rtp-ip" value="$${local_ip_v4}"/>
<!-- ip address to bind to, DO NOT USE HOSTNAMES ONLY IP ADDRESSES -->
<param name="sip-ip" value="$${local_ip_v4}"/>
<param name="hold-music" value="$${hold_music}"/>
<param name="apply-nat-acl" value="nat.auto"/>
<!-- (default true) set to false if you do not wish to have called party info in 1XX responses -->
<!-- <param name="cid-in-1xx" value="false"/> -->
<!-- extended info parsing -->
<!-- <param name="extended-info-parsing" value="true"/> -->
<!--<param name="aggressive-nat-detection" value="true"/>-->
<!--
There are known issues (asserts and segfaults) when 100rel is enabled.
It is not recommended to enable 100rel at this time.
-->
<!--<param name="enable-100rel" value="true"/>-->
<!-- uncomment if you don't wish to try a next SRV destination on 503 response -->
<!-- RFC3263 Section 4.3 -->
<!--<param name="disable-srv503" value="true"/>-->
<!-- Enable Compact SIP headers. -->
<!--<param name="enable-compact-headers" value="true"/>-->
<!--
enable/disable session timers
-->
<!--<param name="enable-timer" value="false"/>-->
<!--<param name="minimum-session-expires" value="120"/>-->
<param name="apply-inbound-acl" value="domains"/>
<!--
This defines your local network, by default we detect your local network
and create this localnet.auto ACL for this.
-->
<param name="local-network-acl" value="localnet.auto"/>
<!--<param name="apply-register-acl" value="domains"/>-->
<!--<param name="dtmf-type" value="info"/>-->
<!-- Added for Microsoft Edge support -->
<param name="apply-candidate-acl" value="wan_v6.auto"/>
<param name="apply-candidate-acl" value="rfc1918.auto"/>
<param name="apply-candidate-acl" value="any_v6.auto"/>
<param name="apply-candidate-acl" value="wan_v4.auto"/>
<param name="apply-candidate-acl" value="any_v4.auto"/>
<!-- 'true' means every time 'first-only' means on the first register -->
<!--<param name="send-message-query-on-register" value="true"/>-->
<!-- 'true' means every time 'first-only' means on the first register -->
<!--<param name="send-presence-on-register" value="first-only"/> -->
<!-- Caller-ID type (choose one, can be overridden by inbound call type and/or sip_cid_type channel variable -->
<!-- Remote-Party-ID header -->
<!--<param name="caller-id-type" value="rpid"/>-->
<!-- P-*-Identity family of headers -->
<!--<param name="caller-id-type" value="pid"/>-->
<!-- neither one -->
<!--<param name="caller-id-type" value="none"/>-->
<param name="record-path" value="$${recordings_dir}"/>
<param name="record-template" value="${caller_id_number}.${target_domain}.${strftime(%Y-%m-%d-%H-%M-%S)}.wav"/>
<!--enable to use presence -->
<param name="manage-presence" value="true"/>
<!-- send a presence probe on each register to query devices to send presence instead of sending presence with less info -->
<!--<param name="presence-probe-on-register" value="true"/>-->
<!--<param name="manage-shared-appearance" value="true"/>-->
<!-- used to share presence info across sofia profiles -->
<!-- Name of the db to use for this profile -->
<!--<param name="dbname" value="share_presence"/>-->
<param name="presence-hosts" value="$${domain},$${local_ip_v4}"/>
<param name="presence-privacy" value="$${presence_privacy}"/>
<!-- ************************************************* -->
<!-- This setting is for AAL2 bitpacking on G726 -->
<!-- <param name="bitpacking" value="aal2"/> -->
<!--max number of open dialogs in proceeding -->
<!--<param name="max-proceeding" value="1000"/>-->
<!--session timers for all call to expire after the specified seconds -->
<!--<param name="session-timeout" value="1800"/>-->
<!-- Can be 'true' or 'contact' -->
<!--<param name="multiple-registrations" value="contact"/>-->
<!--set to 'greedy' if you want your codec list to take precedence -->
<param name="inbound-codec-negotiation" value="generous"/>
<!-- if you want to send any special bind params of your own -->
<!--<param name="bind-params" value="transport=udp"/>-->
<!--<param name="unregister-on-options-fail" value="true"/>-->
<!-- Send an OPTIONS packet to all registered endpoints -->
<!--<param name="all-reg-options-ping" value="true"/>-->
<!-- Send an OPTIONS packet to NATed registered endpoints. Can be 'true' or 'udp-only'. -->
<!--<param name="nat-options-ping" value="true"/>-->
<!--<param name="sip-options-respond-503-on-busy" value="true"/>-->
<!--<param name="sip-messages-respond-200-ok" value="true"/>-->
<!--<param name="sip-subscribe-respond-200-ok" value="true"/>-->
<!-- TLS: disabled by default, set to "true" to enable -->
<param name="tls" value="$${internal_ssl_enable}"/>
<!-- Set to true to not bind on the normal sip-port but only on the TLS port -->
<param name="tls-only" value="false"/>
<!-- additional bind parameters for TLS -->
<param name="tls-bind-params" value="transport=tls"/>
<!-- Port to listen on for TLS requests. (5061 will be used if unspecified) -->
<param name="tls-sip-port" value="$${internal_tls_port}"/>
<!-- Location of the agent.pem and cafile.pem ssl certificates (needed for TLS server) -->
<!--<param name="tls-cert-dir" value=""/>-->
<!-- Optionally set the passphrase password used by openSSL to encrypt/decrypt TLS private key files -->
<param name="tls-passphrase" value=""/>
<!-- Verify the date on TLS certificates -->
<param name="tls-verify-date" value="true"/>
<!-- TLS verify policy, when registering/inviting gateways with other servers (outbound) or handling inbound registration/invite requests how should we verify their certificate -->
<!-- set to 'in' to only verify incoming connections, 'out' to only verify outgoing connections, 'all' to verify all connections, also 'subjects_in', 'subjects_out' and 'subjects_all' for subject validation. Multiple policies can be split with a '|' pipe -->
<param name="tls-verify-policy" value="none"/>
<!-- Certificate max verify depth to use for validating peer TLS certificates when the verify policy is not none -->
<param name="tls-verify-depth" value="2"/>
<!-- If the tls-verify-policy is set to subjects_all or subjects_in this sets which subjects are allowed, multiple subjects can be split with a '|' pipe -->
<param name="tls-verify-in-subjects" value=""/>
<!-- TLS version default: tlsv1,tlsv1.1,tlsv1.2 -->
<param name="tls-version" value="$${sip_tls_version}"/>
<!-- TLS ciphers default: ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH -->
<param name="tls-ciphers" value="$${sip_tls_ciphers}"/>
<!-- turn on auto-flush during bridge (skip timer sleep when the socket already has data)
(reduces delay on latent connections default true, must be disabled explicitly)-->
<!--<param name="rtp-autoflush-during-bridge" value="false"/>-->
<!--If you don't want to pass through timestamps from 1 RTP call to another (on a per call basis with rtp_rewrite_timestamps chanvar)-->
<!--<param name="rtp-rewrite-timestamps" value="true"/>-->
<!--<param name="pass-rfc2833" value="true"/>-->
<!--If you have ODBC support and a working dsn you can use it instead of SQLite-->
<!--<param name="odbc-dsn" value="dsn:user:pass"/>-->
<!-- Or, if you have PGSQL support, you can use that -->
<!--<param name="odbc-dsn" value="pgsql://hostaddr=127.0.0.1 dbname=freeswitch user=freeswitch password='' options='-c client_min_messages=NOTICE' application_name='freeswitch'" />-->
<!--Uncomment to set all inbound calls to no media mode-->
<!--<param name="inbound-bypass-media" value="true"/>-->
<!--Uncomment to set all inbound calls to proxy media mode-->
<!--<param name="inbound-proxy-media" value="true"/>-->
<!-- Let calls hit the dialplan before selecting codec for the a-leg -->
<param name="inbound-late-negotiation" value="true"/>
<!-- Allow ZRTP clients to negotiate end-to-end security associations (also enables late negotiation) -->
<param name="inbound-zrtp-passthru" value="true"/>
<!-- this lets anything register -->
<!-- comment the next line and uncomment one or both of the other 2 lines for call authentication -->
<!-- <param name="accept-blind-reg" value="true"/> -->
<!-- accept any authentication without actually checking (not a good feature for most people) -->
<!-- <param name="accept-blind-auth" value="true"/> -->
<!-- suppress CNG on this profile or per call with the 'suppress_cng' variable -->
<!-- <param name="suppress-cng" value="true"/> -->
<!--TTL for nonce in sip auth-->
<param name="nonce-ttl" value="60"/>
<!--Uncomment if you want to force the outbound leg of a bridge to only offer the codec
that the originator is using-->
<!--<param name="disable-transcoding" value="true"/>-->
<!-- Handle 302 Redirect in the dialplan -->
<!--<param name="manual-redirect" value="true"/> -->
<!-- Disable Transfer -->
<!--<param name="disable-transfer" value="true"/> -->
<!-- Disable Register -->
<!--<param name="disable-register" value="true"/> -->
<!-- Used for when phones respond to a challenged ACK with method INVITE in the hash -->
<!--<param name="NDLB-broken-auth-hash" value="true"/>-->
<!-- add a ;received="<ip>:<port>" to the contact when replying to register for nat handling -->
<!--<param name="NDLB-received-in-nat-reg-contact" value="true"/>-->
<param name="auth-calls" value="$${internal_auth_calls}"/>
<!-- Force the user and auth-user to match. -->
<param name="inbound-reg-force-matching-username" value="true"/>
<!-- on authed calls, authenticate *all* the packets not just invite -->
<param name="auth-all-packets" value="false"/>
<!-- external_sip_ip
Used as the public IP address for SDP.
Can be an one of:
ip address - "12.34.56.78"
a stun server lookup - "stun:stun.server.com"
a DNS name - "host:host.server.com"
auto - Use guessed ip.
auto-nat - Use ip learned from NAT-PMP or UPNP
-->
<param name="ext-rtp-ip" value="auto-nat"/>
<param name="ext-sip-ip" value="auto-nat"/>
<!-- rtp inactivity timeout -->
<param name="rtp-timeout-sec" value="300"/>
<param name="rtp-hold-timeout-sec" value="1800"/>
<!-- VAD choose one (out is a good choice); -->
<!-- <param name="vad" value="in"/> -->
<!-- <param name="vad" value="out"/> -->
<!-- <param name="vad" value="both"/> -->
<!--<param name="alias" value="sip:10.0.1.251:5555"/>-->
<!--
These are enabled to make the default config work better out of the box.
If you need more than ONE domain you'll need to not use these options.
-->
<!--all inbound reg will look in this domain for the users -->
<param name="force-register-domain" value="$${domain}"/>
<!--force the domain in subscriptions to this value -->
<param name="force-subscription-domain" value="$${domain}"/>
<!--all inbound reg will stored in the db using this domain -->
<param name="force-register-db-domain" value="$${domain}"/>
<!-- for sip over websocket support -->
<!-- param name="ws-binding" value=":5066"/ -->
<!-- for sip over secure websocket support -->
<!-- You need wss.pem in $${certs_dir} for wss or one will be created for you -->
<!-- param name="wss-binding" value=":7443"/ -->
<!--<param name="delete-subs-on-register" value="false"/>-->
<!-- launch a new thread to process each new inbound register when using heavier backends -->
<!-- <param name="inbound-reg-in-new-thread" value="true"/> -->
<!-- enable rtcp on every channel also can be done per leg basis with rtcp_audio_interval_msec variable set to passthru to pass it across a call-->
<!--<param name="rtcp-audio-interval-msec" value="5000"/>-->
<!--<param name="rtcp-video-interval-msec" value="5000"/>-->
<!--force suscription expires to a lower value than requested-->
<!--<param name="force-subscription-expires" value="60"/>-->
<!-- add a random deviation to the expires value of the 202 Accepted -->
<!--<param name="sip-subscription-max-deviation" value="120"/>-->
<!-- disable register and transfer which may be undesirable in a public switch -->
<!--<param name="disable-transfer" value="true"/>-->
<!--<param name="disable-register" value="true"/>-->
<!--
enable-3pcc can be set to either 'true' or 'proxy', true accepts the call
right away, proxy waits until the call has been answered then sends accepts
-->
<param name="enable-3pcc" value="proxy"/>
<!-- use at your own risk or if you know what this does.-->
<!--<param name="NDLB-force-rport" value="true"/>-->
<!--
Choose the realm challenge key. Default is auto_to if not set.
auto_from - uses the from field as the value for the sip realm.
auto_to - uses the to field as the value for the sip realm.
<anyvalue> - you can input any value to use for the sip realm.
If you want URL dialing to work you'll want to set this to auto_from.
If you use any other value besides auto_to or auto_from you'll
loose the ability to do multiple domains.
Note: comment out to restore the behavior before 2008-09-29
-->
<param name="challenge-realm" value="auto_from"/>
<!--<param name="disable-rtp-auto-adjust" value="true"/>-->
<!-- on inbound calls make the uuid of the session equal to the sip call id of that call -->
<!--<param name="inbound-use-callid-as-uuid" value="true"/>-->
<!-- on outbound calls set the callid to match the uuid of the session -->
<!--<param name="outbound-use-uuid-as-callid" value="true"/>-->
<!-- set to false disable this feature -->
<!--<param name="rtp-autofix-timing" value="false"/>-->
<!-- set this param to false if your gateway for some reason hates X- headers that it is supposed to ignore-->
<!--<param name="pass-callee-id" value="false"/>-->
<!-- clear clears them all or supply the name to add or the name
prefixed with ~ to remove valid values:
clear
CISCO_SKIP_MARK_BIT_2833
SONUS_SEND_INVALID_TIMESTAMP_2833
-->
<!--<param name="auto-rtp-bugs" data="clear"/>-->
<!-- the following can be used as workaround with bogus SRV/NAPTR records -->
<!--<param name="disable-srv" value="false" />-->
<!--<param name="disable-naptr" value="false" />-->
<!-- The following can be used to fine-tune timers within sofia's transport layer
Those settings are for advanced users and can safely be left as-is -->
<!-- Initial retransmission interval (in milliseconds).
Set the T1 retransmission interval used by the SIP transaction engine.
The T1 is the initial duration used by request retransmission timers A and E (UDP) as well as response retransmission timer G. -->
<!-- <param name="timer-T1" value="500" /> -->
<!-- Transaction timeout (defaults to T1 * 64).
Set the T1x64 timeout value used by the SIP transaction engine.
The T1x64 is duration used for timers B, F, H, and J (UDP) by the SIP transaction engine.
The timeout value T1x64 can be adjusted separately from the initial retransmission interval T1. -->
<!-- <param name="timer-T1X64" value="32000" /> -->
<!-- Maximum retransmission interval (in milliseconds).
Set the maximum retransmission interval used by the SIP transaction engine.
The T2 is the maximum duration used for the timers E (UDP) and G by the SIP transaction engine.
Note that the timer A is not capped by T2. Retransmission interval of INVITE requests grows exponentially
until the timer B fires. -->
<!-- <param name="timer-T2" value="4000" /> -->
<!--
Transaction lifetime (in milliseconds).
Set the lifetime for completed transactions used by the SIP transaction engine.
A completed transaction is kept around for the duration of T4 in order to catch late responses.
The T4 is the maximum duration for the messages to stay in the network and the duration of SIP timer K. -->
<!-- <param name="timer-T4" value="4000" /> -->
<!-- Turn on a jitterbuffer for every call -->
<!-- <param name="auto-jitterbuffer-msec" value="60"/> -->
<!-- By default mod_sofia will ignore the codecs in the sdp for hold/unhold operations
Set this to true if you want to actually parse the sdp and re-negotiate the codec during hold/unhold.
It's probably not what you want so stick with the default unless you really need to change this.
-->
<!--<param name="renegotiate-codec-on-hold" value="true"/>-->
</settings>
</profile>

View File

@ -0,0 +1,145 @@
<configuration name="modules.conf" description="Modules">
<modules>
<!-- Loggers (I'd load these first) -->
<load module="mod_console"/>
<!-- <load module="mod_graylog2"/> -->
<load module="mod_logfile"/>
<!-- <load module="mod_syslog"/> -->
<!--<load module="mod_yaml"/>-->
<!-- Multi-Faceted -->
<!-- mod_enum is a dialplan interface, an application interface and an api command interface -->
<load module="mod_enum"/>
<!-- XML Interfaces -->
<!-- <load module="mod_xml_rpc"/> -->
<!-- <load module="mod_xml_curl"/> -->
<!-- <load module="mod_xml_cdr"/> -->
<!-- <load module="mod_xml_radius"/> -->
<!-- <load module="mod_xml_scgi"/> -->
<!-- Event Handlers -->
<!-- <load module="mod_amqp"/> -->
<!-- <load module="mod_cdr_csv"/> -->
<!-- <load module="mod_cdr_sqlite"/> -->
<!-- <load module="mod_event_multicast"/> -->
<load module="mod_event_socket"/>
<!-- <load module="mod_event_zmq"/> -->
<!-- <load module="mod_zeroconf"/> -->
<!-- <load module="mod_erlang_event"/> -->
<!-- <load module="mod_smpp"/> -->
<!-- <load module="mod_snmp"/> -->
<!-- Directory Interfaces -->
<!-- <load module="mod_ldap"/> -->
<!-- Endpoints -->
<!-- <load module="mod_dingaling"/> -->
<!-- <load module="mod_portaudio"/> -->
<!-- <load module="mod_alsa"/> -->
<load module="mod_sofia"/>
<load module="mod_loopback"/>
<!-- <load module="mod_woomera"/> -->
<!-- <load module="mod_freetdm"/> -->
<!-- <load module="mod_unicall"/> -->
<!-- <load module="mod_skinny"/> -->
<!-- <load module="mod_khomp"/> -->
<load module="mod_rtc"/>
<!-- <load module="mod_rtmp"/> -->
<load module="mod_verto"/>
<!-- Applications -->
<load module="mod_commands"/>
<load module="mod_conference"/>
<!-- <load module="mod_curl"/> -->
<load module="mod_db"/>
<load module="mod_dptools"/>
<load module="mod_expr"/>
<load module="mod_fifo"/>
<load module="mod_hash"/>
<!--<load module="mod_mongo"/> -->
<!--load module="mod_voicemail"/>-->
<!--<load module="mod_directory"/>-->
<!--<load module="mod_distributor"/>-->
<!--<load module="mod_lcr"/>-->
<!--<load module="mod_easyroute"/>-->
<load module="mod_esf"/>
<load module="mod_fsv"/>
<!--<load module="mod_cluechoo"/>-->
<!--load module="mod_valet_parking"/>-->
<!--<load module="mod_fsk"/>-->
<!--<load module="mod_spy"/>-->
<!--<load module="mod_sms"/>-->
<!--<load module="mod_smpp"/>-->
<!--<load module="mod_random"/>-->
<load module="mod_httapi"/>
<!--<load module="mod_translate"/>-->
<!-- SNOM Module -->
<!--<load module="mod_snom"/>-->
<!-- This one only works on Linux for now -->
<!--<load module="mod_ladspa"/>-->
<!-- Dialplan Interfaces -->
<!-- <load module="mod_dialplan_directory"/> -->
<load module="mod_dialplan_xml"/>
<load module="mod_dialplan_asterisk"/>
<!-- Codec Interfaces -->
<load module="mod_spandsp"/>
<load module="mod_g723_1"/>
<load module="mod_g729"/>
<load module="mod_amr"/>
<!--<load module="mod_ilbc"/>-->
<!--<load module="mod_h26x"/>-->
<load module="mod_b64"/>
<!--<load module="mod_siren"/>-->
<!--<load module="mod_isac"/>-->
<load module="mod_opus"/>
<load module="mod_opusfile"/>
<!-- File Format Interfaces -->
<load module="mod_sndfile"/>
<load module="mod_native_file"/>
<load module="mod_png"/>
<!-- <load module="mod_shell_stream"/> -->
<!--For icecast/mp3 streams/files-->
<!--<load module="mod_shout"/>-->
<!--For local streams (play all the files in a directory)-->
<load module="mod_local_stream"/>
<load module="mod_tone_stream"/>
<!-- Timers -->
<!-- <load module="mod_timerfd"/> -->
<!-- <load module="mod_posix_timer"/> -->
<!-- Languages -->
<!-- <load module="mod_v8"/> -->
<!-- <load module="mod_perl"/> -->
<!-- <load module="mod_python"/> -->
<!-- <load module="mod_java"/> -->
<load module="mod_lua"/>
<!-- ASR /TTS -->
<!-- <load module="mod_flite"/> -->
<!-- <load module="mod_pocketsphinx"/> -->
<!-- <load module="mod_cepstral"/> -->
<!-- <load module="mod_tts_commandline"/> -->
<!-- <load module="mod_rss"/> -->
<!-- Say -->
<load module="mod_say_en"/>
<!-- <load module="mod_say_ru"/> -->
<!-- <load module="mod_say_zh"/> -->
<!-- <load module="mod_say_sv"/> -->
<!-- Third party modules -->
<!--<load module="mod_nibblebill"/>-->
<!--<load module="mod_callcenter"/>-->
<!--<load module="mod_av"/-->
</modules>
</configuration>

View File

@ -0,0 +1,12 @@
<configuration name="opus.conf">
<settings>
<param name="use-vbr" value="1"/>
<param name="use-dtx" value="0"/>
<param name="complexity" value="5"/>
<param name="packet-loss-percent" value="15"/>
<param name="keep-fec-enabled" value="1"/>
<param name="use-jb-lookahead" value="1"/>
<param name="advertise-useinbandfec" value="1"/>
</settings>
</configuration>

View File

@ -0,0 +1,43 @@
<!--
NOTICE:
This context is usually accessed via the external sip profile listening on port 5080.
It is recommended to have separate inbound and outbound contexts. Not only for security
but clearing up why you would need to do such a thing. You don't want outside un-authenticated
callers hitting your default context which allows dialing calls thru your providers and results
in Toll Fraud.
-->
<!-- http://wiki.freeswitch.org/wiki/Dialplan_XML -->
<include>
<context name="public">
<extension name="unloop">
<condition field="${unroll_loops}" expression="^true$"/>
<condition field="${sip_looped_call}" expression="^true$">
<action application="deflect" data="${destination_number}"/>
</condition>
</extension>
<!--
Tag anything pass thru here as an outside_call so you can make sure not
to create any routing loops based on the conditions that it came from
the outside of the switch.
-->
<extension name="outside_call" continue="true">
<condition>
<action application="set" data="outside_call=true"/>
<action application="export" data="RFC2822_DATE=${strftime(%a, %d %b %Y %T %z)}"/>
</condition>
</extension>
<!--
You can place files in the public directory to get included.
-->
<X-PRE-PROCESS cmd="include" data="public/*.xml"/>
</context>
</include>

View File

@ -0,0 +1,182 @@
<configuration name="switch.conf" description="Core Configuration">
<cli-keybindings>
<key name="1" value="help"/>
<key name="2" value="status"/>
<key name="3" value="show channels"/>
<key name="4" value="show calls"/>
<key name="5" value="sofia status"/>
<key name="6" value="reloadxml"/>
<key name="7" value="console loglevel 0"/>
<key name="8" value="console loglevel 7"/>
<key name="9" value="sofia status profile internal"/>
<key name="10" value="sofia profile internal siptrace on"/>
<key name="11" value="sofia profile internal siptrace off"/>
<key name="12" value="version"/>
</cli-keybindings>
<default-ptimes>
<!-- Set this to override the 20ms assumption of various codecs in the sdp with no ptime defined -->
<!-- <codec name="G729" ptime="40"/> -->
</default-ptimes>
<settings>
<!-- Colorize the Console -->
<param name="colorize-console" value="true"/>
<!--Include full timestamps in dialplan logs -->
<param name="dialplan-timestamps" value="false"/>
<!-- Run the timer at 20ms by default and drop down as needed unless you set 1m-timer=true which was previous default -->
<!-- <param name="1ms-timer" value="true"/> -->
<!--
Set the Switch Name for HA environments.
When setting the switch name, it will override the system hostname for all DB and CURL requests
allowing cluster environments such as RHCS to have identical FreeSWITCH configurations but run
as different hostnames.
-->
<!-- <param name="switchname" value="freeswitch"/> -->
<!-- <param name="cpu-idle-smoothing-depth" value="30"/> -->
<!-- Maximum number of simultaneous DB handles open -->
<param name="max-db-handles" value="50"/>
<!-- Maximum number of seconds to wait for a new DB handle before failing -->
<param name="db-handle-timeout" value="10"/>
<!-- Minimum idle CPU before refusing calls -->
<!-- <param name="min-idle-cpu" value="25"/> -->
<!--
Max number of sessions to allow at any given time.
NOTICE: If you're driving 28 T1's in a single box you should set this to 644*2 or 1288
this will ensure you're able to use the entire DS3 without a problem. Otherwise you'll
be 144 channels short of always filling that DS3 up which can translate into waste.
-->
<param name="max-sessions" value="1000"/>
<!--Most channels to create per second -->
<param name="sessions-per-second" value="30"/>
<!-- Default Global Log Level - value is one of debug,info,notice,warning,err,crit,alert -->
<param name="loglevel" value="debug"/>
<!-- Set the core DEBUG level (0-10) -->
<!-- <param name="debug-level" value="10"/> -->
<!-- SQL Buffer length within rage of 32k to 10m -->
<!-- <param name="sql-buffer-len" value="1m"/> -->
<!-- Maximum SQL Buffer length must be greater than sql-buffer-len -->
<!-- <param name="max-sql-buffer-len" value="2m"/> -->
<!--
The min-dtmf-duration specifies the minimum DTMF duration to use on
outgoing events. Events shorter than this will be increased in duration
to match min_dtmf_duration. You cannot configure a dtmf duration on a
profile that is less than this setting. You may increase this value,
but cannot set it lower than 400. This value cannot exceed
max-dtmf-duration. -->
<!-- <param name="min-dtmf-duration" value="400"/> -->
<!--
The max-dtmf-duration caps the playout of a DTMF event at the specified
duration. Events exceeding this duration will be truncated to this
duration. You cannot configure a duration on a profile that exceeds
this setting. This setting can be lowered, but cannot exceed 192000.
This setting cannot be set lower than min_dtmf_duration. -->
<!-- <param name="max-dtmf-duration" value="192000"/> -->
<!--
The default_dtmf_duration specifies the DTMF duration to use on
originated DTMF events or on events that are received without a
duration specified. This value can be increased or lowered. This
value is lower-bounded by min_dtmf_duration and upper-bounded by
max-dtmf-duration\. -->
<!-- <param name="default-dtmf-duration" value="2000"/> -->
<!--
If you want to send out voicemail notifications via Windows you'll need to change the mailer-app
variable to the setting below:
<param name="mailer-app" value="msmtp"/>
Do not change mailer-app-args.
You will also need to download a sendmail clone for Windows (msmtp). This version works without issue:
http://msmtp.sourceforge.net/index.html. Download and copy the .exe to %winddir%\system32.
You'll need to create a small config file for smtp credentials (host name, authentication, tls, etc.) in
%USERPROFILE%\Application Data\ called "msmtprc.txt". Below is a sample copy of this file:
###################################
# The SMTP server of the provider.
account provider
host smtp.myisp.com
from john@myisp.com
auth login
user johndoe
password mypassword
# Set a default account
account default : provider
###################################
-->
<param name="mailer-app" value="sendmail"/>
<param name="mailer-app-args" value="-t"/>
<param name="dump-cores" value="yes"/>
<!-- Enable verbose channel events to include every detail about a channel on every event -->
<!-- <param name="verbose-channel-events" value="no"/> -->
<!-- Enable clock nanosleep -->
<!-- <param name="enable-clock-nanosleep" value="true"/> -->
<!-- Enable monotonic timing -->
<!-- <param name="enable-monotonic-timing" value="true"/> -->
<!-- NEEDS DOCUMENTATION -->
<!-- <param name="enable-softtimer-timerfd" value="true"/> -->
<!-- <param name="enable-cond-yield" value="true"/> -->
<!-- <param name="enable-timer-matrix" value="true"/> -->
<!-- <param name="threaded-system-exec" value="true"/> -->
<!-- <param name="tipping-point" value="0"/> -->
<!-- <param name="timer-affinity" value="disabled"/> -->
<!-- NEEDS DOCUMENTATION -->
<!-- RTP port range -->
<param name="rtp-start-port" value="16384"/>
<param name="rtp-end-port" value="24576"/>
<!-- Test each port to make sure it is not in use by some other process before allocating it to RTP -->
<!-- <param name="rtp-port-usage-robustness" value="true"/> -->
<param name="rtp-enable-zrtp" value="true"/>
<!--
Store encryption keys for secure media in channel variables and call CDRs. Default: false.
WARNING: If true, anyone with CDR access can decrypt secure media!
-->
<!-- <param name="rtp-retain-crypto-keys" value="true"/> -->
<!-- <param name="core-db-dsn" value="pgsql://hostaddr=127.0.0.1 dbname=freeswitch user=freeswitch password='' options='-c client_min_messages=NOTICE'" /> -->
<!-- <param name="core-db-dsn" value="dsn:username:password" /> -->
<!--
Allow to specify the sqlite db at a different location (In this example, move it to ramdrive for
better performance on most linux distro (note, you loose the data if you reboot))
-->
<param name="core-db-name" value="/dev/shm/core.db" />
<!-- The system will create all the db schemas automatically, set this to false to avoid this behaviour -->
<!-- <param name="auto-create-schemas" value="true"/> -->
<!-- <param name="auto-clear-sql" value="true"/> -->
<!-- <param name="enable-early-hangup" value="true"/> -->
<!-- <param name="core-dbtype" value="MSSQL"/> -->
<!-- Allow multiple registrations to the same account in the central registration table -->
<!-- <param name="multiple-registrations" value="true"/> -->
</settings>
</configuration>

View File

@ -0,0 +1,450 @@
<include>
<!-- Preprocessor Variables
These are introduced when configuration strings must be consistent across modules.
NOTICE: YOU CAN NOT COMMENT OUT AN X-PRE-PROCESS line, Remove the line instead.
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
YOU SHOULD CHANGE THIS default_password value if you don't want to be subject to any
toll fraud in the future. It's your responsibility to secure your own system.
This default config is used to demonstrate the feature set of FreeSWITCH.
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
-->
<X-PRE-PROCESS cmd="set" data="default_password=1234"/>
<!-- Did you change it yet? -->
<!--
The following variables are set dynamically - calculated if possible by freeswitch - and
are available to the config as $${variable}. You can see their calculated value via fs_cli
by entering eval $${variable}
hostname
local_ip_v4
local_mask_v4
local_ip_v6
switch_serial
base_dir
recordings_dir
sound_prefix
sounds_dir
conf_dir
log_dir
run_dir
db_dir
mod_dir
htdocs_dir
script_dir
temp_dir
grammar_dir
certs_dir
storage_dir
cache_dir
core_uuid
zrtp_enabled
nat_public_addr
nat_private_addr
nat_type
-->
<X-PRE-PROCESS cmd="set" data="sound_prefix=$${sounds_dir}/en/us/callie"/>
<!--
This setting is what sets the default domain FreeSWITCH will use if all else fails.
FreeSWICH will default to $${local_ip_v4} unless changed. Changing this setting does
affect the sip authentication. Please review conf/directory/default.xml for more
information on this topic.
-->
<X-PRE-PROCESS cmd="set" data="local_ip_v4=10.0.3.66"/>
<X-PRE-PROCESS cmd="set" data="domain=$${local_ip_v4}"/>
<X-PRE-PROCESS cmd="set" data="domain_name=$${domain}"/>
<X-PRE-PROCESS cmd="set" data="hold_music=local_stream://moh"/>
<X-PRE-PROCESS cmd="set" data="use_profile=external"/>
<X-PRE-PROCESS cmd="set" data="rtp_sdes_suites=AEAD_AES_256_GCM_8|AEAD_AES_128_GCM_8|AES_CM_256_HMAC_SHA1_80|AES_CM_192_HMAC_SHA1_80|AES_CM_128_HMAC_SHA1_80|AES_CM_256_HMAC_SHA1_32|AES_CM_192_HMAC_SHA1_32|AES_CM_128_HMAC_SHA1_32|AES_CM_128_NULL_AUTH"/>
<!--
Enable ZRTP globally you can override this on a per channel basis
http://wiki.freeswitch.org/wiki/ZRTP (on how to enable zrtp)
-->
<X-PRE-PROCESS cmd="set" data="zrtp_secure_media=true"/>
<!--
NOTICE: When using SRTP it's critical that you do not offer or accept
variable bit rate codecs, doing so would leak information and possibly
compromise your SRTP stream. (FS-6404)
Supported SRTP Crypto Suites:
AEAD_AES_256_GCM_8
____________________________________________________________________________
This algorithm is identical to AEAD_AES_256_GCM (see Section 5.2 of
[RFC5116]), except that the tag length, t, is 8, and an
authentication tag with a length of 8 octets (64 bits) is used.
An AEAD_AES_256_GCM_8 ciphertext is exactly 8 octets longer than its
corresponding plaintext.
AEAD_AES_128_GCM_8
____________________________________________________________________________
This algorithm is identical to AEAD_AES_128_GCM (see Section 5.1 of
[RFC5116]), except that the tag length, t, is 8, and an
authentication tag with a length of 8 octets (64 bits) is used.
An AEAD_AES_128_GCM_8 ciphertext is exactly 8 octets longer than its
corresponding plaintext.
AES_CM_256_HMAC_SHA1_80 | AES_CM_192_HMAC_SHA1_80 | AES_CM_128_HMAC_SHA1_80
____________________________________________________________________________
AES_CM_128_HMAC_SHA1_80 is the SRTP default AES Counter Mode cipher
and HMAC-SHA1 message authentication with an 80-bit authentication
tag. The master-key length is 128 bits and has a default lifetime of
a maximum of 2^48 SRTP packets or 2^31 SRTCP packets, whichever comes
first.
AES_CM_256_HMAC_SHA1_32 | AES_CM_192_HMAC_SHA1_32 | AES_CM_128_HMAC_SHA1_32
____________________________________________________________________________
This crypto-suite is identical to AES_CM_128_HMAC_SHA1_80 except that
the authentication tag is 32 bits. The length of the base64-decoded key and
salt value for this crypto-suite MUST be 30 octets i.e., 240 bits; otherwise,
the crypto attribute is considered invalid.
AES_CM_128_NULL_AUTH
____________________________________________________________________________
The SRTP default cipher (AES-128 Counter Mode), but to use no authentication
method. This policy is NOT RECOMMENDED unless it is unavoidable; see
Section 7.5 of [RFC3711].
SRTP variables that modify behaviors based on direction/leg:
rtp_secure_media
____________________________________________________________________________
possible values:
mandatory - Accept/Offer SAVP negotiation ONLY
optional - Accept/Offer SAVP/AVP with SAVP preferred
forbidden - More useful for inbound to deny SAVP negotiation
false - implies forbidden
true - implies mandatory
default if not set is accept SAVP inbound if offered.
rtp_secure_media_inbound | rtp_secure_media_outbound
____________________________________________________________________________
This is the same as rtp_secure_media, but would apply to either inbound
or outbound offers specifically.
How to specify crypto suites:
____________________________________________________________________________
By default without specifying any crypto suites FreeSWITCH will offer
crypto suites from strongest to weakest accepting the strongest each
endpoint has in common. If you wish to force specific crypto suites you
can do so by appending the suites in a comma separated list in the order
that you wish to offer them in.
Examples:
rtp_secure_media=mandatory:AES_CM_256_HMAC_SHA1_80,AES_CM_256_HMAC_SHA1_32
rtp_secure_media=true:AES_CM_256_HMAC_SHA1_80,AES_CM_256_HMAC_SHA1_32
rtp_secure_media=optional:AES_CM_256_HMAC_SHA1_80
rtp_secure_media=true:AES_CM_256_HMAC_SHA1_80
Additionally you can narrow this down on either inbound or outbound by
specifying as so:
rtp_secure_media_inbound=true:AEAD_AES_256_GCM_8
rtp_secure_media_inbound=mandatory:AEAD_AES_256_GCM_8
rtp_secure_media_outbound=true:AEAD_AES_128_GCM_8
rtp_secure_media_outbound=optional:AEAD_AES_128_GCM_8
rtp_secure_media_suites
____________________________________________________________________________
Optionaly you can use rtp_secure_media_suites to dictate the suite list
and only use rtp_secure_media=[optional|mandatory|false|true] without having
to dictate the suite list with the rtp_secure_media* variables.
-->
<!--
Examples of codec options: (module must be compiled and loaded)
codecname[@8000h|16000h|32000h[@XXi]]
XX is the frame size must be multples allowed for the codec
FreeSWITCH can support 10-120ms on some codecs.
We do not support exceeding the MTU of the RTP packet.
iLBC@30i - iLBC using mode=30 which will win in all cases.
DVI4@8000h@20i - IMA ADPCM 8kHz using 20ms ptime. (multiples of 10)
DVI4@16000h@40i - IMA ADPCM 16kHz using 40ms ptime. (multiples of 10)
speex@8000h@20i - Speex 8kHz using 20ms ptime.
speex@16000h@20i - Speex 16kHz using 20ms ptime.
speex@32000h@20i - Speex 32kHz using 20ms ptime.
BV16 - BroadVoice 16kb/s narrowband, 8kHz
BV32 - BroadVoice 32kb/s wideband, 16kHz
G7221@16000h - G722.1 16kHz (aka Siren 7)
G7221@32000h - G722.1C 32kHz (aka Siren 14)
CELT@32000h - CELT 32kHz, only 10ms supported
CELT@48000h - CELT 48kHz, only 10ms supported
GSM@40i - GSM 8kHz using 40ms ptime. (GSM is done in multiples of 20, Default is 20ms)
G722 - G722 16kHz using default 20ms ptime. (multiples of 10)
PCMU - G711 8kHz ulaw using default 20ms ptime. (multiples of 10)
PCMA - G711 8kHz alaw using default 20ms ptime. (multiples of 10)
G726-16 - G726 16kbit adpcm using default 20ms ptime. (multiples of 10)
G726-24 - G726 24kbit adpcm using default 20ms ptime. (multiples of 10)
G726-32 - G726 32kbit adpcm using default 20ms ptime. (multiples of 10)
G726-40 - G726 40kbit adpcm using default 20ms ptime. (multiples of 10)
AAL2-G726-16 - Same as G726-16 but using AAL2 packing. (multiples of 10)
AAL2-G726-24 - Same as G726-24 but using AAL2 packing. (multiples of 10)
AAL2-G726-32 - Same as G726-32 but using AAL2 packing. (multiples of 10)
AAL2-G726-40 - Same as G726-40 but using AAL2 packing. (multiples of 10)
LPC - LPC10 using 90ms ptime (only supports 90ms at this time in FreeSWITCH)
L16 - L16 isn't recommended for VoIP but you can do it. L16 can exceed the MTU rather quickly.
These are the passthru audio codecs:
G729 - G729 in passthru mode. (mod_g729)
G723 - G723.1 in passthru mode. (mod_g723_1)
AMR - AMR in passthru mode. (mod_amr)
These are the passthru video codecs: (mod_h26x)
H261 - H.261 Video
H263 - H.263 Video
H263-1998 - H.263-1998 Video
H263-2000 - H.263-2000 Video
H264 - H.264 Video
RTP Dynamic Payload Numbers currently used in FreeSWITCH and what for.
96 - AMR
97 - iLBC (30)
98 - iLBC (20)
99 - Speex 8kHz, 16kHz, 32kHz
100 -
101 - telephone-event
102 -
103 -
104 -
105 -
106 - BV16
107 - G722.1 (16kHz)
108 -
109 -
110 -
111 -
112 -
113 -
114 - CELT 32kHz, 48kHz
115 - G722.1C (32kHz)
116 -
117 - SILK 8kHz
118 - SILK 12kHz
119 - SILK 16kHz
120 - SILK 24kHz
121 - AAL2-G726-40 && G726-40
122 - AAL2-G726-32 && G726-32
123 - AAL2-G726-24 && G726-24
124 - AAL2-G726-16 && G726-16
125 -
126 -
127 - BV32
-->
<X-PRE-PROCESS cmd="set" data="global_codec_prefs=OPUS,speex@16000h@20i,speex@8000h@20i,G722,PCMU,PCMA"/>
<X-PRE-PROCESS cmd="set" data="outbound_codec_prefs=OPUS,speex@16000h@20i,G722,PCMU,PCMA"/>
<!--
xmpp_client_profile and xmpp_server_profile
xmpp_client_profile can be any string.
xmpp_server_profile is appended to "dingaling_" to form the database name
containing the "subscriptions" table.
used by: dingaling.conf.xml enum.conf.xml
-->
<X-PRE-PROCESS cmd="set" data="xmpp_client_profile=xmppc"/>
<X-PRE-PROCESS cmd="set" data="xmpp_server_profile=xmpps"/>
<!--
THIS IS ONLY USED FOR DINGALING
bind_server_ip
Can be an ip address, a dns name, or "auto".
This determines an ip address available on this host to bind.
If you are separating RTP and SIP traffic, you will want to have
use different addresses where this variable appears.
Used by: dingaling.conf.xml
-->
<X-PRE-PROCESS cmd="set" data="bind_server_ip=auto"/>
<!-- NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
If you're going to load test FreeSWITCH please input real IP addresses
for external_rtp_ip and external_sip_ip
-->
<!-- external_rtp_ip
Can be an one of:
ip address: "12.34.56.78"
a stun server lookup: "stun:stun.server.com"
a DNS name: "host:host.server.com"
where fs.mydomain.com is a DNS A record-useful when fs is on
a dynamic IP address, and uses a dynamic DNS updater.
If unspecified, the bind_server_ip value is used.
Used by: sofia.conf.xml dingaling.conf.xml
-->
<X-PRE-PROCESS cmd="set" data="external_rtp_ip=stun:stun.l.google.com:19302"/>
<!-- external_sip_ip
Used as the public IP address for SDP.
Can be an one of:
ip address: "12.34.56.78"
a stun server lookup: "stun:stun.server.com"
a DNS name: "host:host.server.com"
where fs.mydomain.com is a DNS A record-useful when fs is on
a dynamic IP address, and uses a dynamic DNS updater.
If unspecified, the bind_server_ip value is used.
Used by: sofia.conf.xml dingaling.conf.xml
-->
<X-PRE-PROCESS cmd="set" data="external_sip_ip=stun:stun.l.google.com:19302"/>
<!-- unroll-loops
Used to turn on sip loopback unrolling.
-->
<X-PRE-PROCESS cmd="set" data="unroll_loops=true"/>
<!-- outbound_caller_id and outbound_caller_name
The caller ID telephone number we should use when calling out.
Used by: conference.conf.xml and user directory for default
outbound callerid name and number.
-->
<X-PRE-PROCESS cmd="set" data="outbound_caller_name=FreeSWITCH"/>
<X-PRE-PROCESS cmd="set" data="outbound_caller_id=0000000000"/>
<!-- various debug and defaults -->
<X-PRE-PROCESS cmd="set" data="call_debug=false"/>
<X-PRE-PROCESS cmd="set" data="console_loglevel=info"/>
<X-PRE-PROCESS cmd="set" data="default_areacode=918"/>
<X-PRE-PROCESS cmd="set" data="default_country=US"/>
<!-- if false or undefined, the destination number is included in presence NOTIFY dm:note.
if true, the destination number is not included -->
<X-PRE-PROCESS cmd="set" data="presence_privacy=false"/>
<X-PRE-PROCESS cmd="set" data="au-ring=%(400,200,383,417);%(400,2000,383,417)"/>
<X-PRE-PROCESS cmd="set" data="be-ring=%(1000,3000,425)"/>
<X-PRE-PROCESS cmd="set" data="ca-ring=%(2000,4000,440,480)"/>
<X-PRE-PROCESS cmd="set" data="cn-ring=%(1000,4000,450)"/>
<X-PRE-PROCESS cmd="set" data="cy-ring=%(1500,3000,425)"/>
<X-PRE-PROCESS cmd="set" data="cz-ring=%(1000,4000,425)"/>
<X-PRE-PROCESS cmd="set" data="de-ring=%(1000,4000,425)"/>
<X-PRE-PROCESS cmd="set" data="dk-ring=%(1000,4000,425)"/>
<X-PRE-PROCESS cmd="set" data="dz-ring=%(1500,3500,425)"/>
<X-PRE-PROCESS cmd="set" data="eg-ring=%(2000,1000,475,375)"/>
<X-PRE-PROCESS cmd="set" data="es-ring=%(1500,3000,425)"/>
<X-PRE-PROCESS cmd="set" data="fi-ring=%(1000,4000,425)"/>
<X-PRE-PROCESS cmd="set" data="fr-ring=%(1500,3500,440)"/>
<X-PRE-PROCESS cmd="set" data="hk-ring=%(400,200,440,480);%(400,3000,440,480)"/>
<X-PRE-PROCESS cmd="set" data="hu-ring=%(1250,3750,425)"/>
<X-PRE-PROCESS cmd="set" data="il-ring=%(1000,3000,400)"/>
<X-PRE-PROCESS cmd="set" data="in-ring=%(400,200,425,375);%(400,2000,425,375)"/>
<X-PRE-PROCESS cmd="set" data="jp-ring=%(1000,2000,420,380)"/>
<X-PRE-PROCESS cmd="set" data="ko-ring=%(1000,2000,440,480)"/>
<X-PRE-PROCESS cmd="set" data="pk-ring=%(1000,2000,400)"/>
<X-PRE-PROCESS cmd="set" data="pl-ring=%(1000,4000,425)"/>
<X-PRE-PROCESS cmd="set" data="ro-ring=%(1850,4150,475,425)"/>
<X-PRE-PROCESS cmd="set" data="rs-ring=%(1000,4000,425)"/>
<X-PRE-PROCESS cmd="set" data="ru-ring=%(800,3200,425)"/>
<X-PRE-PROCESS cmd="set" data="sa-ring=%(1200,4600,425)"/>
<X-PRE-PROCESS cmd="set" data="tr-ring=%(2000,4000,450)"/>
<X-PRE-PROCESS cmd="set" data="uk-ring=%(400,200,400,450);%(400,2000,400,450)"/>
<X-PRE-PROCESS cmd="set" data="us-ring=%(2000,4000,440,480)"/>
<X-PRE-PROCESS cmd="set" data="bong-ring=v=-7;%(100,0,941.0,1477.0);v=-7;>=2;+=.1;%(1400,0,350,440)"/>
<X-PRE-PROCESS cmd="set" data="beep=%(1000,0,640)"/>
<X-PRE-PROCESS cmd="set" data="sit=%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)"/>
<!--
Digits Dialed filter: (FS-6940)
The digits stream may contain valid credit card numbers or social security numbers, These digit
filters will allow you to make a valant effort to stamp out sensitive information for
PCI/HIPPA compliance. (see xml_cdr dialed_digits)
df_us_ssn = US Social Security Number pattern
df_us_luhn = Visa, MasterCard, American Express, Diners Club, Discover and JCB
-->
<X-PRE-PROCESS cmd="set" data="df_us_ssn=(?!219099999|078051120)(?!666|000|9\d{2})\d{3}(?!00)\d{2}(?!0{4})\d{4}"/>
<X-PRE-PROCESS cmd="set" data="df_luhn=?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|6(?:011|5[0-9]{2})[0-9]{12}|(?:2131|1800|35\d{3})\d{11}"/>
<!-- change XX to X below to enable -->
<XX-PRE-PROCESS cmd="set" data="digits_dialed_filter=(($${df_luhn})|($${df_us_ssn}))"/>
<!--
Setting up your default sip provider is easy.
Below are some values that should work in most cases.
These are for conf/directory/default/example.com.xml
-->
<X-PRE-PROCESS cmd="set" data="default_provider=example.com"/>
<X-PRE-PROCESS cmd="set" data="default_provider_username=joeuser"/>
<X-PRE-PROCESS cmd="set" data="default_provider_password=password"/>
<X-PRE-PROCESS cmd="set" data="default_provider_from_domain=example.com"/>
<!-- true or false -->
<X-PRE-PROCESS cmd="set" data="default_provider_register=false"/>
<X-PRE-PROCESS cmd="set" data="default_provider_contact=5000"/>
<!--
SIP and TLS settings. http://wiki.freeswitch.org/wiki/Tls
valid options: sslv2,sslv3,sslv23,tlsv1,tlsv1.1,tlsv1.2
default: tlsv1,tlsv1.1,tlsv1.2
-->
<X-PRE-PROCESS cmd="set" data="sip_tls_version=tlsv1,tlsv1.1,tlsv1.2"/>
<!--
TLS cipher suite: default ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH
The actual ciphers supported will change per platform.
openssl ciphers -v 'ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH'
Will show you what is available in your verion of openssl.
-->
<X-PRE-PROCESS cmd="set" data="sip_tls_ciphers=ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"/>
<!-- Internal SIP Profile -->
<X-PRE-PROCESS cmd="set" data="internal_auth_calls=true"/>
<X-PRE-PROCESS cmd="set" data="internal_sip_port=5090"/>
<X-PRE-PROCESS cmd="set" data="internal_tls_port=5061"/>
<X-PRE-PROCESS cmd="set" data="internal_ssl_enable=false"/>
<!-- External SIP Profile -->
<X-PRE-PROCESS cmd="set" data="external_auth_calls=false"/>
<X-PRE-PROCESS cmd="set" data="external_sip_port=5060"/>
<X-PRE-PROCESS cmd="set" data="external_tls_port=5081"/>
<X-PRE-PROCESS cmd="set" data="external_ssl_enable=false"/>
<!-- Video Settings -->
<!-- Setting the max bandwdith -->
<X-PRE-PROCESS cmd="set" data="rtp_video_max_bandwidth_in=1mb"/>
<X-PRE-PROCESS cmd="set" data="rtp_video_max_bandwidth_out=1mb"/>
<!-- WebRTC Video -->
<!-- Suppress CNG for WebRTC Audio -->
<X-PRE-PROCESS cmd="set" data="suppress_cng=true"/>
<!-- Enable liberal DTMF for those that can't get it right -->
<X-PRE-PROCESS cmd="set" data="rtp_liberal_dtmf=true"/>
<!-- Helps with WebRTC Audio -->
<!-- Stock Video Avatars -->
<X-PRE-PROCESS cmd="set" data="video_mute_png=$${images_dir}/default-mute.png"/>
<X-PRE-PROCESS cmd="set" data="video_no_avatar_png=$${images_dir}/default-avatar.png"/>
</include>

View File

@ -0,0 +1,63 @@
<configuration name="verto.conf" description="HTML5 Verto Endpoint">
<settings>
<param name="debug" value="0"/>
<!-- seconds to wait before hanging up a disconnected channel -->
<!-- <param name="detach-timeout-sec" value="120"/> -->
<!-- enable broadcasting all FreeSWITCH events in Verto -->
<!-- <param name="enable-fs-events" value="false"/> -->
<!-- enable broadcasting FreeSWITCH presence events in Verto -->
<!-- <param name="enable-presence" value="true"/> -->
</settings>
<profiles>
<profile name="public-v4">
<param name="bind-local" value="$${local_ip_v4}:8081"/>
<param name="bind-local" value="$${local_ip_v4}:8082" secure="true"/>
<param name="force-register-domain" value="$${domain}"/>
<param name="secure-combined" value="$${certs_dir}/wss.pem"/>
<param name="secure-chain" value="$${certs_dir}/wss.pem"/>
<param name="userauth" value="true"/>
<!-- setting this to true will allow anyone to register even with no account so use with care -->
<param name="blind-reg" value="false"/>
<param name="mcast-ip" value="224.1.1.1"/>
<param name="mcast-port" value="1337"/>
<param name="rtp-ip" value="$${local_ip_v4}"/>
<!-- <param name="ext-rtp-ip" value=""/> -->
<param name="local-network" value="localnet.auto"/>
<param name="outbound-codec-string" value="opus,vp8"/>
<param name="inbound-codec-string" value="opus,vp8"/>
<param name="apply-candidate-acl" value="localnet.auto"/>
<param name="apply-candidate-acl" value="wan_v4.auto"/>
<param name="apply-candidate-acl" value="rfc1918.auto"/>
<param name="apply-candidate-acl" value="any_v4.auto"/>
<param name="timer-name" value="soft"/>
</profile>
<profile name="public-v6">
<param name="bind-local" value="[$${local_ip_v6}]:8081"/>
<param name="bind-local" value="[$${local_ip_v6}]:8082" secure="true"/>
<param name="force-register-domain" value="$${domain}"/>
<param name="secure-combined" value="$${certs_dir}/wss.pem"/>
<param name="secure-chain" value="$${certs_dir}/wss.pem"/>
<param name="userauth" value="true"/>
<!-- setting this to true will allow anyone to register even with no account so use with care -->
<param name="blind-reg" value="false"/>
<param name="rtp-ip" value="$${local_ip_v6}"/>
<!-- <param name="ext-rtp-ip" value=""/> -->
<param name="outbound-codec-string" value="opus,vp8"/>
<param name="inbound-codec-string" value="opus,vp8"/>
<param name="apply-candidate-acl" value="wan_v6.auto"/>
<param name="apply-candidate-acl" value="rfc1918.auto"/>
<param name="apply-candidate-acl" value="any_v6.auto"/>
<param name="apply-candidate-acl" value="wan_v4.auto"/>
<param name="apply-candidate-acl" value="any_v4.auto"/>
<param name="timer-name" value="soft"/>
</profile>
</profiles>
</configuration>

View File

@ -0,0 +1,28 @@
From d8224580afd2b8dd6a685ac10a79ae223acf874a Mon Sep 17 00:00:00 2001
From: Andrey Volk <andywolk@gmail.com>
Date: Thu, 31 Oct 2019 20:11:36 +0400
Subject: [PATCH] [sofia-sip] Fix crash in nta outgoing_create when NULL queue.
---
libs/sofia-sip/.update | 2 +-
libs/sofia-sip/libsofia-sip-ua/nta/nta.c | 7 ++++++-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c
index 9b2e295007..8f5eb3b82e 100644
--- a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c
+++ b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c
@@ -8098,7 +8098,12 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent,
return retval;
}
- assert(orq->orq_queue);
+ if (!orq->orq_queue) {
+ SU_DEBUG_5(("nta outgoing create: orq->orq_queue is NULL.\n" VA_NONE));
+ outgoing_free(orq);
+ return NULL;
+ }
+
outgoing_insert(agent, orq);

View File

@ -0,0 +1,17 @@
diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c
index 9b2e295..6665ec7 100644
--- a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c
+++ b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c
@@ -10869,7 +10869,10 @@ void outgoing_answer_a(sres_context_t *orq, sres_query_t *q,
sres_free_answers(orq->orq_agent->sa_resolver, answers);
- outgoing_query_results(orq, sq, results, found);
+ if (results)
+ outgoing_query_results(orq, sq, results, found);
+ else if (!q)
+ outgoing_resolving_error(orq, SIPDNS_503_ERROR);
}
/** Store A/AAAA query results */

View File

@ -0,0 +1,12 @@
--- src/mod/applications/mod_conference/conference_loop.c 2021-04-19 23:56:18.636116836 +0000
+++ src/mod/applications/mod_conference/conference_loop-new.c 2021-04-20 00:23:16.700700282 +0000
@@ -1193,7 +1193,7 @@
member->last_score = member->score;
- if ((switch_channel_test_flag(channel, CF_VIDEO) || member->avatar_png_img) && (member->id == member->conference->floor_holder)) {
+ if (member->id == member->conference->floor_holder) {
if (member->id != member->conference->video_floor_holder &&
(member->floor_packets > member->conference->video_floor_packets || member->energy_level == 0)) {
conference_video_set_floor_holder(member->conference, member, SWITCH_FALSE);

View File

@ -0,0 +1,2 @@
d /var/run/freeswitch 0755 freeswitch freeswitch - -

View File

@ -0,0 +1,58 @@
;;;;; Author: Travis Cross <tc@traviscross.com>
[Unit]
Description=freeswitch
After=syslog.target network.target local-fs.target
[Service]
; service
Type=forking
PIDFile=/opt/freeswitch/var/run/freeswitch/freeswitch.pid
Environment="DAEMON_OPTS=-nonat"
EnvironmentFile=-/etc/default/freeswitch
ExecStart=/opt/freeswitch/bin/freeswitch -u freeswitch -g daemon -ncwait $DAEMON_OPTS
TimeoutSec=45s
Restart=always
; exec
WorkingDirectory=/opt/freeswitch
User=freeswitch
Group=daemon
LimitCORE=infinity
LimitNOFILE=100000
LimitNPROC=60000
LimitSTACK=250000
LimitRTPRIO=infinity
LimitRTTIME=7000000
IOSchedulingClass=realtime
IOSchedulingPriority=2
#CPUSchedulingPolicy=rr
CPUSchedulingPriority=89
#UMask=0007
; alternatives which you can enforce by placing a unit drop-in into
; /etc/systemd/system/freeswitch.service.d/*.conf:
;
; User=freeswitch
; Group=freeswitch
; ExecStart=
; ExecStart=/usr/bin/freeswitch -ncwait -nonat -rp
;
; empty ExecStart is required to flush the list.
;
; if your filesystem supports extended attributes, execute
; setcap 'cap_net_bind_service,cap_sys_nice=+ep' /usr/bin/freeswitch
; this will also allow socket binding on low ports
;
; otherwise, remove the -rp option from ExecStart and
; add these lines to give real-time priority to the process:
;
; PermissionsStartOnly=true
; ExecStartPost=/bin/chrt -f -p 1 $MAINPID
;
; execute "systemctl daemon-reload" after editing the unit files.
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,58 @@
;;;;; Author: Travis Cross <tc@traviscross.com>
[Unit]
Description=freeswitch
After=syslog.target network.target local-fs.target
[Service]
; service
Type=forking
PIDFile=/opt/freeswitch/var/run/freeswitch/freeswitch.pid
Environment="DAEMON_OPTS=-nonat"
EnvironmentFile=-/etc/default/freeswitch
ExecStart=/opt/freeswitch/bin/freeswitch -u freeswitch -g daemon -ncwait $DAEMON_OPTS
TimeoutSec=45s
Restart=always
; exec
WorkingDirectory=/opt/freeswitch
User=freeswitch
Group=daemon
LimitCORE=infinity
LimitNOFILE=100000
LimitNPROC=60000
LimitSTACK=250000
LimitRTPRIO=infinity
LimitRTTIME=7000000
IOSchedulingClass=realtime
IOSchedulingPriority=2
CPUSchedulingPolicy=rr
CPUSchedulingPriority=89
#UMask=0007
; alternatives which you can enforce by placing a unit drop-in into
; /etc/systemd/system/freeswitch.service.d/*.conf:
;
; User=freeswitch
; Group=freeswitch
; ExecStart=
; ExecStart=/usr/bin/freeswitch -ncwait -nonat -rp
;
; empty ExecStart is required to flush the list.
;
; if your filesystem supports extended attributes, execute
; setcap 'cap_net_bind_service,cap_sys_nice=+ep' /usr/bin/freeswitch
; this will also allow socket binding on low ports
;
; otherwise, remove the -rp option from ExecStart and
; add these lines to give real-time priority to the process:
;
; PermissionsStartOnly=true
; ExecStartPost=/bin/chrt -f -p 1 $MAINPID
;
; execute "systemctl daemon-reload" after editing the unit files.
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,58 @@
;;;;; Author: Travis Cross <tc@traviscross.com>
[Unit]
Description=freeswitch
After=syslog.target network.target local-fs.target
[Service]
; service
Type=forking
PIDFile=/opt/freeswitch/var/run/freeswitch/freeswitch.pid
Environment="DAEMON_OPTS=-nonat"
EnvironmentFile=-/etc/default/freeswitch
ExecStart=/opt/freeswitch/bin/freeswitch -u freeswitch -g daemon -ncwait $DAEMON_OPTS
TimeoutSec=45s
Restart=always
; exec
WorkingDirectory=/opt/freeswitch
User=freeswitch
Group=daemon
LimitCORE=infinity
LimitNOFILE=100000
LimitNPROC=60000
LimitSTACK=250000
LimitRTPRIO=infinity
LimitRTTIME=7000000
IOSchedulingClass=realtime
IOSchedulingPriority=2
#CPUSchedulingPolicy=rr
CPUSchedulingPriority=89
#UMask=0007
; alternatives which you can enforce by placing a unit drop-in into
; /etc/systemd/system/freeswitch.service.d/*.conf:
;
; User=freeswitch
; Group=freeswitch
; ExecStart=
; ExecStart=/usr/bin/freeswitch -ncwait -nonat -rp
;
; empty ExecStart is required to flush the list.
;
; if your filesystem supports extended attributes, execute
; setcap 'cap_net_bind_service,cap_sys_nice=+ep' /usr/bin/freeswitch
; this will also allow socket binding on low ports
;
; otherwise, remove the -rp option from ExecStart and
; add these lines to give real-time priority to the process:
;
; PermissionsStartOnly=true
; ExecStartPost=/bin/chrt -f -p 1 $MAINPID
;
; execute "systemctl daemon-reload" after editing the unit files.
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,58 @@
;;;;; Author: Travis Cross <tc@traviscross.com>
[Unit]
Description=freeswitch
After=syslog.target network.target local-fs.target
[Service]
; service
Type=forking
PIDFile=/opt/freeswitch/var/run/freeswitch/freeswitch.pid
Environment="DAEMON_OPTS=-nonat"
EnvironmentFile=-/etc/default/freeswitch
ExecStart=/opt/freeswitch/bin/freeswitch -u freeswitch -g daemon -ncwait $DAEMON_OPTS
TimeoutSec=45s
Restart=always
; exec
WorkingDirectory=/opt/freeswitch
User=freeswitch
Group=daemon
LimitCORE=infinity
LimitNOFILE=100000
LimitNPROC=60000
LimitSTACK=250000
LimitRTPRIO=infinity
LimitRTTIME=7000000
IOSchedulingClass=realtime
IOSchedulingPriority=2
CPUSchedulingPolicy=rr
CPUSchedulingPriority=89
#UMask=0007
; alternatives which you can enforce by placing a unit drop-in into
; /etc/systemd/system/freeswitch.service.d/*.conf:
;
; User=freeswitch
; Group=freeswitch
; ExecStart=
; ExecStart=/usr/bin/freeswitch -ncwait -nonat -rp
;
; empty ExecStart is required to flush the list.
;
; if your filesystem supports extended attributes, execute
; setcap 'cap_net_bind_service,cap_sys_nice=+ep' /usr/bin/freeswitch
; this will also allow socket binding on low ports
;
; otherwise, remove the -rp option from ExecStart and
; add these lines to give real-time priority to the process:
;
; PermissionsStartOnly=true
; ExecStartPost=/bin/chrt -f -p 1 $MAINPID
;
; execute "systemctl daemon-reload" after editing the unit files.
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,4 @@
#!/bin/bash
/opt/freeswitch/bin/fs_cli -p $(xmlstarlet sel -t -m 'configuration/settings/param[@name="password"]' -v @value /opt/freeswitch/etc/freeswitch/autoload_configs/event_socket.conf.xml)

View File

@ -0,0 +1,213 @@
diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c
index 9b2e295..572f5f7 100644
--- a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c
+++ b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c
@@ -7841,6 +7841,8 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent,
tagi_t const *t;
tport_t *override_tport = NULL;
+ SU_DEBUG_1(("nta: outgoing_create: ======= START ========= \n" VA_NONE));
+
if (!agent->sa_tport_ip6)
res_order = nta_res_ip4_only;
else if (!agent->sa_tport_ip4)
@@ -7935,6 +7937,8 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent,
if (cc)
orq->orq_cc = nta_compartment_ref(cc);
+ SU_DEBUG_3(("nta: outgoing_create: outgoing_features\n" VA_NONE));
+
/* Add supported features */
outgoing_features(agent, orq, msg, sip, ta_args(ta));
@@ -8014,7 +8018,10 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent,
orq->orq_branch = branch;
orq->orq_via_branch = branch;
+ SU_DEBUG_3(("nta: outgoing_create: orq_method\n" VA_NONE));
+
if (orq->orq_method == sip_method_ack) {
+ SU_DEBUG_3(("nta: outgoing_create: orq_method == sip_method_ack \n" VA_NONE));
/* Find the original INVITE which we are ACKing */
if (ack_branch != NULL && ack_branch != NONE) {
if (su_casenmatch(ack_branch, "branch=", 7))
@@ -8046,7 +8053,7 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent,
}
}
else {
- SU_DEBUG_1(("outgoing_create: ACK without INVITE\n" VA_NONE));
+ SU_DEBUG_1(("nta: outgoing_create: ACK without INVITE\n" VA_NONE));
assert(!"INVITE found for ACK");
}
}
@@ -8062,13 +8069,15 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent,
orq->orq_sips = su_casematch(scheme, "sips");
if (invalid < 0 || !orq->orq_branch || msg_serialize(msg, (void *)sip) < 0) {
- SU_DEBUG_3(("nta outgoing create: %s\n",
+ SU_DEBUG_3(("nta: outgoing_create: %s\n",
invalid < 0 ? "invalid URI" :
!orq->orq_branch ? "no branch" : "invalid message"));
outgoing_free(orq);
return NULL;
}
+ SU_DEBUG_1(("nta: outgoing_create: committed in sending the transaction \n" VA_NONE));
+
/* Now we are committed in sending the transaction */
orq->orq_request = msg;
agent->sa_stats->as_client_tr++;
@@ -8098,10 +8107,19 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent,
return retval;
}
+ SU_DEBUG_1(("nta: outgoing_create:checking orq_queue \n" VA_NONE));
+
+ if (!orq->orq_queue)
+ SU_DEBUG_5(("nta: outgoing_create: orq->orq_queue NULL.\n" VA_NONE));
+ else
+ SU_DEBUG_5(("nta: outgoing_create: orq->orq_queue NOT NULL.\n" VA_NONE));
+
assert(orq->orq_queue);
outgoing_insert(agent, orq);
+ SU_DEBUG_1(("nta: outgoing_create: ======= END ========= \n" VA_NONE));
+
return orq;
}
@@ -8604,6 +8622,11 @@ outgoing_queue_adjust(nta_agent_t *sa,
su_inline int
outgoing_is_queued(nta_outgoing_t const *orq)
{
+ if (!orq->orq_queue)
+ SU_DEBUG_5(("outgoing_is_queued: orq->orq_queue is NULL.\n" VA_NONE));
+ else
+ SU_DEBUG_5(("outgoing_is_queued: orq->orq_queue is NOT NULL.\n" VA_NONE));
+
return orq && orq->orq_queue;
}
@@ -8618,6 +8641,7 @@ outgoing_queue(outgoing_queue_t *queue,
nta_outgoing_t *orq)
{
if (orq->orq_queue == queue) {
+ SU_DEBUG_5(("outgoing_queue: orq->orq_queue == queue.\n" VA_NONE));
//assert(queue->q_timeout == 0);
return;
}
@@ -8629,6 +8653,8 @@ outgoing_queue(outgoing_queue_t *queue,
orq->orq_timeout = set_timeout(orq->orq_agent, queue->q_timeout);
+ SU_DEBUG_5(("outgoing_queue: orq->orq_queue = queue.\n" VA_NONE));
+
orq->orq_queue = queue;
orq->orq_prev = queue->q_tail;
*queue->q_tail = orq;
@@ -8642,14 +8668,19 @@ outgoing_queue(outgoing_queue_t *queue,
su_inline
void outgoing_remove(nta_outgoing_t *orq)
{
+ SU_DEBUG_5(("outgoing_remove: orq->orq_queue = queue.\n" VA_NONE));
assert(outgoing_is_queued(orq));
assert(orq->orq_queue->q_length > 0);
+ SU_DEBUG_5(("outgoing_remove: orq->orq_queue queued and gt 0 \n" VA_NONE));
+
if ((*orq->orq_prev = orq->orq_next))
orq->orq_next->orq_prev = orq->orq_prev;
else
orq->orq_queue->q_tail = orq->orq_prev;
+ SU_DEBUG_5(("outgoing_remove: orq->orq_queue NULLing \n" VA_NONE));
+
orq->orq_queue->q_length--;
orq->orq_next = NULL;
orq->orq_prev = NULL;
@@ -9077,10 +9108,15 @@ outgoing_complete(nta_outgoing_t *orq)
}
if (orq->orq_method == sip_method_invite) {
- if (orq->orq_queue != orq->orq_agent->sa_out.inv_completed)
+ SU_DEBUG_5(("outgoing_complete: orq->orq_method == sip_method_invite \n" VA_NONE));
+
+ if (orq->orq_queue != orq->orq_agent->sa_out.inv_completed) {
+ SU_DEBUG_5(("outgoing_complete: orq->orq_queue != orq->orq_agent->sa_out.inv_completed \n" VA_NONE));
outgoing_queue(orq->orq_agent->sa_out.inv_completed, orq); /* Timer D */
+ }
}
else {
+ SU_DEBUG_5(("outgoing_complete: orq->orq_agent->sa_out.completed \n" VA_NONE));
outgoing_queue(orq->orq_agent->sa_out.completed, orq); /* Timer K */
}
@@ -9383,9 +9419,11 @@ int outgoing_recv(nta_outgoing_t *_orq,
orq->orq_status = status;
if (original->orq_queue == sa->sa_out.inv_calling) {
+ SU_DEBUG_5(("outgoing_recv: original->orq_queue == sa->sa_out.inv_calling.\n" VA_NONE));
outgoing_queue(sa->sa_out.inv_proceeding, original);
}
else if (original->orq_queue == sa->sa_out.inv_proceeding) {
+ SU_DEBUG_5(("outgoing_recv: original->orq_queue == sa->sa_out.inv_proceeding \n" VA_NONE));
if (sa->sa_out.inv_proceeding->q_timeout) {
outgoing_remove(original);
outgoing_queue(sa->sa_out.inv_proceeding, original);
@@ -9442,6 +9480,7 @@ int outgoing_recv(nta_outgoing_t *_orq,
/* Non-INVITE */
if (orq->orq_queue == sa->sa_out.trying ||
orq->orq_queue == sa->sa_out.resolving) {
+ SU_DEBUG_5(("outgoing_recv: sa->sa_out.trying || sa->sa_out.resolving\n" VA_NONE));
/* hacked by freeswitch, this is being hit by options 404 status with 404 orq->orq_status and orq_destroyed = 1, orq_completed = 1 */
/* assert(orq->orq_status < 200); */
if (orq->orq_status >= 200) {msg_destroy(msg); return 0;}
@@ -9468,6 +9507,7 @@ int outgoing_recv(nta_outgoing_t *_orq,
}
}
else {
+ SU_DEBUG_5(("outgoing_recv: Already completed or terminated \n" VA_NONE));
/* Already completed or terminated */
assert(orq->orq_queue == sa->sa_out.completed ||
orq->orq_queue == sa->sa_out.terminated);
@@ -9752,8 +9792,10 @@ int outgoing_reply(nta_outgoing_t *orq, int status, char const *phrase,
SU_DEBUG_3(("nta(%p): responding %u %s to ACK!\n",
(void *)orq, status, phrase));
orq->orq_status = status;
- if (orq->orq_queue == NULL)
+ if (orq->orq_queue == NULL) {
+ SU_DEBUG_5(("outgoing_reply: orq->orq_queue == NULL.\n" VA_NONE));
outgoing_trying(orq); /* Timer F */
+ }
return 0;
}
@@ -9768,8 +9810,10 @@ int outgoing_reply(nta_outgoing_t *orq, int status, char const *phrase,
;
else if (orq->orq_queue == NULL ||
orq->orq_queue == orq->orq_agent->sa_out.resolving ||
- orq->orq_queue == orq->orq_agent->sa_out.delayed)
+ orq->orq_queue == orq->orq_agent->sa_out.delayed) {
+ SU_DEBUG_5(("outgoing_reply: orq->orq_queue == NULL || sa_out.resolving || sa_out.delayed.\n" VA_NONE));
outgoing_trying(orq);
+ }
/** Insert a dummy Via header */
if (!orq->orq_prepared) {
diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c
index 7e1dc76..8b27378 100644
--- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c
+++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c
@@ -328,8 +328,8 @@ ssize_t tport_send_stream_ws(tport_t const *self, msg_t *msg,
if (wrote < 0) {
int err = su_errno();
- SU_DEBUG_3(("ws_write_frame: %s\n", strerror(err)));
- size = wrote;
+ SU_DEBUG_3(("ws_write_frame: %s (%ld, %s, wstp_buflen: %ld)\n", strerror(err), (long)wrote, ((wstp->ws.down) ? "DOWN" : "NOT_DOWN"), (long)wstp->wstp_buflen));
+ return -1;
} else {
size = wstp->wstp_buflen;

View File

@ -0,0 +1,168 @@
#applications/mod_abstraction
#applications/mod_av
#applications/mod_avmd
#applications/mod_bert
#applications/mod_blacklist
#applications/mod_callcenter
#applications/mod_cidlookup
#applications/mod_cluechoo
applications/mod_commands
applications/mod_conference
#applications/mod_curl
#applications/mod_cv
applications/mod_db
#applications/mod_directory
#applications/mod_distributor
applications/mod_dptools
#applications/mod_easyroute
applications/mod_enum
applications/mod_esf
#applications/mod_esl
applications/mod_expr
applications/mod_fifo
#applications/mod_fsk
applications/mod_fsv
applications/mod_hash
#applications/mod_hiredis
applications/mod_httapi
#applications/mod_http_cache
#applications/mod_ladspa
#applications/mod_lcr
#applications/mod_memcache
#applications/mod_mongo
#applications/mod_mp4
#applications/mod_mp4v2
#applications/mod_nibblebill
#applications/mod_oreka
#applications/mod_osp
#applications/mod_prefix
#applications/mod_rad_auth
#applications/mod_redis
#applications/mod_rss
applications/mod_sms
#applications/mod_snapshot
#applications/mod_snom
#applications/mod_sonar
#applications/mod_soundtouch
applications/mod_spandsp
#applications/mod_spy
#applications/mod_stress
#applications/mod_translate
applications/mod_valet_parking
#applications/mod_vmd
applications/mod_voicemail
#applications/mod_voicemail_ivr
#asr_tts/mod_cepstral
#asr_tts/mod_flite
#asr_tts/mod_pocketsphinx
#asr_tts/mod_tts_commandline
#asr_tts/mod_unimrcp
codecs/mod_amr
#codecs/mod_amrwb
codecs/mod_b64
#codecs/mod_bv
#codecs/mod_codec2
#codecs/mod_com_g729
#codecs/mod_dahdi_codec
codecs/mod_g723_1
codecs/mod_g729
codecs/mod_h26x
#codecs/mod_ilbc
#codecs/mod_isac
#codecs/mod_mp4v
codecs/mod_opus
#codecs/mod_sangoma_codec
#codecs/mod_silk
#codecs/mod_siren
#codecs/mod_theora
dialplans/mod_dialplan_asterisk
#dialplans/mod_dialplan_directory
dialplans/mod_dialplan_xml
#directories/mod_ldap
#endpoints/mod_alsa
#endpoints/mod_dingaling
#endpoints/mod_gsmopen
#endpoints/mod_h323
#endpoints/mod_khomp
endpoints/mod_loopback
#endpoints/mod_opal
#endpoints/mod_portaudio
endpoints/mod_rtc
#endpoints/mod_rtmp
endpoints/mod_skinny
#endpoints/mod_skypopen
endpoints/mod_sofia
endpoints/mod_verto
#event_handlers/mod_amqp
event_handlers/mod_cdr_csv
#event_handlers/mod_cdr_mongodb
#event_handlers/mod_cdr_pg_csv
event_handlers/mod_cdr_sqlite
#event_handlers/mod_erlang_event
#event_handlers/mod_event_multicast
event_handlers/mod_event_socket
#event_handlers/mod_format_cdr
#event_handlers/mod_json_cdr
#event_handlers/mod_radius_cdr
#event_handlers/mod_odbc_cdr
#event_handlers/mod_kazoo
#event_handlers/mod_rayo
#event_handlers/mod_smpp
#event_handlers/mod_snmp
#event_handlers/mod_event_zmq
#formats/mod_imagick
formats/mod_local_stream
formats/mod_native_file
formats/mod_opusfile
formats/mod_png
#formats/mod_portaudio_stream
#formats/mod_shell_stream
#formats/mod_shout
formats/mod_sndfile
#formats/mod_ssml
formats/mod_tone_stream
#formats/mod_vlc
#languages/mod_basic
#languages/mod_java
languages/mod_lua
#languages/mod_managed
#languages/mod_perl
#languages/mod_python
#languages/mod_v8
#languages/mod_yaml
loggers/mod_console
#loggers/mod_graylog2
loggers/mod_logfile
loggers/mod_syslog
#say/mod_say_de
say/mod_say_en
#say/mod_say_es
#say/mod_say_es_ar
#say/mod_say_fa
#say/mod_say_fr
#say/mod_say_he
#say/mod_say_hr
#say/mod_say_hu
#say/mod_say_it
#say/mod_say_ja
#say/mod_say_nl
#say/mod_say_pl
#say/mod_say_pt
#say/mod_say_ru
#say/mod_say_sv
#say/mod_say_th
#say/mod_say_zh
#timers/mod_posix_timer
#timers/mod_timerfd
xml_int/mod_xml_cdr
#xml_int/mod_xml_curl
#xml_int/mod_xml_ldap
#xml_int/mod_xml_radius
xml_int/mod_xml_rpc
xml_int/mod_xml_scgi
#../../libs/freetdm/mod_freetdm
## Experimental Modules (don't cry if they're broken)
#../../contrib/mod/xml_int/mod_xml_odbc

View File

@ -0,0 +1,4 @@
. ./opts-global.sh
OPTS="$OPTS -t rpm -d speex,opusfile --rpm-dist el7 --rpm-user freeswitch --rpm-group daemon --rpm-use-file-permissions"

View File

@ -0,0 +1,13 @@
. ./opts-global.sh
# mkdir /tmp/debs
# cd /tmp/debs
# wget https://launchpad.net/~kepstin/+archive/ubuntu/opus/+files/libopusenc-dev_0.2.1-1kepstin1_amd64.deb
# wget https://launchpad.net/~kepstin/+archive/ubuntu/opus/+files/libopusenc-doc_0.2.1-1kepstin1_all.deb
# wget https://launchpad.net/~kepstin/+archive/ubuntu/opus/+files/libopusenc0_0.2.1-1kepstin1_amd64.deb
# reprepro --priority optional -b /var/lib/jenkins/reprepro_dev/m22/bionic-2.3.0 includedeb bigbluebutton-bionic *
#OPTS="$OPTS -t deb -d xmlstarlet,libfreetype6,libcurl3,libspeex1,libspeexdsp1,libopus0,libopusfile0,libopusenc0,libsndfile1,liblua5.2-0,libjbig0,libldns1,bbb-freeswitch-sounds --deb-user freeswitch --deb-group daemon --deb-use-file-permissions"
OPTS="$OPTS -t deb -d xmlstarlet,libfreetype6,libcurl4,libspeex1,libspeexdsp1,libopus0,libsndfile1,libopusenc0,libopusfile0,liblua5.2-0,libjbig0,libldns2,bbb-freeswitch-sounds --deb-user freeswitch --deb-group daemon --deb-use-file-permissions"

View File

@ -0,0 +1,4 @@
. ./opts-global.sh
OPTS="$OPTS -t rpm -d speex --rpm-dist el7 --rpm-user freeswitch --rpm-group daemon --rpm-use-file-permissions"

View File

@ -0,0 +1,4 @@
. ./opts-global.sh
OPTS="$OPTS -t deb -d xmlstarlet,libfreetype6,libcurl3,libspeex1,libspeexdsp1,libopus0,libopusfile0,libopusenc0,libsndfile1,liblua5.2-0,libjbig0,libldns1,bbb-freeswitch-sounds --deb-user freeswitch --deb-group daemon --deb-use-file-permissions"

View File

@ -0,0 +1,19 @@
include $(top_srcdir)/build/modmake.rulesam
MODNAME=mod_opusfile
mod_LTLIBRARIES = mod_opusfile.la
mod_opusfile_la_SOURCES = mod_opusfile.c
mod_opusfile_la_CFLAGS = $(AM_CFLAGS)
mod_opusfile_la_LIBADD = $(switch_builddir)/libfreeswitch.la
mod_opusfile_la_LDFLAGS = -avoid-version -module -no-undefined -shared
if HAVE_OPUSFILE_DECODE
mod_opusfile_la_CFLAGS += $(OPUSFILE_DECODE_CFLAGS)
mod_opusfile_la_LIBADD += $(OPUSFILE_DECODE_LIBS)
endif
if HAVE_OPUSFILE_ENCODE
mod_opusfile_la_CFLAGS += $(OPUSFILE_ENCODE_CFLAGS) -DHAVE_OPUSFILE_ENCODE
mod_opusfile_la_LIBADD += $(OPUSFILE_ENCODE_LIBS)
endif

View File

@ -0,0 +1,533 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Dragos Oancea <dragos.oancea@nexmo.com> (mod_opusfile.c)
*
*
* mod_opusfile.c -- Read and Write OGG/Opus files . Some parts inspired from mod_shout.c, libopusfile, libopusenc
*
*/
#include <switch.h>
#include <opusfile.h>
#ifdef HAVE_OPUSFILE_ENCODE
#include <opus/opusenc.h>
#endif
#define OPUSFILE_MAX 32*1024
#define TC_BUFFER_SIZE 1024 * 256 /* max ammount of decoded audio we can have at a time (bytes)*/
#define DEFAULT_RATE 48000 /* default fullband */
#define OPUS_MAX_PCM 5760 /* opus recommended max output buf */
//#undef HAVE_OPUSFILE_ENCODE /*don't encode anything */
SWITCH_MODULE_LOAD_FUNCTION(mod_opusfile_load);
SWITCH_MODULE_DEFINITION(mod_opusfile, mod_opusfile_load, NULL, NULL);
struct opus_file_context {
switch_file_t *fd;
OggOpusFile *of;
ogg_int64_t duration;
int output_seekable;
ogg_int64_t pcm_offset;
ogg_int64_t pcm_print_offset;
ogg_int64_t next_pcm_offset;
ogg_int64_t nsamples;
opus_int32 bitrate;
int li;
int prev_li;
switch_mutex_t *audio_mutex;
switch_buffer_t *audio_buffer;
switch_mutex_t *ogg_mutex;
switch_buffer_t *ogg_buffer;
opus_int16 decode_buf[OPUS_MAX_PCM];
switch_bool_t eof;
switch_thread_rwlock_t *rwlock;
switch_file_handle_t *handle;
size_t samplerate;
int frame_size;
int channels;
size_t buffer_seconds;
size_t err;
opus_int16 *opusbuf;
switch_size_t opusbuflen;
FILE *fp;
#ifdef HAVE_OPUSFILE_ENCODE
OggOpusEnc *enc;
OggOpusComments *comments;
unsigned char encode_buf[OPUSFILE_MAX];
int encoded_buflen;
size_t samples_encode;
#endif
switch_memory_pool_t *pool;
};
typedef struct opus_file_context opus_file_context;
static struct {
int debug;
} globals;
static switch_status_t switch_opusfile_decode(opus_file_context *context, void *data, size_t max_bytes, int channels)
{
int ret = 0;
size_t buf_inuse;
if (!context->of) {
return SWITCH_STATUS_FALSE;
}
memset(context->decode_buf, 0, sizeof(context->decode_buf));
switch_mutex_lock(context->audio_mutex);
while (!(context->eof) && (buf_inuse = switch_buffer_inuse(context->audio_buffer)) <= max_bytes) {
if (channels == 1) {
ret = op_read(context->of, (opus_int16 *)context->decode_buf, OPUS_MAX_PCM, NULL);
} else if (channels == 2) {
ret = op_read_stereo(context->of, (opus_int16 *)context->decode_buf, OPUS_MAX_PCM);
} else if (channels > 2) {
ret = op_read(context->of, (opus_int16 *)context->decode_buf, OPUS_MAX_PCM, NULL);
} else if ((channels > 255) || (channels < 1)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[OGG/OPUS File] Invalid number of channels");
switch_mutex_unlock(context->audio_mutex);
return SWITCH_STATUS_FALSE;
}
if (ret < 0) {
switch(ret) {
case OP_HOLE: /* There was a hole in the data, and some samples may have been skipped. Call this function again to continue decoding past the hole.*/
case OP_EREAD: /*An underlying read operation failed. This may signal a truncation attack from an <https:> source.*/
case OP_EFAULT: /* An internal memory allocation failed. */
case OP_EIMPL: /*An unseekable stream encountered a new link that used a feature that is not implemented, such as an unsupported channel family.*/
case OP_EINVAL: /* The stream was only partially open. */
case OP_ENOTFORMAT: /* An unseekable stream encountered a new link that did not have any logical Opus streams in it. */
case OP_EBADHEADER: /*An unseekable stream encountered a new link with a required header packet that was not properly formatted, contained illegal values, or was missing altogether.*/
case OP_EVERSION: /*An unseekable stream encountered a new link with an ID header that contained an unrecognized version number.*/
case OP_EBADPACKET: /*Failed to properly decode the next packet.*/
case OP_EBADLINK: /*We failed to find data we had seen before.*/
case OP_EBADTIMESTAMP: /*An unseekable stream encountered a new link with a starting timestamp that failed basic validity checks.*/
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[OGG/OPUS Decoder]: error decoding file: [%d]\n", ret);
switch_mutex_unlock(context->audio_mutex);
return SWITCH_STATUS_FALSE;
}
} else if (ret == 0) {
/*The number of samples returned may be 0 if the buffer was too small to store even a single sample for both channels, or if end-of-file was reached*/
if (globals.debug) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[OGG/OPUS Decoder]: EOF reached [%d]\n", ret);
}
context->eof = TRUE;
break;
} else /* (ret > 0)*/ {
/*The number of samples read per channel on success*/
switch_buffer_write(context->audio_buffer, (opus_int16 *)context->decode_buf, ret * sizeof(opus_int16) * channels);
if (globals.debug) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
"[OGG/OPUS Decoder]: Read samples: %d. Wrote bytes to buffer: [%d] bytes in use: [%u]\n", ret, (int)(ret * sizeof(int16_t) * channels), (unsigned int)buf_inuse);
}
}
}
switch_mutex_unlock(context->audio_mutex);
context->eof = FALSE; // for next page
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t switch_opusfile_open(switch_file_handle_t *handle, const char *path)
{
opus_file_context *context;
char *ext;
unsigned int flags = 0;
int ret;
if ((ext = strrchr(path, '.')) == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[OGG/OPUS File] Invalid Format\n");
return SWITCH_STATUS_GENERR;
}
ext++;
if ((context = switch_core_alloc(handle->memory_pool, sizeof(*context))) == 0) {
return SWITCH_STATUS_MEMERR;
}
context->pool = handle->memory_pool;
switch_thread_rwlock_create(&(context->rwlock), context->pool);
switch_thread_rwlock_rdlock(context->rwlock);
switch_mutex_init(&context->audio_mutex, SWITCH_MUTEX_NESTED, context->pool);
if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
flags |= SWITCH_FOPEN_WRITE | SWITCH_FOPEN_CREATE;
if (switch_test_flag(handle, SWITCH_FILE_WRITE_APPEND) || switch_test_flag(handle, SWITCH_FILE_WRITE_OVER)) {
flags |= SWITCH_FOPEN_READ;
} else {
flags |= SWITCH_FOPEN_TRUNCATE;
}
}
if (switch_test_flag(handle, SWITCH_FILE_FLAG_READ)) {
if (switch_buffer_create_dynamic(&context->audio_buffer, TC_BUFFER_SIZE, TC_BUFFER_SIZE * 2, 0) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n");
goto err;
}
flags |= SWITCH_FOPEN_READ;
}
handle->samples = 0;
handle->samplerate = context->samplerate = DEFAULT_RATE; /*open files at 48 khz always*/
handle->format = 0;
handle->sections = 0;
handle->seekable = 1;
handle->speed = 0;
handle->pos = 0;
handle->private_info = context;
context->handle = handle;
memcpy(handle->file_path, path, strlen(path));
#ifdef HAVE_OPUSFILE_ENCODE
if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
int err; int mapping_family = 0;
context->channels = handle->channels;
context->samplerate = handle->samplerate;
handle->seekable = 0;
context->comments = ope_comments_create();
ope_comments_add(context->comments, "METADATA", "Freeswitch/mod_opusfile");
// opus_multistream_surround_encoder_get_size() in libopus will check these
if ((context->channels > 2) && (context->channels <= 8)) {
mapping_family = 1;
} else if ((context->channels > 8) && (context->channels <= 255)) {
mapping_family = 255;
}
context->enc = ope_encoder_create_file(handle->file_path, context->comments, context->samplerate, context->channels, mapping_family, &err);
if (!context->enc) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open file for writing [%d] [%s]\n", err, ope_strerror(err));
switch_thread_rwlock_unlock(context->rwlock);
return SWITCH_STATUS_FALSE;
}
switch_thread_rwlock_unlock(context->rwlock);
return SWITCH_STATUS_SUCCESS;
}
#endif
context->of = op_open_file(path, &ret);
if (!context->of) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[OGG/OPUS File] Error opening %s\n", path);
return SWITCH_STATUS_GENERR;
}
if (switch_test_flag(handle, SWITCH_FILE_WRITE_APPEND)) {
op_pcm_seek(context->of, 0); // overwrite
handle->pos = 0;
}
context->prev_li = -1;
context->nsamples = 0;
handle->channels = context->channels = op_channel_count(context->of, -1);
context->pcm_offset = op_pcm_tell(context->of);
if(context->pcm_offset!=0){
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[OGG/OPUS File] Non-zero starting PCM offset: [%li]\n", (long)context->pcm_offset);
}
context->pcm_print_offset = context->pcm_offset - DEFAULT_RATE;
context->bitrate = 0;
context->buffer_seconds = 1;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "[OGG/OPUS File] Opening File [%s] %dhz\n", path, handle->samplerate);
context->li = op_current_link(context->of);
if (context->li != context->prev_li) {
const OpusHead *head;
const OpusTags *tags;
head=op_head(context->of, context->li);
if (head) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "[OGG/OPUS File] Channels: %i\n", head->channel_count);
if (head->input_sample_rate) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "[OGG/OPUS File] Original sampling rate: %lu Hz\n", (unsigned long)head->input_sample_rate);
handle->samplerate = context->samplerate = head->input_sample_rate;
}
}
if (op_seekable(context->of)) {
ogg_int64_t duration;
opus_int64 size;
duration = op_pcm_total(context->of, context->li);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO , "[OGG/OPUS File] Duration (samples): %u", (unsigned int)duration);
size = op_raw_total(context->of, context->li);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,"[OGG/OPUS File] Size (bytes): %u", (unsigned int)size);
}
tags = op_tags(context->of, context->li);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "[OGG/OPUS File] Encoded by: %s\n", tags->vendor);
}
switch_thread_rwlock_unlock(context->rwlock);
return SWITCH_STATUS_SUCCESS;
err:
switch_thread_rwlock_unlock(context->rwlock);
return SWITCH_STATUS_FALSE;
}
static switch_status_t switch_opusfile_close(switch_file_handle_t *handle)
{
opus_file_context *context = handle->private_info;
switch_thread_rwlock_rdlock(context->rwlock);
if (context->of) {
op_free(context->of);
}
#ifdef HAVE_OPUSFILE_ENCODE
if (context->enc) {
ope_encoder_destroy(context->enc);
}
if (context->comments) {
ope_comments_destroy(context->comments);
}
#endif
if (context->audio_buffer) {
switch_buffer_destroy(&context->audio_buffer);
}
switch_thread_rwlock_unlock(context->rwlock);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t switch_opusfile_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence)
{
int ret;
opus_file_context *context = handle->private_info;
if (handle->handler || switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
return SWITCH_STATUS_FALSE;
} else {
if (whence == SWITCH_SEEK_CUR) {
samples -= switch_buffer_inuse(context->audio_buffer) / sizeof(int16_t);
}
switch_buffer_zero(context->audio_buffer);
ret = op_pcm_seek(context->of, samples);
if (globals.debug) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"[OGG/OPUS File] seek samples: [%u]", (unsigned int)samples);
}
if (ret == 0) {
handle->pos = *cur_sample = samples;
return SWITCH_STATUS_SUCCESS;
}
}
return SWITCH_STATUS_FALSE;
}
static switch_status_t switch_opusfile_read(switch_file_handle_t *handle, void *data, size_t *len)
{
opus_file_context *context = handle->private_info;
size_t bytes = *len * sizeof(int16_t) * handle->real_channels;
size_t rb = 0, newbytes;
if (!context) {
return SWITCH_STATUS_FALSE;
}
if (!handle->handler) {
if (switch_opusfile_decode(context, data, bytes, handle->real_channels) == SWITCH_STATUS_FALSE) {
context->eof = 1;
}
}
switch_mutex_lock(context->audio_mutex);
rb = switch_buffer_read(context->audio_buffer, data, bytes);
switch_mutex_unlock(context->audio_mutex);
if (!rb && (context->eof)) {
return SWITCH_STATUS_FALSE;
}
if (rb) {
*len = rb / sizeof(int16_t) / handle->real_channels;
if (globals.debug) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[OGG/OPUS File] rb: [%d] *len: [%d]\n", (int)rb, (int)*len);
}
} else {
newbytes = (2 * handle->samplerate * handle->real_channels) * context->buffer_seconds;
if (newbytes < bytes) {
bytes = newbytes;
}
if (globals.debug) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
"[OGG/OPUS File] Padding with empty audio. seconds: [%d] bytes: [%d] newbytes: [%d] real_channels: [%d]\n",
(int)context->buffer_seconds, (int)bytes, (int)newbytes, (int)handle->real_channels);
}
memset(data, 255, bytes);
*len = bytes / sizeof(int16_t) / handle->real_channels;
}
handle->pos += *len;
handle->sample_count += *len;
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t switch_opusfile_write(switch_file_handle_t *handle, void *data, size_t *len)
{
#ifdef HAVE_OPUSFILE_ENCODE
size_t nsamples = *len;
int err;
int mapping_family = 0;
opus_file_context *context = handle->private_info;
if (!handle) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error no handle\n");
return SWITCH_STATUS_FALSE;
}
if (!(context = handle->private_info)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error no context\n");
return SWITCH_STATUS_FALSE;
}
if (!context->comments) {
context->comments = ope_comments_create();
ope_comments_add(context->comments, "METADATA", "Freeswitch/mod_opusfile");
}
if (context->channels > 2) {
mapping_family = 1;
}
if (!context->enc) {
context->enc = ope_encoder_create_file(handle->file_path, context->comments, handle->samplerate, handle->channels, mapping_family, &err);
if (!context->enc) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open file for writing. err: [%d] [%s]\n", err, ope_strerror(err));
return SWITCH_STATUS_FALSE;
}
}
if (globals.debug) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"[OGG/OPUS File] write nsamples: [%d]", (int)nsamples);
}
err = ope_encoder_write(context->enc, (opus_int16 *)data, nsamples);
if (err != OPE_OK) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[OGG/OPUS File] Can't encode. err: [%d] [%s]", err, ope_strerror(err));
return SWITCH_STATUS_FALSE;
}
handle->sample_count += *len;
#endif
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t switch_opusfile_set_string(switch_file_handle_t *handle, switch_audio_col_t col, const char *string)
{
return SWITCH_STATUS_FALSE;
}
static switch_status_t switch_opusfile_get_string(switch_file_handle_t *handle, switch_audio_col_t col, const char **string)
{
return SWITCH_STATUS_FALSE;
}
#define OPUSFILE_DEBUG_SYNTAX "<on|off>"
SWITCH_STANDARD_API(mod_opusfile_debug)
{
if (zstr(cmd)) {
stream->write_function(stream, "-USAGE: %s\n", OPUSFILE_DEBUG_SYNTAX);
} else {
if (!strcasecmp(cmd, "on")) {
globals.debug = 1;
stream->write_function(stream, "OPUSFILE Debug: on\n");
#ifdef HAVE_OPUSFILE_ENCODE
stream->write_function(stream, "Library version (encoding): %s\n", ope_get_version_string());
#endif
} else if (!strcasecmp(cmd, "off")) {
globals.debug = 0;
stream->write_function(stream, "OPUSFILE Debug: off\n");
} else {
stream->write_function(stream, "-USAGE: %s\n", OPUSFILE_DEBUG_SYNTAX);
}
}
return SWITCH_STATUS_SUCCESS;
}
/* Registration */
static char *supported_formats[SWITCH_MAX_CODECS] = { 0 };
SWITCH_MODULE_LOAD_FUNCTION(mod_opusfile_load)
{
switch_file_interface_t *file_interface;
switch_api_interface_t *commands_api_interface;
supported_formats[0] = "opus";
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_API(commands_api_interface, "opusfile_debug", "Set OPUSFILE Debug", mod_opusfile_debug, OPUSFILE_DEBUG_SYNTAX);
switch_console_set_complete("add opusfile_debug on");
switch_console_set_complete("add opusfile_debug off");
globals.debug = 0;
file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
file_interface->interface_name = modname;
file_interface->extens = supported_formats;
file_interface->file_open = switch_opusfile_open;
file_interface->file_close = switch_opusfile_close;
file_interface->file_read = switch_opusfile_read;
file_interface->file_write = switch_opusfile_write;
file_interface->file_seek = switch_opusfile_seek;
file_interface->file_set_string = switch_opusfile_set_string;
file_interface->file_get_string = switch_opusfile_get_string;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "mod_opusfile loaded\n");
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -0,0 +1,32 @@
diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport.c
index fbfdfa5..f25dcf1 100644
--- a/libs/sofia-sip/libsofia-sip-ua/tport/tport.c
+++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport.c
@@ -2264,6 +2264,8 @@ int tport_set_secondary_timer(tport_t *self)
return 0;
if (tport_is_closed(self)) {
+
+ again:
if (self->tp_refs == 0) {
SU_DEBUG_7(("tport(%p): set timer at %u ms because %s\n",
(void *)self, 0, "zap"));
@@ -2289,9 +2291,14 @@ int tport_set_secondary_timer(tport_t *self)
}
}
- if (self->tp_pri->pri_vtable->vtp_next_secondary_timer)
- self->tp_pri->pri_vtable->
- vtp_next_secondary_timer(self, &target, &why);
+ if (self->tp_pri->pri_vtable->vtp_next_secondary_timer) {
+ if (self->tp_pri->pri_vtable->
+ vtp_next_secondary_timer(self, &target, &why) == -1) {
+ if (tport_is_closed(self)) {
+ goto again;
+ }
+ }
+ }
if (su_time_cmp(target, infinity)) {
SU_DEBUG_7(("tport(%p): set timer at %ld ms because %s\n",

View File

@ -0,0 +1,30 @@
diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c
index 7e1dc76..618ac8b 100644
--- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c
+++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c
@@ -635,6 +635,8 @@ int tport_ws_next_timer(tport_t *self,
SU_DEBUG_7(("%s(%p): %s to " TPN_FORMAT "%s\n",
__func__, (void *)self,
(punt == 2 ? "Timeout establishing SSL" : "Error establishing SSL"), TPN_ARGS(self->tp_name), ""));
+ if (wstp->ws.secure)
+ return -1;
}
@@ -646,7 +648,13 @@ int tport_ws_next_timer(tport_t *self,
/** WS timer. */
void tport_ws_timer(tport_t *self, su_time_t now)
{
- tport_recv_timeout_timer(self, now);
- tport_keepalive_timer(self, now);
+ tport_ws_t *wstp = (tport_ws_t *)self;
+
+ if (!strcmp("wss", self->tp_protoname) && !wstp->ws.secure_established) {
+ tport_close(self);
+ } else {
+ tport_recv_timeout_timer(self, now);
+ tport_keepalive_timer(self, now);
+ }
tport_base_timer(self, now);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,660 @@
/*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2006 Nokia Corporation.
*
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
/**@CFILE tport_type_ws.c WS Transport
*
* See tport.docs for more detailed description of tport interface.
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Martti Mela <Martti.Mela@nokia.com>
*
* @date Created: Fri Mar 24 08:45:49 EET 2006 ppessi
*/
#include "config.h"
#include "tport_internal.h"
#include "tport_ws.h"
#include "tport_tls.h"
#if HAVE_NETINET_TCP_H
#include <netinet/tcp.h>
#endif
#ifndef SOL_TCP
#define SOL_TCP IPPROTO_TCP
#endif
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <assert.h>
#include <errno.h>
#include <limits.h>
#if HAVE_FUNC
#elif HAVE_FUNCTION
#define __func__ __FUNCTION__
#else
static char const __func__[] = "tport_type_ws";
#endif
#if HAVE_WIN32
#include <io.h>
#define access(_filename, _mode) _access(_filename, _mode)
#define R_OK (04)
#endif
/* ---------------------------------------------------------------------- */
/* WS */
#include <sofia-sip/http.h>
#include <sofia-sip/http_header.h>
static int tport_ws_init_primary_secure(tport_primary_t *pri,
tp_name_t tpn[1],
su_addrinfo_t *ai,
tagi_t const *tags,
char const **return_culprit);
static int tport_ws_setsndbuf(int socket, int atleast);
static void tport_ws_deinit_primary(tport_primary_t *pri);
tport_vtable_t const tport_ws_vtable =
{
/* vtp_name */ "ws",
/* vtp_public */ tport_type_local,
/* vtp_pri_size */ sizeof (tport_ws_primary_t),
/* vtp_init_primary */ tport_ws_init_primary,
/* vtp_deinit_primary */ tport_ws_deinit_primary,
/* vtp_wakeup_pri */ tport_accept,
/* vtp_connect */ NULL,
/* vtp_secondary_size */ sizeof (tport_ws_t),
/* vtp_init_secondary */ tport_ws_init_secondary,
/* tp_deinit_secondary */ tport_ws_deinit_secondary,
/* vtp_shutdown */ NULL,
/* vtp_set_events */ NULL,
/* vtp_wakeup */ NULL,
/* vtp_recv */ tport_recv_stream_ws,
/* vtp_send */ tport_send_stream_ws,
/* vtp_deliver */ NULL,
/* vtp_prepare */ NULL,
/* vtp_keepalive */ NULL,
/* vtp_stun_response */ NULL,
/* vtp_next_secondary_timer*/ tport_ws_next_timer,
/* vtp_secondary_timer */ tport_ws_timer,
};
tport_vtable_t const tport_ws_client_vtable =
{
/* vtp_name */ "ws",
/* vtp_public */ tport_type_client,
/* vtp_pri_size */ sizeof (tport_ws_primary_t),
/* vtp_init_primary */ tport_ws_init_client,
/* vtp_deinit_primary */ tport_ws_deinit_primary,
/* vtp_wakeup_pri */ NULL,
/* vtp_connect */ NULL,
/* vtp_secondary_size */ sizeof (tport_ws_t),
/* vtp_init_secondary */ tport_ws_init_secondary,
/* vtp_deinit_secondary */ NULL,
/* vtp_shutdown */ NULL,
/* vtp_set_events */ NULL,
/* vtp_wakeup */ NULL,
/* vtp_recv */ tport_recv_stream_ws,
/* vtp_send */ tport_send_stream_ws,
/* vtp_deliver */ NULL,
/* vtp_prepare */ NULL,
/* vtp_keepalive */ NULL,
/* vtp_stun_response */ NULL,
/* vtp_next_secondary_timer*/ tport_ws_next_timer,
/* vtp_secondary_timer */ tport_ws_timer,
};
tport_vtable_t const tport_wss_vtable =
{
/* vtp_name */ "wss",
/* vtp_public */ tport_type_local,
/* vtp_pri_size */ sizeof (tport_ws_primary_t),
/* vtp_init_primary */ tport_ws_init_primary_secure,
/* vtp_deinit_primary */ tport_ws_deinit_primary,
/* vtp_wakeup_pri */ tport_accept,
/* vtp_connect */ NULL,
/* vtp_secondary_size */ sizeof (tport_ws_t),
/* vtp_init_secondary */ tport_ws_init_secondary,
/* vtp_deinit_secondary */ tport_ws_deinit_secondary,
/* vtp_shutdown */ NULL,
/* vtp_set_events */ NULL,
/* vtp_wakeup */ NULL,
/* vtp_recv */ tport_recv_stream_ws,
/* vtp_send */ tport_send_stream_ws,
/* vtp_deliver */ NULL,
/* vtp_prepare */ NULL,
/* vtp_keepalive */ NULL,
/* vtp_stun_response */ NULL,
/* vtp_next_secondary_timer*/ tport_ws_next_timer,
/* vtp_secondary_timer */ tport_ws_timer,
};
tport_vtable_t const tport_wss_client_vtable =
{
/* vtp_name */ "wss",
/* vtp_public */ tport_type_client,
/* vtp_pri_size */ sizeof (tport_ws_primary_t),
/* vtp_init_primary */ tport_ws_init_client,
/* vtp_deinit_primary */ tport_ws_deinit_primary,
/* vtp_wakeup_pri */ NULL,
/* vtp_connect */ NULL,
/* vtp_secondary_size */ sizeof (tport_ws_t),
/* vtp_init_secondary */ tport_ws_init_secondary,
/* vtp_deinit_secondary */ NULL,
/* vtp_shutdown */ NULL,
/* vtp_set_events */ NULL,
/* vtp_wakeup */ NULL,
/* vtp_recv */ tport_recv_stream_ws,
/* vtp_send */ tport_send_stream_ws,
/* vtp_deliver */ NULL,
/* vtp_prepare */ NULL,
/* vtp_keepalive */ NULL,
/* vtp_stun_response */ NULL,
/* vtp_next_secondary_timer*/ tport_ws_next_timer,
/* vtp_secondary_timer */ tport_ws_timer,
};
static void tport_ws_deinit_primary(tport_primary_t *pri)
{
tport_ws_primary_t *wspri = (tport_ws_primary_t *)pri;
if ( wspri->ssl_ctx ) {
SSL_CTX_free(wspri->ssl_ctx);
wspri->ssl_ctx = NULL;
}
}
/** Receive from stream.
*
* @retval -1 error
* @retval 0 end-of-stream
* @retval 1 normal receive
* @retval 2 incomplete recv, recv again
*
*/
int tport_recv_stream_ws(tport_t *self)
{
msg_t *msg;
ssize_t n, N, veclen, i, m;
int err;
msg_iovec_t iovec[msg_n_fragments] = {{ 0 }};
tport_ws_t *wstp = (tport_ws_t *)self;
uint8_t *data;
ws_opcode_t oc;
if (wstp->ws_initialized < 0) {
return -1;
}
N = ws_read_frame(&wstp->ws, &oc, &data);
if (N == -2) {
return 1;
}
if ((N == -1000) || (N == 0)) {
if (self->tp_msg) {
msg_recv_commit(self->tp_msg, 0, 1);
}
return 0; /* End of stream */
}
if (N < 0) {
err = errno = EHOSTDOWN;
SU_DEBUG_1(("%s(%p): su_getmsgsize(): %s (%d) N=%ld\n", __func__, (void *)self,
su_strerror(err), err, (long)N));
return 0;
}
veclen = tport_recv_iovec(self, &self->tp_msg, iovec, N, 0);
if (veclen < 0)
return -1;
msg = self->tp_msg;
msg_set_address(msg, self->tp_addr, self->tp_addrlen);
for (i = 0, n = 0; i < veclen; i++) {
m = iovec[i].mv_len; assert(N >= n + m);
memcpy(iovec[i].mv_base, data + n, m);
n += m;
}
assert(N == n);
/* Write the received data to the message dump file */
if (self->tp_master->mr_dump_file)
tport_dump_iovec(self, msg, n, iovec, veclen, "recv", "from");
if (self->tp_master->mr_capt_sock)
tport_capt_msg(self, msg, n, iovec, veclen, "recv");
/* Mark buffer as used */
msg_recv_commit(msg, N, 0);
return 1;
}
/** Send to stream */
ssize_t tport_send_stream_ws(tport_t const *self, msg_t *msg,
msg_iovec_t iov[],
size_t iovlen)
{
size_t i, j, m, size = 0;
ssize_t nerror;
tport_ws_t *wstp = (tport_ws_t *)self;
wstp->wstp_buflen = 0;
for (i = 0; i < iovlen; i = j) {
char *buf = NULL;
unsigned wsbufsize = sizeof(wstp->wstp_buffer);
for (j = i, m = 0; buf && j < iovlen; j++) {
if (m + iov[j].siv_len > wsbufsize) {
break;
}
if (buf + m != iov[j].siv_base) {
memcpy(buf + m, iov[j].siv_base, iov[j].siv_len);
}
m += iov[j].siv_len; iov[j].siv_len = 0;
}
if (j == i) {
buf = iov[i].siv_base, m = iov[i].siv_len, j++;
} else {
iov[j].siv_base = buf, iov[j].siv_len = m;
}
nerror = 0;
if (m + wstp->wstp_buflen >= wsbufsize) {
nerror = -1;
errno = ENOMEM;
} else {
if (memcpy(wstp->wstp_buffer + wstp->wstp_buflen, buf, m)) {
wstp->wstp_buflen += m;
} else {
nerror = -1;
errno = ENOMEM;
}
}
SU_DEBUG_9(("tport_ws_writevec: vec %p %p %lu ("MOD_ZD")\n",
(void *)&wstp->ws, (void *)iov[i].siv_base, (LU)iov[i].siv_len,
nerror));
if (nerror == -1) {
int err = su_errno();
if (su_is_blocking(err))
break;
SU_DEBUG_3(("ws_write: %s\n", strerror(err)));
return -1;
}
}
if (wstp->wstp_buflen) {
ssize_t wrote = 0;
*(wstp->wstp_buffer + wstp->wstp_buflen) = '\0';
wrote = ws_write_frame(&wstp->ws, WSOC_TEXT, wstp->wstp_buffer, wstp->wstp_buflen);
if (wrote < 0) {
int err = su_errno();
SU_DEBUG_3(("ws_write_frame: %s\n", strerror(err)));
size = wrote;
} else {
size = wstp->wstp_buflen;
}
}
return size;
}
static int tport_ws_init_primary_secure(tport_primary_t *pri,
tp_name_t tpn[1],
su_addrinfo_t *ai,
tagi_t const *tags,
char const **return_culprit)
{
tport_ws_primary_t *wspri = (tport_ws_primary_t *)pri;
const char *cert = "/ssl.pem";
const char *key = "/ssl.pem";
const char *chain = NULL;
char *homedir;
char *tbf = NULL;
su_home_t autohome[SU_HOME_AUTO_SIZE(1024)];
char const *path = NULL;
int ret = -1;
su_home_auto(autohome, sizeof autohome);
tl_gets(tags,
TPTAG_CERTIFICATE_REF(path),
TAG_END());
if (!path) {
homedir = getenv("HOME");
if (!homedir)
homedir = "";
path = tbf = su_sprintf(autohome, "%s/.sip/auth", homedir);
}
if (path) {
key = su_sprintf(autohome, "%s/%s", path, "wss.key");
if (access(key, R_OK) != 0) key = NULL;
cert = su_sprintf(autohome, "%s/%s", path, "wss.crt");
if (access(cert, R_OK) != 0) cert = NULL;
chain = su_sprintf(autohome, "%s/%s", path, "ca-bundle.crt");
if (access(chain, R_OK) != 0) chain = NULL;
if ( !key ) key = su_sprintf(autohome, "%s/%s", path, "wss.pem");
if ( !cert ) cert = su_sprintf(autohome, "%s/%s", path, "wss.pem");
if ( !chain ) chain = su_sprintf(autohome, "%s/%s", path, "wss.pem");
if (access(key, R_OK) != 0) key = NULL;
if (access(cert, R_OK) != 0) cert = NULL;
if (access(chain, R_OK) != 0) chain = NULL;
}
init_ssl();
// OpenSSL_add_all_algorithms(); /* load & register cryptos */
// SSL_load_error_strings(); /* load all error messages */
wspri->ssl_method = SSLv23_server_method(); /* create server instance */
wspri->ssl_ctx = SSL_CTX_new((SSL_METHOD *)wspri->ssl_method); /* create context */
SSL_CTX_sess_set_remove_cb(wspri->ssl_ctx, NULL);
wspri->ws_secure = 1;
if ( !wspri->ssl_ctx ) {
tls_log_errors(3, "tport_ws_init_primary_secure", 0);
goto done;
}
/* Disable SSLv2 */
SSL_CTX_set_options(wspri->ssl_ctx, SSL_OP_NO_SSLv2);
/* Disable SSLv3 */
SSL_CTX_set_options(wspri->ssl_ctx, SSL_OP_NO_SSLv3);
/* Disable TLSv1 */
SSL_CTX_set_options(wspri->ssl_ctx, SSL_OP_NO_TLSv1);
/* Disable Compression CRIME (Compression Ratio Info-leak Made Easy) */
SSL_CTX_set_options(wspri->ssl_ctx, SSL_OP_NO_COMPRESSION);
if (chain) {
if ( !SSL_CTX_use_certificate_chain_file(wspri->ssl_ctx, chain) ) {
tls_log_errors(3, "tport_ws_init_primary_secure", 0);
}
}
/* set the local certificate from CertFile */
if ( !SSL_CTX_use_certificate_file(wspri->ssl_ctx, cert, SSL_FILETYPE_PEM) ) {
tls_log_errors(3, "tport_ws_init_primary_secure", 0);
goto done;
}
/* set the private key from KeyFile */
if ( !SSL_CTX_use_PrivateKey_file(wspri->ssl_ctx, key, SSL_FILETYPE_PEM) ) {
tls_log_errors(3, "tport_ws_init_primary_secure", 0);
goto done;
}
/* verify private key */
if ( !SSL_CTX_check_private_key(wspri->ssl_ctx) ) {
tls_log_errors(3, "tport_ws_init_primary_secure", 0);
goto done;
}
if ( !SSL_CTX_set_cipher_list(wspri->ssl_ctx, "!eNULL:!aNULL:!DSS:HIGH:@STRENGTH") ) {
tls_log_errors(3, "tport_ws_init_primary_secure", 0);
goto done;
}
ret = tport_ws_init_primary(pri, tpn, ai, tags, return_culprit);
done:
su_home_zap(autohome);
return ret;
}
int tport_ws_init_primary(tport_primary_t *pri,
tp_name_t tpn[1],
su_addrinfo_t *ai,
tagi_t const *tags,
char const **return_culprit)
{
int socket;
socket = su_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (socket == INVALID_SOCKET)
return *return_culprit = "socket", -1;
tport_ws_setsndbuf(socket, 64 * 1024);
return tport_stream_init_primary(pri, socket, tpn, ai, tags, return_culprit);
}
int tport_ws_init_client(tport_primary_t *pri,
tp_name_t tpn[1],
su_addrinfo_t *ai,
tagi_t const *tags,
char const **return_culprit)
{
pri->pri_primary->tp_conn_orient = 1;
return 0;
}
int tport_ws_init_secondary(tport_t *self, int socket, int accepted,
char const **return_reason)
{
int one = 1;
tport_ws_primary_t *wspri = (tport_ws_primary_t *)self->tp_pri;
tport_ws_t *wstp = (tport_ws_t *)self;
self->tp_has_connection = 1;
self->tp_params->tpp_keepalive = 5000;
/* override the default 30 minute timeout on tport connections */
self->tp_params->tpp_idle = UINT_MAX;
if (setsockopt(socket, SOL_TCP, TCP_NODELAY, (void *)&one, sizeof one) == -1)
return *return_reason = "TCP_NODELAY", -1;
#if defined(SO_KEEPALIVE)
setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, (void *)&one, sizeof one);
#endif
one = 30;
#if defined(TCP_KEEPIDLE)
setsockopt(socket, SOL_TCP, TCP_KEEPIDLE, (void *)&one, sizeof one);
#endif
#if defined(TCP_KEEPINTVL)
setsockopt(socket, SOL_TCP, TCP_KEEPINTVL, (void *)&one, sizeof one);
#endif
if (!accepted)
tport_ws_setsndbuf(socket, 64 * 1024);
if ( wspri->ws_secure ) wstp->ws_secure = 1;
memset(&wstp->ws, 0, sizeof(wstp->ws));
if (ws_init(&wstp->ws, socket, wstp->ws_secure ? wspri->ssl_ctx : NULL, 0, 0, 0) < 0) {
ws_destroy(&wstp->ws);
wstp->ws_initialized = -1;
return *return_reason = "WS_INIT", -1;
}
wstp->connected = time(NULL);
wstp->ws_initialized = 1;
self->tp_pre_framed = 1;
tport_set_secondary_timer(self);
return 0;
}
static void tport_ws_deinit_secondary(tport_t *self)
{
tport_ws_t *wstp = (tport_ws_t *)self;
if (wstp->ws_initialized == 1) {
SU_DEBUG_1(("%p destroy ws%s transport %p.\n", (void *) self, wstp->ws_secure ? "s" : "", (void *) &wstp->ws));
ws_destroy(&wstp->ws);
wstp->ws_initialized = -1;
}
}
static int tport_ws_setsndbuf(int socket, int atleast)
{
#if SU_HAVE_WINSOCK2
/* Set send buffer size to something reasonable on windows */
int size = 0;
socklen_t sizelen = sizeof size;
if (getsockopt(socket, SOL_SOCKET, SO_SNDBUF, (void *)&size, &sizelen) < 0)
return -1;
if (sizelen != sizeof size)
return su_seterrno(EINVAL);
if (size >= atleast)
return 0; /* OK */
return setsockopt(socket, SOL_SOCKET, SO_SNDBUF,
(void *)&atleast, sizeof atleast);
#else
return 0;
#endif
}
/** Send PING */
int tport_ws_ping(tport_t *self, su_time_t now)
{
ssize_t n;
char *why = "";
if (tport_has_queued(self))
return 0;
n = send(self->tp_socket, "\r\n\r\n", 4, 0);
if (n > 0)
self->tp_ktime = now;
if (n == 4) {
if (self->tp_ptime.tv_sec == 0)
self->tp_ptime = now;
}
else if (n == -1) {
int error = su_errno();
why = " failed";
if (!su_is_blocking(error))
tport_error_report(self, error, NULL);
else
why = " blocking";
}
SU_DEBUG_7(("%s(%p): %s to " TPN_FORMAT "%s\n",
__func__, (void *)self,
"sending PING", TPN_ARGS(self->tp_name), why));
return n == -1 ? -1 : 0;
}
/** Send pong */
int tport_ws_pong(tport_t *self)
{
self->tp_ping = 0;
if (tport_has_queued(self) || !self->tp_params->tpp_pong2ping)
return 0;
SU_DEBUG_7(("%s(%p): %s to " TPN_FORMAT "%s\n",
__func__, (void *)self,
"sending PONG", TPN_ARGS(self->tp_name), ""));
return send(self->tp_socket, "\r\n", 2, 0);
}
/** Calculate next timer for WS. */
int tport_ws_next_timer(tport_t *self,
su_time_t *return_target,
char const **return_why)
{
tport_ws_t *wstp = (tport_ws_t *)self;
int ll = establish_logical_layer(&wstp->ws);
int punt = 0;
if (ll == -1) {
punt = 1;
} else if (ll < 0) {
time_t now = time(NULL);
if (now - wstp->connected > 5) {
punt = 2;
}
} else {
self->tp_params->tpp_keepalive = 0;
}
if (punt) {
tport_close(self);
SU_DEBUG_7(("%s(%p): %s to " TPN_FORMAT "%s\n",
__func__, (void *)self,
(punt == 2 ? "Timeout establishing SSL" : "Error establishing SSL"), TPN_ARGS(self->tp_name), ""));
if (wstp->ws.secure)
return -1;
}
return
tport_next_recv_timeout(self, return_target, return_why) |
tport_next_keepalive(self, return_target, return_why);
}
/** WS timer. */
void tport_ws_timer(tport_t *self, su_time_t now)
{
tport_ws_t *wstp = (tport_ws_t *)self;
if (!strcmp("wss", self->tp_protoname) && !wstp->ws.secure_established) {
tport_close(self);
} else {
tport_recv_timeout_timer(self, now);
tport_keepalive_timer(self, now);
}
tport_base_timer(self, now);
}

View File

@ -0,0 +1,45 @@
#!/bin/bash -ex
TARGET=`basename $(pwd)`
PACKAGE=$(echo $TARGET | cut -d'_' -f1)
VERSION=$(echo $TARGET | cut -d'_' -f2)
DISTRO=$(echo $TARGET | cut -d'_' -f3)
#VERSION=1.6.7
#
# Clear staging directory for build
rm -rf staging
#
# Create directory for fpm to process
#DIRS="/opt/freeswitch \
# /var/freeswitch/meetings"
#for dir in $DIRS; do
# mkdir -p staging$dir
# DIRECTORIES="$DIRECTORIES --directories $dir"
#done
##
##
DESTDIR=staging
CONFDIR=$DESTDIR/opt/freeswitch/etc/freeswitch
mkdir -p $DESTDIR/opt/freeswitch/share/freeswitch
if [ ! -f sounds.tar.gz ] ; then
wget http://bigbluebutton.org/downloads/sounds.tar.gz -O sounds.tar.gz
fi
tar xvfz sounds.tar.gz -C $DESTDIR/opt/freeswitch/share/freeswitch
. ./opts-$DISTRO.sh
fpm -s dir -C $DESTDIR -n $PACKAGE \
--version $VERSION --epoch $EPOCH \
--description "FreeSWITCH Sounds" \
$DIRECTORIES \
$OPTS

View File

@ -0,0 +1,4 @@
. ./opts-global.sh
OPTS="$OPTS -t deb --deb-user freeswitch --deb-group daemon --deb-use-file-permissions"

View File

@ -0,0 +1,55 @@
#!/bin/bash -ex
TARGET=`basename $(pwd)`
PACKAGE=$(echo $TARGET | cut -d'_' -f1)
DISTRO=$(echo $TARGET | cut -d'_' -f3)
##
EPHEMERAL_VERSION=0.0.$(date +%s)-SNAPSHOT
sed -i "s|\(version := \)\".*|\1\"$EPHEMERAL_VERSION\"|g" bbb-common-message/build.sbt
find -name build.gradle -exec sed -i "s|\(.*org.bigbluebutton.*bbb-common-message[^:]*\):.*|\1:$EPHEMERAL_VERSION'|g" {} \;
find -name build.sbt -exec sed -i "s|\(.*org.bigbluebutton.*bbb-common-message[^\"]*\"[ ]*%[ ]*\)\"[^\"]*\"\(.*\)|\1\"$EPHEMERAL_VERSION\"\2|g" {} \;
sed -i "s|\(version := \)\".*|\1\"$EPHEMERAL_VERSION\"|g" bbb-fsesl-client/build.sbt
find -name build.gradle -exec sed -i "s|\(.*org.bigbluebutton.*bbb-fsesl-client[^:]*\):.*|\1:$EPHEMERAL_VERSION'|g" {} \;
find -name build.sbt -exec sed -i "s|\(.*org.bigbluebutton.*bbb-fsesl-client[^\"]*\"[ ]*%[ ]*\)\"[^\"]*\"\(.*\)|\1\"$EPHEMERAL_VERSION\"\2|g" {} \;
build_common_messages () {
cd bbb-common-message
sbt publish
sbt publishLocal
}
build_fsesl_client () {
cd bbb-fsesl-client
sbt publish
sbt publishLocal
}
# build these two in parallel
build_common_messages &
build_fsesl_client &
wait
cd akka-bbb-fsesl
sed -i 's/\r$//' project/Dependencies.scala
sed -i 's|\(val bbbCommons = \)"[^"]*"$|\1"EPHEMERAL_VERSION"|g' project/Dependencies.scala
sed -i 's|\(val bbbFsesl = \)"[^"]*"$|\1"EPHEMERAL_VERSION"|g' project/Dependencies.scala
sed -i "s/EPHEMERAL_VERSION/$EPHEMERAL_VERSION/g" project/Dependencies.scala
echo "enablePlugins(SystemdPlugin)" >> build.sbt
echo "serverLoading in Debian := Some(com.typesafe.sbt.packager.archetypes.systemloader.ServerLoader.Systemd)" >> build.sbt
mkdir -p src/templates
echo '#JAVA_OPTS="-Dconfig.file=/usr/share/bbb-fsesl-akka/conf/application.conf $JAVA_OPTS"' > src/templates/etc-default
sed -i "s/^version .*/version := \"$VERSION\"/g" build.sbt
if [[ -n $EPOCH && $EPOCH -gt 0 ]] ; then
echo 'version in Debian := "'$EPOCH:$VERSION'"' >> build.sbt
fi
sbt debian:packageBin
cp ./target/*.deb ..
##

View File

@ -0,0 +1,158 @@
#!/bin/bash -e
HOST=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*\///;p}')
if [ ! -L /etc/nginx/sites-enabled/bigbluebutton ]; then
ln -s /etc/nginx/sites-available/bigbluebutton /etc/nginx/sites-enabled/bigbluebutton
fi
cd /usr/share/meteor
# meteor code should be owned by root, config file by meteor user
meteor_owner=$(stat -c %U:%G /usr/share/meteor)
if [[ $meteor_owner != "root:root" ]] ; then
chown -R root:root /usr/share/meteor
fi
if [ -f $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties ]; then
sed -i 's/^svgImagesRequired=.*/svgImagesRequired=true/' $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties
if [ ! -f /.dockerenv ]; then
systemctl restart nginx
fi
if cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep bigbluebutton.web.serverURL | grep -q https; then
PROTOCOL=https
sed -i 's/^ENVIRONMENT_TYPE=.*/ENVIRONMENT_TYPE=production/' /usr/share/meteor/bundle/systemd_start.sh
else
PROTOCOL=http
sed -i 's/^ENVIRONMENT_TYPE=.*/ENVIRONMENT_TYPE=development/' /usr/share/meteor/bundle/systemd_start.sh
fi
fi
SOURCE=/tmp/settings.yml
TARGET=/usr/share/meteor/bundle/programs/server/assets/app/config/settings.yml
if [ -f $SOURCE ]; then
WSURL=$(yq r $SOURCE public.kurento.wsUrl)
CHROMEEXTENSIONKEY=$(yq r $SOURCE public.kurento.chromeExtensionKey)
CHROMEEXTENSIONLINK=$(yq r $SOURCE public.kurento.chromeExtensionLink)
ENABLESCREENSHARING=$(yq r $SOURCE public.kurento.enableScreensharing)
ENABLEVIDEO=$(yq r $SOURCE public.kurento.enableVideo)
ETHERPAD_ENABLED=$(yq r $SOURCE public.note.enabled)
ETHERPAD_URL=$(yq r $SOURCE public.note.url)
yq w -i $TARGET public.kurento.wsUrl "$WSURL"
yq w -i $TARGET public.kurento.chromeExtensionKey "$CHROMEEXTENSIONKEY"
yq w -i $TARGET public.kurento.chromeExtensionLink "$CHROMEEXTENSIONLINK"
yq w -i $TARGET public.kurento.enableScreensharing "$ENABLESCREENSHARING"
yq w -i $TARGET public.kurento.enableVideo "$ENABLEVIDEO"
if [ "$ETHERPAD_ENABLED" == "null" ]; then
# This is an upgrade from a previous version of 2.2-dev that didn't have settings for etherpad
yq w -i $TARGET public.note.enabled "true"
yq w -i $TARGET public.note.url "$PROTOCOL://$HOST/pad"
else
yq w -i $TARGET public.note.enabled "$ETHERPAD_ENABLED"
yq w -i $TARGET public.note.url "$ETHERPAD_URL"
fi
yq w -i $TARGET public.app.listenOnlyMode "true"
mv -f $SOURCE "${SOURCE}_"
else
# New Setup
WSURL=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}' | sed 's/https/wss/g' | sed s'/http/ws/g')
yq w -i $TARGET public.kurento.wsUrl "$WSURL/bbb-webrtc-sfu"
yq w -i $TARGET public.kurento.enableScreensharing "true"
yq w -i $TARGET public.kurento.enableVideo "true"
yq w -i $TARGET public.app.listenOnlyMode "true"
yq w -i $TARGET public.note.enabled "true"
yq w -i $TARGET public.note.url "$PROTOCOL://$HOST/pad"
sed -i "s/proxy_pass .*/proxy_pass http:\/\/$IP:5066;/g" /etc/bigbluebutton/nginx/sip.nginx
sed -i "s/server_name .*/server_name $IP;/g" /etc/nginx/sites-available/bigbluebutton
fi
APIKEY=$(cat /usr/share/etherpad-lite/APIKEY.txt)
yq w -i $TARGET private.etherpad.apikey $APIKEY
chmod 600 $TARGET
chown meteor:meteor $TARGET
if [ ! -f /.dockerenv ]; then
systemctl enable disable-transparent-huge-pages.service
systemctl daemon-reload
fi
# Remove old overrides
if [ -f /etc/systemd/system/mongod.service.d/override-mongo.conf ] \
|| [ -f /etc/systemd/system/mongod.service.d/override.conf ] \
|| [ -f /usr/lib/systemd/system/mongod.service.d/mongod-service-override.conf ] ; then
rm -f /etc/systemd/system/mongod.service.d/override-mongo.conf
rm -f /etc/systemd/system/mongod.service.d/override.conf
rm -f /usr/lib/systemd/system/mongod.service.d/mongod-service-override.conf
systemctl daemon-reload
fi
# Setup specific version of node
source /etc/lsb-release
if [ "$DISTRIB_RELEASE" == "16.04" ]; then
if [ ! -d /usr/share/node-v8.17.0-linux-x64 ]; then
cd /usr/share
tar xfz node-v8.17.0-linux-x64.tar.gz
chown -R meteor:meteor node-v8.17.0-linux-x64
fi
fi
if [ "$DISTRIB_RELEASE" == "18.04" ]; then
node_version="12.16.1"
if [[ ! -d /usr/share/node-v${node_version}-linux-x64 ]]; then
cd /usr/share
tar xfz "node-v${node_version}-linux-x64.tar.gz"
fi
node_owner=$(stat -c %U:%G "/usr/share/node-v${node_version}-linux-x64")
if [[ $node_owner != root:root ]] ; then
chown -R root:root "/usr/share/node-v${node_version}-linux-x64"
fi
fi
# Enable Listen Only support in FreeSWITCH
if [ -f /opt/freeswitch/etc/freeswitch/sip_profiles/external.xml ]; then
sed -i 's/<!--<param name="enable-3pcc" value="true"\/>-->/<param name="enable-3pcc" value="proxy"\/>/g' /opt/freeswitch/etc/freeswitch/sip_profiles/external.xml
fi
if [ -f /tmp/sip.nginx ]; then
IP_SIP=$(cat /tmp/sip.nginx | grep -v '#' | sed -n '/proxy_pass/{s/.*\/\///;s/:.*//;p}')
IP_PORT=$(cat /tmp/sip.nginx | grep -v '#' | sed -n '/proxy_pass/{s/[^:]*.*[^:]*://;s/;.*//;p}')
if grep proxy_pass /tmp/sip.nginx | grep -q https; then
sed -i "s/proxy_pass http.*/proxy_pass https:\/\/$IP_SIP:$IP_PORT;/g" \
/etc/bigbluebutton/nginx/sip.nginx
else
sed -i "s/proxy_pass http.*/proxy_pass http:\/\/$IP_SIP:$IP_PORT;/g" \
/etc/bigbluebutton/nginx/sip.nginx
fi
fi
if ! grep -q auth_request /etc/bigbluebutton/nginx/sip.nginx; then
sed -i 's#}#\n auth_request /bigbluebutton/connection/checkAuthorization;\n auth_request_set $auth_status $upstream_status;\n}#g' \
/etc/bigbluebutton/nginx/sip.nginx
fi
chown root:root /usr/lib/systemd/system
chown root:root /usr/lib/systemd/system/bbb-html5.service
chown root:root /usr/lib/systemd/system/disable-transparent-huge-pages.service
startService bbb-html5 || echo "bbb-html5 service could not be registered or started"

View File

@ -0,0 +1,29 @@
#!/bin/bash -e
case "$1" in
remove|failed-upgrade|abort-upgrade|abort-install|disappear|0|1)
if [ -f $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties ]; then
sed -i 's/svgImagesRequired=true/svgImagesRequired=false/g' $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties
#if [ ! -f /.dockerenv ]; then
# systemctl restart tomcat7
#elif [ which supervisorctl > /dev/null ]; then
# supervisorctl restart tomcat7
#fi
fi
if [ -L /etc/nginx/sites-enabled/bigbluebutton ]; then
rm /etc/nginx/sites-enabled/bigbluebutton
fi
;;
purge)
deleteUser meteor
deleteGroup meteor
;;
upgrade)
;;
*)
echo "postinst called with unknown argument $1" >&2
;;
esac

View File

@ -0,0 +1,23 @@
#!/bin/bash -e
addGroup meteor ""
addUser meteor "" meteor /usr/share/meteor "meteor user-daemon" "/bin/bash"
case "$1" in
install|upgrade|1|2)
if [ -f /usr/share/meteor/bundle/programs/server/assets/app/config/settings.yml ]; then
cp /usr/share/meteor/bundle/programs/server/assets/app/config/settings.yml /tmp/settings.yml
fi
rm -f /tmp/sip.nginx
if [ -f /etc/bigbluebutton/nginx/sip.nginx ]; then
cp /etc/bigbluebutton/nginx/sip.nginx /tmp/sip.nginx
fi
if [ -f /usr/share/meteor/bundle/programs/server/node_modules ]; then
rm -r /usr/share/meteor/bundle/programs/server/node_modules
fi
;;
esac

View File

@ -0,0 +1,4 @@
#!/bin/bash -e
stopService bbb-html5 || echo "bbb-html5 could not be unregistered or stopped"

View File

@ -0,0 +1,63 @@
server {
listen 80;
listen [::]:80;
server_name 192.168.0.103;
access_log /var/log/nginx/bigbluebutton.access.log;
# Handle RTMPT (RTMP Tunneling). Forwards requests
# to Red5 on port 5080
location ~ (/open/|/close/|/idle/|/send/|/fcs/) {
proxy_pass http://127.0.0.1:5080;
proxy_redirect off;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffering off;
keepalive_requests 1000000000;
}
# Handle desktop sharing tunneling. Forwards
# requests to Red5 on port 5080.
location /deskshare {
proxy_pass http://127.0.0.1:5080;
proxy_redirect default;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
include fastcgi_params;
}
# BigBlueButton landing page.
location / {
root /var/www/bigbluebutton-default;
index index.html index.htm;
expires 1m;
}
# Include specific rules for record and playback
include /etc/bigbluebutton/nginx/*.nginx;
#error_page 404 /404.html;
# Redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/www/nginx-default;
}
}

View File

@ -0,0 +1,25 @@
[Unit]
Description=BigBlueButton HTML5 service, backend instance %i
Requires=bbb-html5.service
Before=bbb-html5.service
BindsTo=bbb-html5.service
[Service]
PermissionsStartOnly=true
#Type=simple
Type=idle
EnvironmentFile=/usr/share/meteor/bundle/bbb-html5-with-roles.conf
ExecStart=/usr/share/meteor/bundle/systemd_start.sh %i $BACKEND_NODEJS_ROLE
WorkingDirectory=/usr/share/meteor/bundle
StandardOutput=syslog
StandardError=syslog
TimeoutStartSec=10
RestartSec=10
User=meteor
Group=meteor
CPUSchedulingPolicy=fifo
Nice=19
[Install]
WantedBy=bbb-html5.service

View File

@ -0,0 +1,25 @@
[Unit]
Description=BigBlueButton HTML5 service, frontend instance %i
Requires=bbb-html5.service
Before=bbb-html5.service
BindsTo=bbb-html5.service
[Service]
PermissionsStartOnly=true
#Type=simple
Type=idle
EnvironmentFile=/usr/share/meteor/bundle/bbb-html5-with-roles.conf
ExecStart=/usr/share/meteor/bundle/systemd_start_frontend.sh %i
WorkingDirectory=/usr/share/meteor/bundle
StandardOutput=syslog
StandardError=syslog
TimeoutStartSec=10
RestartSec=10
User=meteor
Group=meteor
CPUSchedulingPolicy=fifo
Nice=19
[Install]
WantedBy=bbb-html5.service

View File

@ -0,0 +1,13 @@
upstream poolhtml5servers {
zone poolhtml5servers 32k;
least_conn;
server 127.0.0.1:4100 fail_timeout=5s max_fails=3;
server 127.0.0.1:4101 fail_timeout=5s max_fails=3;
server 127.0.0.1:4102 fail_timeout=5s max_fails=3;
server 127.0.0.1:4103 fail_timeout=5s max_fails=3;
server 127.0.0.1:4104 fail_timeout=5s max_fails=3;
server 127.0.0.1:4105 fail_timeout=5s max_fails=3;
server 127.0.0.1:4106 fail_timeout=5s max_fails=3;
server 127.0.0.1:4107 fail_timeout=5s max_fails=3;
}

View File

@ -0,0 +1,9 @@
# Default = 1; Min = 1; Max = 4
# On powerful systems with high number of meetings you can set values up to 4 to accelerate handling of events
NUMBER_OF_BACKEND_NODEJS_PROCESSES=2
# Default = 1; Min = 0; Max = 8
# If 0 is set, bbb-html5 will handle both backend and frontend roles in one process (default until Feb 2021)
# Set a number between 1 and 4 times the value of NUMBER_OF_BACKEND_NODEJS_PROCESSES where higher number helps with meetings
# stretching the recommended number of users in BigBlueButton
NUMBER_OF_FRONTEND_NODEJS_PROCESSES=2

View File

@ -0,0 +1,26 @@
[Unit]
Description=BigBlueButton HTML5 service, instance %i
Requires=bbb-html5.service
Before=bbb-html5.service
BindsTo=bbb-html5.service
[Service]
PermissionsStartOnly=true
#Type=simple
Type=idle
EnvironmentFile=/usr/share/meteor/bundle/bbb-html5.conf
ExecStart=/usr/share/meteor/bundle/systemd_start.sh %i $INSTANCE_MAX
WorkingDirectory=/usr/share/meteor/bundle
StandardOutput=syslog
StandardError=syslog
TimeoutStartSec=10
RestartSec=10
User=meteor
Group=meteor
CPUSchedulingPolicy=fifo
Nice=19
[Install]
WantedBy=bbb-html5.service

View File

@ -0,0 +1,4 @@
INSTANCE_MIN=1
INSTANCE_MAX=4
DESIRED_INSTANCE_COUNT=1

View File

@ -0,0 +1,27 @@
location /html5client/locales {
alias /usr/share/meteor/bundle/programs/web.browser/app/locales;
}
location /html5client/compatibility {
alias /usr/share/meteor/bundle/programs/web.browser/app/compatibility;
}
location /html5client/resources {
alias /usr/share/meteor/bundle/programs/web.browser/app/resources;
}
location /html5client/svgs {
alias /usr/share/meteor/bundle/programs/web.browser/app/svgs;
}
location /html5client/fonts {
alias /usr/share/meteor/bundle/programs/web.browser/app/fonts;
}
location ~ ^/html5client/ {
# proxy_pass http://127.0.0.1:4100; # use for development
proxy_pass http://poolhtml5servers; # use for production
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}

Some files were not shown because too many files have changed in this diff Show More