Merge branch 'signalwire:master' into master

This commit is contained in:
Howell Yan 2024-08-25 21:49:21 +08:00 committed by GitHub
commit b039837a6d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
100 changed files with 2658 additions and 13883 deletions

View File

@ -1,183 +0,0 @@
---
kind: pipeline
name: unit-tests
steps:
- name: bootstrap
image: signalwire/freeswitch-public-base:bullseye
pull: always
commands:
- cat /proc/sys/kernel/core_pattern
- ./bootstrap.sh -j
- name: configure
image: signalwire/freeswitch-public-base:bullseye
pull: always
environment:
REPOTOKEN:
from_secret: repotoken
commands:
- echo "machine freeswitch.signalwire.com password $REPOTOKEN" > /etc/apt/auth.conf
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -yq remove libsofia-sip-ua0 libspandsp-dev
- DEBIAN_FRONTEND=noninteractive apt-get -yq install libspandsp3-dev
- export REPOTOKEN=''
- rm -rf /etc/apt/auth.conf
- git clone https://github.com/freeswitch/sofia-sip.git
- cd sofia-sip && ./autogen.sh && ./configure.gnu && make -j`nproc` && make install && cd ..
- echo 'codecs/mod_openh264' >> modules.conf
- sed -i '/applications\\/mod_http_cache/s/^#//g' modules.conf
- sed -i '/event_handlers\\/mod_rayo/s/^#//g' modules.conf
- sed -i '/formats\\/mod_opusfile/s/^#//g' modules.conf
- sed -i '/languages\\/mod_lua/s/^#//g' modules.conf
- export ASAN_OPTIONS=log_path=stdout:disable_coredump=0:unmap_shadow_on_exit=1:fast_unwind_on_malloc=0
- ./configure --enable-address-sanitizer --enable-fake-dlclose
- name: build
image: signalwire/freeswitch-public-base:bullseye
pull: always
environment:
REPOTOKEN:
from_secret: repotoken
commands:
- echo "machine freeswitch.signalwire.com password $REPOTOKEN" > /etc/apt/auth.conf
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -yq remove libsofia-sip-ua0 libspandsp-dev
- DEBIAN_FRONTEND=noninteractive apt-get -yq install libspandsp3-dev
- export REPOTOKEN=''
- rm -rf /etc/apt/auth.conf
- cd sofia-sip && make install && cd ..
- echo '#!/bin/bash\nmake -j`nproc --all` |& tee ./unit-tests-build-result.txt\nexitstatus=$${PIPESTATUS[0]}\necho $$exitstatus > ./build-status.txt\n' > build.sh
- chmod +x build.sh
- ./build.sh
- name: run-tests
image: signalwire/freeswitch-public-base:bullseye
pull: always
environment:
REPOTOKEN:
from_secret: repotoken
commands:
- echo "machine freeswitch.signalwire.com password $REPOTOKEN" > /etc/apt/auth.conf
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -yq remove libsofia-sip-ua0 libspandsp-dev
- DEBIAN_FRONTEND=noninteractive apt-get -yq install libspandsp3-dev
- export REPOTOKEN=''
- rm -rf /etc/apt/auth.conf
- cd sofia-sip && make install && cd ..
- make install || true
- cd tests/unit
- export ASAN_OPTIONS=log_path=stdout:disable_coredump=0:unmap_shadow_on_exit=1:fast_unwind_on_malloc=0
- ./run-tests.sh
- ls -la /cores
- mkdir logs && (mv log_run-tests_*.html logs || true) && (mv backtrace_*.txt logs || true)
- echo 0 > run-tests-status.txt
- ./collect-test-logs.sh && exit 0 || echo 'Some tests failed'
- echo 1 > run-tests-status.txt
- cd logs && ls -la
- name: notify
image: signalwire/drone-notify
pull: always
environment:
SLACK_WEBHOOK_URL:
from_secret: slack_webhook_url
ENV_FILE:
from_secret: notify_env
commands:
- /root/unit-tests-notify.sh
trigger:
branch:
- master
event:
- pull_request
- push
---
kind: pipeline
name: scan-build
steps:
- name: bootstrap
image: signalwire/freeswitch-public-base:bullseye
pull: always
commands:
- ./bootstrap.sh -j
- name: configure
image: signalwire/freeswitch-public-base:bullseye
pull: always
environment:
REPOTOKEN:
from_secret: repotoken
commands:
- echo "machine freeswitch.signalwire.com password $REPOTOKEN" > /etc/apt/auth.conf
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -yq remove libspandsp-dev
- DEBIAN_FRONTEND=noninteractive apt-get -yq install libsofia-sip-ua-dev libspandsp3-dev
- export REPOTOKEN=''
- rm -rf /etc/apt/auth.conf
- cp build/modules.conf.most modules.conf
#Enable/Uncomment mods
- echo 'codecs/mod_openh264' >> modules.conf
- sed -i "/mod_mariadb/s/^#//g" modules.conf
- sed -i "/mod_v8/s/^#//g" modules.conf
#Disable/Comment out mods
- sed -i '/mod_ilbc/s/^/#/g' modules.conf
- sed -i '/mod_isac/s/^/#/g' modules.conf
- sed -i '/mod_mp4/s/^/#/g' modules.conf
- sed -i '/mod_mongo/s/^/#/g' modules.conf
- sed -i '/mod_pocketsphinx/s/^/#/g' modules.conf
- sed -i '/mod_sangoma_codec/s/^/#/g' modules.conf
- sed -i '/mod_siren/s/^/#/g' modules.conf
#Comment out mods for a while
- sed -i '/mod_avmd/s/^/#/g' modules.conf
- sed -i '/mod_basic/s/^/#/g' modules.conf
- sed -i '/mod_cdr_mongodb/s/^/#/g' modules.conf
- sed -i '/mod_cv/s/^/#/g' modules.conf
- sed -i '/mod_erlang_event/s/^/#/g' modules.conf
- sed -i '/mod_perl/s/^/#/g' modules.conf
- sed -i '/mod_rtmp/s/^/#/g' modules.conf
- sed -i '/mod_unimrcp/s/^/#/g' modules.conf
- sed -i '/mod_xml_rpc/s/^/#/g' modules.conf
- ./configure
- name: scan-build
image: signalwire/freeswitch-public-base:bullseye
pull: always
environment:
REPOTOKEN:
from_secret: repotoken
commands:
- echo "machine freeswitch.signalwire.com password $REPOTOKEN" > /etc/apt/auth.conf
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -yq remove libspandsp-dev
- DEBIAN_FRONTEND=noninteractive apt-get -yq install libsofia-sip-ua-dev libspandsp3-dev
- export REPOTOKEN=''
- rm -rf /etc/apt/auth.conf
- mkdir -p scan-build
- echo '#!/bin/bash\nscan-build-11 -o ./scan-build/ make -j`nproc --all` |& tee ./scan-build-result.txt\nexitstatus=$${PIPESTATUS[0]}\necho $$exitstatus > ./scan-build-status.txt\n' > scan.sh
- chmod +x scan.sh
- ./scan.sh
- exitstatus=`cat ./scan-build-status.txt`
- echo "*** Exit status is $exitstatus"
- name: notify
image: signalwire/drone-notify
pull: always
environment:
SLACK_WEBHOOK_URL:
from_secret: slack_webhook_url
ENV_FILE:
from_secret: notify_env
commands:
- /root/scan-build-notify.sh
trigger:
branch:
- master
event:
- pull_request
- push
---
kind: signature
hmac: 780e4aaee61e3683ea4a8d6fe5131f7c9e62ebad727546013f18df0fca80d705
...

View File

@ -0,0 +1,103 @@
ARG BUILDER_IMAGE=debian:bookworm-20240513
FROM ${BUILDER_IMAGE} AS builder
ARG MAINTAINER_NAME="Andrey Volk"
ARG MAINTAINER_EMAIL="andrey@signalwire.com"
# Credentials
ARG REPO_DOMAIN=freeswitch.signalwire.com
ARG REPO_USERNAME=user
ARG BUILD_NUMBER=42
ARG GIT_SHA=0000000000
ARG DATA_DIR=/data
ARG CODENAME=bookworm
ARG GPG_KEY="/usr/share/keyrings/signalwire-freeswitch-repo.gpg"
MAINTAINER "${MAINTAINER_NAME} <${MAINTAINER_EMAIL}>"
SHELL ["/bin/bash", "-c"]
RUN apt-get -q update && \
DEBIAN_FRONTEND=noninteractive apt-get -yq install \
apt-transport-https \
build-essential \
ca-certificates \
cmake \
curl \
debhelper \
devscripts \
dh-autoreconf \
dos2unix \
doxygen \
git \
graphviz \
libglib2.0-dev \
libssl-dev \
lsb-release \
pkg-config \
wget
RUN update-ca-certificates --fresh
RUN echo "export CODENAME=${CODENAME}" | tee ~/.env && \
chmod +x ~/.env
RUN . ~/.env && cat <<EOF > /etc/apt/sources.list.d/freeswitch.list
deb [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/debian-unstable ${CODENAME} main
deb-src [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/debian-unstable ${CODENAME} main
EOF
RUN git config --global --add safe.directory '*' \
&& git config --global user.name "${MAINTAINER_NAME}" \
&& git config --global user.email "${MAINTAINER_EMAIL}"
# Bootstrap and Build
COPY . ${DATA_DIR}
WORKDIR ${DATA_DIR}
RUN echo "export VERSION=$(cat ./build/next-release.txt | tr -d '\n')" | tee -a ~/.env
RUN . ~/.env && ./debian/util.sh prep-create-orig -n -V${VERSION}-${BUILD_NUMBER}-${GIT_SHA} -x
RUN . ~/.env && ./debian/util.sh prep-create-dsc ${CODENAME}
RUN --mount=type=secret,id=REPO_PASSWORD,required=true \
printf "machine ${REPO_DOMAIN} " > /etc/apt/auth.conf && \
printf "login ${REPO_USERNAME} " >> /etc/apt/auth.conf && \
printf "password " >> /etc/apt/auth.conf && \
cat /run/secrets/REPO_PASSWORD >> /etc/apt/auth.conf && \
sha512sum /run/secrets/REPO_PASSWORD && \
curl \
--fail \
--netrc-file /etc/apt/auth.conf \
--output ${GPG_KEY} \
https://${REPO_DOMAIN}/repo/deb/debian-unstable/signalwire-freeswitch-repo.gpg && \
file ${GPG_KEY} && \
apt-get --quiet update && \
mk-build-deps \
--install \
--remove debian/control \
--tool "apt-get --yes --no-install-recommends" && \
apt-get --yes --fix-broken install && \
rm -f /etc/apt/auth.conf
ENV DEB_BUILD_OPTIONS="parallel=1"
RUN . ~/.env && dch -b -M -v "${VERSION}-${BUILD_NUMBER}-${GIT_SHA}~${CODENAME}" \
--force-distribution -D "${CODENAME}" "Nightly build, ${GIT_SHA}"
RUN . ~/.env && ./debian/util.sh create-orig -n -V${VERSION}-${BUILD_NUMBER}-${GIT_SHA} -x
RUN dpkg-source \
--diff-ignore=.* \
--compression=xz \
--compression-level=9 \
--build \
. \
&& debuild -b -us -uc \
&& mkdir OUT \
&& mv -v ../*.{deb,dsc,changes,tar.*} OUT/.
# Artifacts image (mandatory part, the resulting image must have a single filesystem layer)
FROM scratch
COPY --from=builder /data/OUT/ /

View File

@ -0,0 +1,102 @@
ARG BUILDER_IMAGE=arm32v7/debian:bookworm-20240513
FROM --platform=linux/arm32 ${BUILDER_IMAGE} AS builder
ARG MAINTAINER_NAME="Andrey Volk"
ARG MAINTAINER_EMAIL="andrey@signalwire.com"
# Credentials
ARG REPO_DOMAIN=freeswitch.signalwire.com
ARG REPO_USERNAME=user
ARG BUILD_NUMBER=42
ARG GIT_SHA=0000000000
ARG DATA_DIR=/data
ARG CODENAME=bookworm
ARG GPG_KEY="/usr/share/keyrings/signalwire-freeswitch-repo.gpg"
MAINTAINER "${MAINTAINER_NAME} <${MAINTAINER_EMAIL}>"
SHELL ["/bin/bash", "-c"]
RUN apt-get -q update && \
DEBIAN_FRONTEND=noninteractive apt-get -yq install \
apt-transport-https \
build-essential \
ca-certificates \
cmake \
curl \
debhelper \
devscripts \
dh-autoreconf \
dos2unix \
doxygen \
git \
graphviz \
libglib2.0-dev \
libssl-dev \
lsb-release \
pkg-config \
wget
RUN update-ca-certificates --fresh
RUN echo "export CODENAME=${CODENAME}" | tee ~/.env && \
chmod +x ~/.env
RUN . ~/.env && cat <<EOF > /etc/apt/sources.list.d/freeswitch.list
deb [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/rpi/debian-dev ${CODENAME} main
deb-src [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/rpi/debian-dev ${CODENAME} main
EOF
RUN git config --global --add safe.directory '*' \
&& git config --global user.name "${MAINTAINER_NAME}" \
&& git config --global user.email "${MAINTAINER_EMAIL}"
# Bootstrap and Build
COPY . ${DATA_DIR}
WORKDIR ${DATA_DIR}
RUN echo "export VERSION=$(cat ./build/next-release.txt | tr -d '\n')" | tee -a ~/.env
RUN . ~/.env && ./debian/util.sh prep-create-orig -n -V${VERSION}-${BUILD_NUMBER}-${GIT_SHA} -x
RUN . ~/.env && ./debian/util.sh prep-create-dsc -a armhf ${CODENAME}
RUN --mount=type=secret,id=REPO_PASSWORD,required=true \
printf "machine ${REPO_DOMAIN} " > /etc/apt/auth.conf && \
printf "login ${REPO_USERNAME} " >> /etc/apt/auth.conf && \
printf "password " >> /etc/apt/auth.conf && \
cat /run/secrets/REPO_PASSWORD >> /etc/apt/auth.conf && \
sha512sum /run/secrets/REPO_PASSWORD && \
curl \
--fail \
--netrc-file /etc/apt/auth.conf \
--output ${GPG_KEY} \
https://${REPO_DOMAIN}/repo/deb/rpi/debian-dev/signalwire-freeswitch-repo.gpg && \
file ${GPG_KEY} && \
apt-get --quiet update && \
mk-build-deps \
--install \
--remove debian/control \
--tool "apt-get --yes --no-install-recommends" && \
apt-get --yes --fix-broken install && \
rm -f /etc/apt/auth.conf
ENV DEB_BUILD_OPTIONS="parallel=1"
RUN . ~/.env && dch -b -M -v "${VERSION}-${BUILD_NUMBER}-${GIT_SHA}~${CODENAME}" \
--force-distribution -D "${CODENAME}" "Nightly build, ${GIT_SHA}"
RUN . ~/.env && ./debian/util.sh create-orig -n -V${VERSION}-${BUILD_NUMBER}-${GIT_SHA} -x
RUN dpkg-source \
--diff-ignore=.* \
--compression=xz \
--compression-level=9 \
--build \
. \
&& debuild -b -us -uc \
&& mkdir OUT \
&& mv -v ../*.{deb,dsc,changes,tar.*} OUT/.
# Artifacts image (mandatory part, the resulting image must have a single filesystem layer)
FROM scratch
COPY --from=builder /data/OUT/ /

View File

@ -0,0 +1,102 @@
ARG BUILDER_IMAGE=arm64v8/debian:bookworm-20240513
FROM --platform=linux/arm64 ${BUILDER_IMAGE} AS builder
ARG MAINTAINER_NAME="Andrey Volk"
ARG MAINTAINER_EMAIL="andrey@signalwire.com"
# Credentials
ARG REPO_DOMAIN=freeswitch.signalwire.com
ARG REPO_USERNAME=user
ARG BUILD_NUMBER=42
ARG GIT_SHA=0000000000
ARG DATA_DIR=/data
ARG CODENAME=bookworm
ARG GPG_KEY="/usr/share/keyrings/signalwire-freeswitch-repo.gpg"
MAINTAINER "${MAINTAINER_NAME} <${MAINTAINER_EMAIL}>"
SHELL ["/bin/bash", "-c"]
RUN apt-get -q update && \
DEBIAN_FRONTEND=noninteractive apt-get -yq install \
apt-transport-https \
build-essential \
ca-certificates \
cmake \
curl \
debhelper \
devscripts \
dh-autoreconf \
dos2unix \
doxygen \
git \
graphviz \
libglib2.0-dev \
libssl-dev \
lsb-release \
pkg-config \
wget
RUN update-ca-certificates --fresh
RUN echo "export CODENAME=${CODENAME}" | tee ~/.env && \
chmod +x ~/.env
RUN . ~/.env && cat <<EOF > /etc/apt/sources.list.d/freeswitch.list
deb [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/debian-unstable ${CODENAME} main
deb-src [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/debian-unstable ${CODENAME} main
EOF
RUN git config --global --add safe.directory '*' \
&& git config --global user.name "${MAINTAINER_NAME}" \
&& git config --global user.email "${MAINTAINER_EMAIL}"
# Bootstrap and Build
COPY . ${DATA_DIR}
WORKDIR ${DATA_DIR}
RUN echo "export VERSION=$(cat ./build/next-release.txt | tr -d '\n')" | tee -a ~/.env
RUN . ~/.env && ./debian/util.sh prep-create-orig -n -V${VERSION}-${BUILD_NUMBER}-${GIT_SHA} -x
RUN . ~/.env && ./debian/util.sh prep-create-dsc -a arm64 ${CODENAME}
RUN --mount=type=secret,id=REPO_PASSWORD,required=true \
printf "machine ${REPO_DOMAIN} " > /etc/apt/auth.conf && \
printf "login ${REPO_USERNAME} " >> /etc/apt/auth.conf && \
printf "password " >> /etc/apt/auth.conf && \
cat /run/secrets/REPO_PASSWORD >> /etc/apt/auth.conf && \
sha512sum /run/secrets/REPO_PASSWORD && \
curl \
--fail \
--netrc-file /etc/apt/auth.conf \
--output ${GPG_KEY} \
https://${REPO_DOMAIN}/repo/deb/debian-unstable/signalwire-freeswitch-repo.gpg && \
file ${GPG_KEY} && \
apt-get --quiet update && \
mk-build-deps \
--install \
--remove debian/control \
--tool "apt-get --yes --no-install-recommends" && \
apt-get --yes --fix-broken install && \
rm -f /etc/apt/auth.conf
ENV DEB_BUILD_OPTIONS="parallel=1"
RUN . ~/.env && dch -b -M -v "${VERSION}-${BUILD_NUMBER}-${GIT_SHA}~${CODENAME}" \
--force-distribution -D "${CODENAME}" "Nightly build, ${GIT_SHA}"
RUN . ~/.env && ./debian/util.sh create-orig -n -V${VERSION}-${BUILD_NUMBER}-${GIT_SHA} -x
RUN dpkg-source \
--diff-ignore=.* \
--compression=xz \
--compression-level=9 \
--build \
. \
&& debuild -b -us -uc \
&& mkdir OUT \
&& mv -v ../*.{deb,dsc,changes,tar.*} OUT/.
# Artifacts image (mandatory part, the resulting image must have a single filesystem layer)
FROM scratch
COPY --from=builder /data/OUT/ /

View File

@ -0,0 +1,102 @@
ARG BUILDER_IMAGE=debian:bullseye-20240513
FROM ${BUILDER_IMAGE} AS builder
ARG MAINTAINER_NAME="Andrey Volk"
ARG MAINTAINER_EMAIL="andrey@signalwire.com"
# Credentials
ARG REPO_DOMAIN=freeswitch.signalwire.com
ARG REPO_USERNAME=user
ARG BUILD_NUMBER=42
ARG GIT_SHA=0000000000
ARG DATA_DIR=/data
ARG CODENAME=bullseye
ARG GPG_KEY="/usr/share/keyrings/signalwire-freeswitch-repo.gpg"
MAINTAINER "${MAINTAINER_NAME} <${MAINTAINER_EMAIL}>"
SHELL ["/bin/bash", "-c"]
RUN apt-get -q update && \
DEBIAN_FRONTEND=noninteractive apt-get -yq install \
apt-transport-https \
build-essential \
ca-certificates \
cmake \
curl \
debhelper \
devscripts \
dh-autoreconf \
dos2unix \
doxygen \
git \
graphviz \
libglib2.0-dev \
libssl-dev \
lsb-release \
pkg-config \
wget
RUN update-ca-certificates --fresh
RUN echo "export CODENAME=${CODENAME}" | tee ~/.env && \
chmod +x ~/.env
RUN . ~/.env && cat <<EOF > /etc/apt/sources.list.d/freeswitch.list
deb [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/debian-unstable ${CODENAME} main
deb-src [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/debian-unstable ${CODENAME} main
EOF
RUN git config --global --add safe.directory '*' \
&& git config --global user.name "${MAINTAINER_NAME}" \
&& git config --global user.email "${MAINTAINER_EMAIL}"
# Bootstrap and Build
COPY . ${DATA_DIR}
WORKDIR ${DATA_DIR}
RUN echo "export VERSION=$(cat ./build/next-release.txt | tr -d '\n')" | tee -a ~/.env
RUN . ~/.env && ./debian/util.sh prep-create-orig -n -V${VERSION}-${BUILD_NUMBER}-${GIT_SHA} -x
RUN . ~/.env && ./debian/util.sh prep-create-dsc ${CODENAME}
RUN --mount=type=secret,id=REPO_PASSWORD,required=true \
printf "machine ${REPO_DOMAIN} " > /etc/apt/auth.conf && \
printf "login ${REPO_USERNAME} " >> /etc/apt/auth.conf && \
printf "password " >> /etc/apt/auth.conf && \
cat /run/secrets/REPO_PASSWORD >> /etc/apt/auth.conf && \
sha512sum /run/secrets/REPO_PASSWORD && \
curl \
--fail \
--netrc-file /etc/apt/auth.conf \
--output ${GPG_KEY} \
https://${REPO_DOMAIN}/repo/deb/debian-unstable/signalwire-freeswitch-repo.gpg && \
file ${GPG_KEY} && \
apt-get --quiet update && \
mk-build-deps \
--install \
--remove debian/control \
--tool "apt-get --yes --no-install-recommends" && \
apt-get --yes --fix-broken install && \
rm -f /etc/apt/auth.conf
ENV DEB_BUILD_OPTIONS="parallel=1"
RUN . ~/.env && dch -b -M -v "${VERSION}-${BUILD_NUMBER}-${GIT_SHA}~${CODENAME}" \
--force-distribution -D "${CODENAME}" "Nightly build, ${GIT_SHA}"
RUN . ~/.env && ./debian/util.sh create-orig -n -V${VERSION}-${BUILD_NUMBER}-${GIT_SHA} -x
RUN dpkg-source \
--diff-ignore=.* \
--compression=xz \
--compression-level=9 \
--build \
. \
&& debuild -b -us -uc \
&& mkdir OUT \
&& mv -v ../*.{deb,dsc,changes,tar.*} OUT/.
# Artifacts image (mandatory part, the resulting image must have a single filesystem layer)
FROM scratch
COPY --from=builder /data/OUT/ /

View File

@ -0,0 +1,102 @@
ARG BUILDER_IMAGE=arm32v7/debian:bullseye-20240513
FROM --platform=linux/arm32 ${BUILDER_IMAGE} AS builder
ARG MAINTAINER_NAME="Andrey Volk"
ARG MAINTAINER_EMAIL="andrey@signalwire.com"
# Credentials
ARG REPO_DOMAIN=freeswitch.signalwire.com
ARG REPO_USERNAME=user
ARG BUILD_NUMBER=42
ARG GIT_SHA=0000000000
ARG DATA_DIR=/data
ARG CODENAME=bullseye
ARG GPG_KEY="/usr/share/keyrings/signalwire-freeswitch-repo.gpg"
MAINTAINER "${MAINTAINER_NAME} <${MAINTAINER_EMAIL}>"
SHELL ["/bin/bash", "-c"]
RUN apt-get -q update && \
DEBIAN_FRONTEND=noninteractive apt-get -yq install \
apt-transport-https \
build-essential \
ca-certificates \
cmake \
curl \
debhelper \
devscripts \
dh-autoreconf \
dos2unix \
doxygen \
git \
graphviz \
libglib2.0-dev \
libssl-dev \
lsb-release \
pkg-config \
wget
RUN update-ca-certificates --fresh
RUN echo "export CODENAME=${CODENAME}" | tee ~/.env && \
chmod +x ~/.env
RUN . ~/.env && cat <<EOF > /etc/apt/sources.list.d/freeswitch.list
deb [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/rpi/debian-dev ${CODENAME} main
deb-src [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/rpi/debian-dev ${CODENAME} main
EOF
RUN git config --global --add safe.directory '*' \
&& git config --global user.name "${MAINTAINER_NAME}" \
&& git config --global user.email "${MAINTAINER_EMAIL}"
# Bootstrap and Build
COPY . ${DATA_DIR}
WORKDIR ${DATA_DIR}
RUN echo "export VERSION=$(cat ./build/next-release.txt | tr -d '\n')" | tee -a ~/.env
RUN . ~/.env && ./debian/util.sh prep-create-orig -n -V${VERSION}-${BUILD_NUMBER}-${GIT_SHA} -x
RUN . ~/.env && ./debian/util.sh prep-create-dsc -a armhf ${CODENAME}
RUN --mount=type=secret,id=REPO_PASSWORD,required=true \
printf "machine ${REPO_DOMAIN} " > /etc/apt/auth.conf && \
printf "login ${REPO_USERNAME} " >> /etc/apt/auth.conf && \
printf "password " >> /etc/apt/auth.conf && \
cat /run/secrets/REPO_PASSWORD >> /etc/apt/auth.conf && \
sha512sum /run/secrets/REPO_PASSWORD && \
curl \
--fail \
--netrc-file /etc/apt/auth.conf \
--output ${GPG_KEY} \
https://${REPO_DOMAIN}/repo/deb/rpi/debian-dev/signalwire-freeswitch-repo.gpg && \
file ${GPG_KEY} && \
apt-get --quiet update && \
mk-build-deps \
--install \
--remove debian/control \
--tool "apt-get --yes --no-install-recommends" && \
apt-get --yes --fix-broken install && \
rm -f /etc/apt/auth.conf
ENV DEB_BUILD_OPTIONS="parallel=1"
RUN . ~/.env && dch -b -M -v "${VERSION}-${BUILD_NUMBER}-${GIT_SHA}~${CODENAME}" \
--force-distribution -D "${CODENAME}" "Nightly build, ${GIT_SHA}"
RUN . ~/.env && ./debian/util.sh create-orig -n -V${VERSION}-${BUILD_NUMBER}-${GIT_SHA} -x
RUN dpkg-source \
--diff-ignore=.* \
--compression=xz \
--compression-level=9 \
--build \
. \
&& debuild -b -us -uc \
&& mkdir OUT \
&& mv -v ../*.{deb,dsc,changes,tar.*} OUT/.
# Artifacts image (mandatory part, the resulting image must have a single filesystem layer)
FROM scratch
COPY --from=builder /data/OUT/ /

View File

@ -0,0 +1,102 @@
ARG BUILDER_IMAGE=arm64v8/debian:bullseye-20240513
FROM --platform=linux/arm64 ${BUILDER_IMAGE} AS builder
ARG MAINTAINER_NAME="Andrey Volk"
ARG MAINTAINER_EMAIL="andrey@signalwire.com"
# Credentials
ARG REPO_DOMAIN=freeswitch.signalwire.com
ARG REPO_USERNAME=user
ARG BUILD_NUMBER=42
ARG GIT_SHA=0000000000
ARG DATA_DIR=/data
ARG CODENAME=bullseye
ARG GPG_KEY="/usr/share/keyrings/signalwire-freeswitch-repo.gpg"
MAINTAINER "${MAINTAINER_NAME} <${MAINTAINER_EMAIL}>"
SHELL ["/bin/bash", "-c"]
RUN apt-get -q update && \
DEBIAN_FRONTEND=noninteractive apt-get -yq install \
apt-transport-https \
build-essential \
ca-certificates \
cmake \
curl \
debhelper \
devscripts \
dh-autoreconf \
dos2unix \
doxygen \
git \
graphviz \
libglib2.0-dev \
libssl-dev \
lsb-release \
pkg-config \
wget
RUN update-ca-certificates --fresh
RUN echo "export CODENAME=${CODENAME}" | tee ~/.env && \
chmod +x ~/.env
RUN . ~/.env && cat <<EOF > /etc/apt/sources.list.d/freeswitch.list
deb [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/debian-unstable ${CODENAME} main
deb-src [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/debian-unstable ${CODENAME} main
EOF
RUN git config --global --add safe.directory '*' \
&& git config --global user.name "${MAINTAINER_NAME}" \
&& git config --global user.email "${MAINTAINER_EMAIL}"
# Bootstrap and Build
COPY . ${DATA_DIR}
WORKDIR ${DATA_DIR}
RUN echo "export VERSION=$(cat ./build/next-release.txt | tr -d '\n')" | tee -a ~/.env
RUN . ~/.env && ./debian/util.sh prep-create-orig -n -V${VERSION}-${BUILD_NUMBER}-${GIT_SHA} -x
RUN . ~/.env && ./debian/util.sh prep-create-dsc -a arm64 ${CODENAME}
RUN --mount=type=secret,id=REPO_PASSWORD,required=true \
printf "machine ${REPO_DOMAIN} " > /etc/apt/auth.conf && \
printf "login ${REPO_USERNAME} " >> /etc/apt/auth.conf && \
printf "password " >> /etc/apt/auth.conf && \
cat /run/secrets/REPO_PASSWORD >> /etc/apt/auth.conf && \
sha512sum /run/secrets/REPO_PASSWORD && \
curl \
--fail \
--netrc-file /etc/apt/auth.conf \
--output ${GPG_KEY} \
https://${REPO_DOMAIN}/repo/deb/debian-unstable/signalwire-freeswitch-repo.gpg && \
file ${GPG_KEY} && \
apt-get --quiet update && \
mk-build-deps \
--install \
--remove debian/control \
--tool "apt-get --yes --no-install-recommends" && \
apt-get --yes --fix-broken install && \
rm -f /etc/apt/auth.conf
ENV DEB_BUILD_OPTIONS="parallel=1"
RUN . ~/.env && dch -b -M -v "${VERSION}-${BUILD_NUMBER}-${GIT_SHA}~${CODENAME}" \
--force-distribution -D "${CODENAME}" "Nightly build, ${GIT_SHA}"
RUN . ~/.env && ./debian/util.sh create-orig -n -V${VERSION}-${BUILD_NUMBER}-${GIT_SHA} -x
RUN dpkg-source \
--diff-ignore=.* \
--compression=xz \
--compression-level=9 \
--build \
. \
&& debuild -b -us -uc \
&& mkdir OUT \
&& mv -v ../*.{deb,dsc,changes,tar.*} OUT/.
# Artifacts image (mandatory part, the resulting image must have a single filesystem layer)
FROM scratch
COPY --from=builder /data/OUT/ /

113
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,113 @@
name: Build and Distribute
on:
pull_request:
push:
branches:
- master
- v1.10
paths:
- "**"
workflow_dispatch:
concurrency:
group: ${{ github.head_ref || github.ref }}
jobs:
excludes:
name: 'Excludes'
# if: github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
outputs:
deb: ${{ steps.deb.outputs.excludes }}
steps:
- id: deb
name: Generate Matrix excludes for DEB
run: |
JSON="[]"
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
JSON=$(jq -n '[
{
"version": "bookworm",
"platform": {
"name": "arm64v8"
}
},
{
"version": "bullseye",
"platform": {
"name": "amd64"
}
},
{
"version": "bullseye",
"platform": {
"name": "arm32v7"
}
}
]')
fi
echo "excludes=$(echo $JSON | jq -c .)" | tee -a $GITHUB_OUTPUT
deb:
name: 'DEB'
# if: github.event.pull_request.head.repo.full_name == github.repository
permissions:
id-token: write
contents: read
needs:
- excludes
uses: signalwire/actions-template/.github/workflows/cicd-docker-build-and-distribute.yml@main
strategy:
# max-parallel: 1
fail-fast: false
matrix:
os:
- debian
version:
- bookworm
- bullseye
platform:
- name: amd64
runner: ubuntu-latest
- name: arm32v7
runner: linux-arm64-4-core-public
- name: arm64v8
runner: linux-arm64-4-core-public
exclude: ${{ fromJson(needs.excludes.outputs.deb) }}
with:
RUNNER: ${{ matrix.platform.runner }}
ARTIFACTS_PATTERN: '.*\.(deb|dsc|changes|tar.bz2|tar.gz|tar.lzma|tar.xz)$'
DOCKERFILE: .github/docker/${{ matrix.os }}/${{ matrix.version }}/${{ matrix.platform.name }}/Dockerfile
MAINTAINER: 'Andrey Volk <andrey@signalwire.com>'
META_FILE_PATH_PREFIX: /var/www/freeswitch/${{ github.ref_name }}/${{ github.run_id }}-${{ github.run_number }}
PLATFORM: ${{ matrix.platform.name }}
REPO_DOMAIN: freeswitch.signalwire.com
TARGET_ARTIFACT_NAME: ${{ matrix.os }}-${{ matrix.version }}-${{ matrix.platform.name }}-artifact
UPLOAD_BUILD_ARTIFACTS: ${{ github.event_name != 'pull_request' || contains(github.event.pull_request.title, ':upload-artifacts') }}
secrets:
GH_BOT_DEPLOY_TOKEN: ${{ secrets.PAT }}
HOSTNAME: ${{ secrets.HOSTNAME }}
PROXY_URL: ${{ secrets.PROXY_URL }}
USERNAME: ${{ secrets.USERNAME }}
TELEPORT_TOKEN: ${{ secrets.TELEPORT_TOKEN }}
REPO_USERNAME: 'SWUSERNAME'
REPO_PASSWORD: ${{ secrets.REPOTOKEN }}
meta:
name: 'Publish build data to meta-repo'
if: ${{ github.event_name != 'pull_request' || contains(github.event.pull_request.title, ':upload-artifacts') }}
needs:
- deb
permissions:
id-token: write
contents: read
uses: signalwire/actions-template/.github/workflows/meta-repo-content.yml@main
with:
META_CONTENT: '/var/www/freeswitch/${{ github.ref_name }}/${{ github.run_id }}-${{ github.run_number }}'
META_REPO: signalwire/bamboo_gha_trigger
META_REPO_BRANCH: trigger/freeswitch/${{ github.ref_name }}
secrets:
GH_BOT_DEPLOY_TOKEN: ${{ secrets.PAT }}

2
.gitignore vendored
View File

@ -187,7 +187,7 @@ ipch/
/w32/Setup/obj /w32/Setup/obj
*dSYM* *dSYM*
/UpgradeLog.* /UpgradeLog*.*
/_UpgradeReport_Files/ /_UpgradeReport_Files/
*.aps *.aps
/w32/Library/switch_version.inc /w32/Library/switch_version.inc

View File

@ -554,6 +554,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_switch_core_db", "test
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_switch_ivr_originate", "tests\unit\test_switch_ivr_originate.2017.vcxproj", "{69A7464A-9B0D-4804-A108-835229DACF58}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_switch_ivr_originate", "tests\unit\test_switch_ivr_originate.2017.vcxproj", "{69A7464A-9B0D-4804-A108-835229DACF58}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_switch_core_codec", "tests\unit\test_switch_core_codec.2017.vcxproj", "{589A07E7-5DE5-49FD-A62C-27795B806AFB}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
All|Win32 = All|Win32 All|Win32 = All|Win32
@ -2516,6 +2518,18 @@ Global
{69A7464A-9B0D-4804-A108-835229DACF58}.Release|Win32.Build.0 = Release|Win32 {69A7464A-9B0D-4804-A108-835229DACF58}.Release|Win32.Build.0 = Release|Win32
{69A7464A-9B0D-4804-A108-835229DACF58}.Release|x64.ActiveCfg = Release|x64 {69A7464A-9B0D-4804-A108-835229DACF58}.Release|x64.ActiveCfg = Release|x64
{69A7464A-9B0D-4804-A108-835229DACF58}.Release|x64.Build.0 = Release|x64 {69A7464A-9B0D-4804-A108-835229DACF58}.Release|x64.Build.0 = Release|x64
{589A07E7-5DE5-49FD-A62C-27795B806AFB}.All|Win32.ActiveCfg = Debug|Win32
{589A07E7-5DE5-49FD-A62C-27795B806AFB}.All|Win32.Build.0 = Debug|Win32
{589A07E7-5DE5-49FD-A62C-27795B806AFB}.All|x64.ActiveCfg = Debug|x64
{589A07E7-5DE5-49FD-A62C-27795B806AFB}.All|x64.Build.0 = Debug|x64
{589A07E7-5DE5-49FD-A62C-27795B806AFB}.Debug|Win32.ActiveCfg = Debug|Win32
{589A07E7-5DE5-49FD-A62C-27795B806AFB}.Debug|Win32.Build.0 = Debug|Win32
{589A07E7-5DE5-49FD-A62C-27795B806AFB}.Debug|x64.ActiveCfg = Debug|x64
{589A07E7-5DE5-49FD-A62C-27795B806AFB}.Debug|x64.Build.0 = Debug|x64
{589A07E7-5DE5-49FD-A62C-27795B806AFB}.Release|Win32.ActiveCfg = Release|Win32
{589A07E7-5DE5-49FD-A62C-27795B806AFB}.Release|Win32.Build.0 = Release|Win32
{589A07E7-5DE5-49FD-A62C-27795B806AFB}.Release|x64.ActiveCfg = Release|x64
{589A07E7-5DE5-49FD-A62C-27795B806AFB}.Release|x64.Build.0 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -2714,6 +2728,7 @@ Global
{0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC} = {31C2761D-20E0-4BF8-98B9-E32F0D8DD6E1} {0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC} = {31C2761D-20E0-4BF8-98B9-E32F0D8DD6E1}
{580675D7-C1C9-4197-AAC5-00F64FAFDE78} = {9388C266-C3FC-468A-92EF-0CBC35941412} {580675D7-C1C9-4197-AAC5-00F64FAFDE78} = {9388C266-C3FC-468A-92EF-0CBC35941412}
{69A7464A-9B0D-4804-A108-835229DACF58} = {9388C266-C3FC-468A-92EF-0CBC35941412} {69A7464A-9B0D-4804-A108-835229DACF58} = {9388C266-C3FC-468A-92EF-0CBC35941412}
{589A07E7-5DE5-49FD-A62C-27795B806AFB} = {9388C266-C3FC-468A-92EF-0CBC35941412}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {09840DE7-9208-45AA-9667-1A71EE93BD1E} SolutionGuid = {09840DE7-9208-45AA-9667-1A71EE93BD1E}

View File

@ -110,7 +110,6 @@ event_handlers/mod_event_socket
#event_handlers/mod_json_cdr #event_handlers/mod_json_cdr
#event_handlers/mod_radius_cdr #event_handlers/mod_radius_cdr
#event_handlers/mod_odbc_cdr #event_handlers/mod_odbc_cdr
#event_handlers/mod_kazoo
#event_handlers/mod_rayo #event_handlers/mod_rayo
#event_handlers/mod_smpp #event_handlers/mod_smpp
#event_handlers/mod_snmp #event_handlers/mod_snmp

View File

@ -104,7 +104,6 @@ event_handlers/mod_event_multicast
event_handlers/mod_event_socket event_handlers/mod_event_socket
event_handlers/mod_format_cdr event_handlers/mod_format_cdr
event_handlers/mod_json_cdr event_handlers/mod_json_cdr
event_handlers/mod_kazoo
#event_handlers/mod_radius_cdr #event_handlers/mod_radius_cdr
event_handlers/mod_odbc_cdr event_handlers/mod_odbc_cdr
event_handlers/mod_rayo event_handlers/mod_rayo

View File

@ -1 +1 @@
1.10.11-dev 1.10.13-dev

View File

@ -1,215 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration name="kazoo.conf" description="General purpose Erlang c-node produced to better fit the Kazoo project">
<settings>
<param name="listen-ip" value="0.0.0.0" />
<param name="listen-port" value="8031" />
<!--<param name="cookie-file" value="/etc/freeswitch/autoload_configs/.erlang.cookie" />-->
<param name="cookie" value="change_me" />
<param name="shortname" value="false" />
<param name="nodename" value="freeswitch" />
<param name="send-msg-batch-size" value="10" />
<param name="receive-timeout" value="1" />
<!--<param name="receive-msg-preallocate" value="0" />-->
<!--<param name="event-stream-preallocate" value="0" />-->
<!--<param name="event-stream-framing" value="2" />-->
<!--<param name="kazoo-var-prefix" value="ecallmgr" />-->
<!--<param name="compat-rel" value="12"/> -->
</settings>
<event-filter type="whitelist">
<header name="Acquired-UUID" />
<header name="action" />
<header name="Action" />
<header name="alt_event_type" />
<header name="Answer-State" />
<header name="Application" />
<header name="Application-Data" />
<header name="Application-Name" />
<header name="Application-Response" />
<header name="att_xfer_replaced_by" />
<header name="Auth-Method" />
<header name="Auth-Realm" />
<header name="Auth-User" />
<header name="Bridge-A-Unique-ID" />
<header name="Bridge-B-Unique-ID" />
<header name="Call-Direction" />
<header name="Caller-Callee-ID-Name" />
<header name="Caller-Callee-ID-Number" />
<header name="Caller-Caller-ID-Name" />
<header name="Caller-Caller-ID-Number" />
<header name="Caller-Context" />
<header name="Caller-Controls" />
<header name="Caller-Destination-Number" />
<header name="Caller-Dialplan" />
<header name="Caller-Network-Addr" />
<header name="Caller-Unique-ID" />
<header name="Call-ID" />
<header name="Channel-Call-State" />
<header name="Channel-Call-UUID" />
<header name="Channel-Presence-ID" />
<header name="Channel-State" />
<header name="Chat-Permissions" />
<header name="Conference-Name" />
<header name="Conference-Profile-Name" />
<header name="Conference-Unique-ID" />
<header name="Conference-Size" />
<header name="New-ID" />
<header name="Old-ID" />
<header name="Detected-Tone" />
<header name="dialog_state" />
<header name="direction" />
<header name="Distributed-From" />
<header name="DTMF-Digit" />
<header name="DTMF-Duration" />
<header name="Event-Date-Timestamp" />
<header name="Event-Name" />
<header name="Event-Subclass" />
<header name="Expires" />
<header name="Ext-SIP-IP" />
<header name="File" />
<header name="FreeSWITCH-Hostname" />
<header name="from" />
<header name="Hunt-Destination-Number" />
<header name="ip" />
<header name="Message-Account" />
<header name="metadata" />
<header name="old_node_channel_uuid" />
<header name="Other-Leg-Callee-ID-Name" />
<header name="Other-Leg-Callee-ID-Number" />
<header name="Other-Leg-Caller-ID-Name" />
<header name="Other-Leg-Caller-ID-Number" />
<header name="Other-Leg-Destination-Number" />
<header name="Other-Leg-Direction" />
<header name="Other-Leg-Unique-ID" />
<header name="Participant-Type" />
<header name="Path" />
<header name="profile_name" />
<header name="Profiles" />
<header name="proto-specific-event-name" />
<header name="Raw-Application-Data" />
<header name="Resigning-UUID" />
<header name="set" />
<header name="sip_auto_answer" />
<header name="sip_auth_method" />
<header name="sip_from_host" />
<header name="sip_from_user" />
<header name="sip_to_host" />
<header name="sip_to_user" />
<header name="sub-call-id" />
<header name="technology" />
<header name="to" />
<header name="Unique-ID" />
<header name="URL" />
<header name="variable_channel_is_moving" />
<header name="variable_collected_digits" />
<header name="variable_current_application" />
<header name="variable_current_application_data" />
<header name="variable_domain_name" />
<header name="variable_effective_caller_id_name" />
<header name="variable_effective_caller_id_number" />
<header name="variable_fax_bad_rows" />
<header name="variable_fax_document_total_pages" />
<header name="variable_fax_document_transferred_pages" />
<header name="variable_fax_ecm_used" />
<header name="variable_fax_result_code" />
<header name="variable_fax_result_text" />
<header name="variable_fax_success" />
<header name="variable_fax_transfer_rate" />
<header name="variable_holding_uuid" />
<header name="variable_hold_music" />
<header name="variable_media_group_id" />
<header name="variable_originate_disposition" />
<header name="variable_playback_terminator_used" />
<header name="variable_presence_id" />
<header name="variable_record_ms" />
<header name="variable_recovered" />
<header name="variable_silence_hits_exhausted" />
<header name="variable_sip_auth_realm" />
<header name="variable_sip_from_host" />
<header name="variable_sip_from_user" />
<header name="variable_sip_h_X-AUTH-IP" />
<header name="variable_sip_received_ip" />
<header name="variable_sip_to_host" />
<header name="variable_sip_to_user" />
<header name="variable_sofia_profile_name" />
<header name="variable_transfer_history" />
<header name="variable_user_name" />
<header name="variable_endpoint_disposition" />
<header name="variable_originate_disposition" />
<header name="variable_bridge_hangup_cause" />
<header name="variable_hangup_cause" />
<header name="variable_last_bridge_proto_specific_hangup_cause" />
<header name="variable_proto_specific_hangup_cause" />
<header name="VM-Call-ID" />
<header name="VM-sub-call-id" />
<header name="whistle_application_name" />
<header name="whistle_application_response" />
<header name="whistle_event_name" />
<header name="sip_auto_answer_notify" />
<header name="eavesdrop_group" />
<header name="origination_caller_id_name" />
<header name="origination_caller_id_number" />
<header name="origination_callee_id_name" />
<header name="origination_callee_id_number" />
<header name="sip_auth_username" />
<header name="sip_auth_password" />
<header name="effective_caller_id_name" />
<header name="effective_caller_id_number" />
<header name="effective_callee_id_name" />
<header name="effective_callee_id_number" />
<!-- Registrations -->
<header name="call-id" />
<header name="profile-name" />
<header name="from-user" />
<header name="from-host" />
<header name="presence-hosts" />
<header name="contact" />
<header name="rpid" />
<header name="status" />
<header name="expires" />
<header name="to-user" />
<header name="to-host" />
<header name="network-ip" />
<header name="network-port" />
<header name="username" />
<header name="realm" />
<header name="user-agent" />
<!-- CDR Headers -->
<header name="Hangup-Cause" />
<header name="Unique-ID" />
<header name="variable_switch_r_sdp" />
<header name="variable_sip_local_sdp_str" />
<header name="variable_sip_to_uri" />
<header name="variable_sip_from_uri" />
<header name="variable_effective_caller_id_number" />
<header name="Caller-Caller-ID-Number" />
<header name="variable_effective_caller_id_name" />
<header name="Caller-Caller-ID-Name" />
<header name="Caller-Callee-ID-Name" />
<header name="Caller-Callee-ID-Number" />
<header name="Other-Leg-Unique-ID" />
<header name="variable_sip_user_agent" />
<header name="variable_duration" />
<header name="variable_billsec" />
<header name="variable_progresssec" />
<header name="variable_progress_uepoch" />
<header name="variable_progress_media_uepoch" />
<header name="variable_start_uepoch" />
<header name="variable_digits_dialed" />
<header name="variable_sip_cid_type" />
<!-- Conference Headers -->
<header name="Hear" />
<header name="Speak" />
<header name="Video" />
<header name="Talking" />
<header name="Mute-Detect" />
<header name="Member-ID" />
<header name="Member-Type" />
<header name="Energy-Level" />
<header name="Current-Energy" />
<header name="Floor" />
</event-filter>
</configuration>

View File

@ -3,10 +3,10 @@
# Must change all of the below together # Must change all of the below together
# For a release, set revision for that tagged release as well and uncomment # For a release, set revision for that tagged release as well and uncomment
AC_INIT([freeswitch], [1.10.11-dev], bugs@freeswitch.org) AC_INIT([freeswitch], [1.10.13-dev], bugs@freeswitch.org)
AC_SUBST(SWITCH_VERSION_MAJOR, [1]) AC_SUBST(SWITCH_VERSION_MAJOR, [1])
AC_SUBST(SWITCH_VERSION_MINOR, [10]) AC_SUBST(SWITCH_VERSION_MINOR, [10])
AC_SUBST(SWITCH_VERSION_MICRO, [11-dev]) AC_SUBST(SWITCH_VERSION_MICRO, [13-dev])
AC_SUBST(SWITCH_VERSION_REVISION, []) AC_SUBST(SWITCH_VERSION_REVISION, [])
AC_SUBST(SWITCH_VERSION_REVISION_HUMAN, []) AC_SUBST(SWITCH_VERSION_REVISION_HUMAN, [])
@ -716,7 +716,7 @@ PKG_CHECK_MODULES([SPANDSP], [spandsp >= 3.0],[
AC_MSG_ERROR([no usable spandsp; please install spandsp3 devel package or equivalent]) AC_MSG_ERROR([no usable spandsp; please install spandsp3 devel package or equivalent])
]) ])
PKG_CHECK_MODULES([SOFIA_SIP], [sofia-sip-ua >= 1.13.15],[ PKG_CHECK_MODULES([SOFIA_SIP], [sofia-sip-ua >= 1.13.17],[
AM_CONDITIONAL([HAVE_SOFIA_SIP],[true])],[ AM_CONDITIONAL([HAVE_SOFIA_SIP],[true])],[
AC_MSG_ERROR([no usable sofia-sip; please install sofia-sip-ua devel package or equivalent]) AC_MSG_ERROR([no usable sofia-sip; please install sofia-sip-ua devel package or equivalent])
]) ])
@ -2208,7 +2208,6 @@ AC_CONFIG_FILES([Makefile
src/mod/event_handlers/mod_fail2ban/Makefile src/mod/event_handlers/mod_fail2ban/Makefile
src/mod/event_handlers/mod_format_cdr/Makefile src/mod/event_handlers/mod_format_cdr/Makefile
src/mod/event_handlers/mod_json_cdr/Makefile src/mod/event_handlers/mod_json_cdr/Makefile
src/mod/event_handlers/mod_kazoo/Makefile
src/mod/event_handlers/mod_radius_cdr/Makefile src/mod/event_handlers/mod_radius_cdr/Makefile
src/mod/event_handlers/mod_odbc_cdr/Makefile src/mod/event_handlers/mod_odbc_cdr/Makefile
src/mod/event_handlers/mod_rayo/Makefile src/mod/event_handlers/mod_rayo/Makefile

69
debian/bootstrap.sh vendored
View File

@ -65,6 +65,9 @@ avoid_mods=(
avoid_mods_armhf=( avoid_mods_armhf=(
languages/mod_v8 languages/mod_v8
) )
avoid_mods_arm64=(
languages/mod_v8
)
avoid_mods_sid=( avoid_mods_sid=(
directories/mod_ldap directories/mod_ldap
) )
@ -335,7 +338,7 @@ Build-Depends:
uuid-dev, libexpat1-dev, libgdbm-dev, libdb-dev, uuid-dev, libexpat1-dev, libgdbm-dev, libdb-dev,
# used by many modules # used by many modules
libcurl4-openssl-dev | libcurl4-gnutls-dev | libcurl-dev, libcurl4-openssl-dev | libcurl4-gnutls-dev | libcurl-dev,
bison, zlib1g-dev, libsofia-sip-ua-dev (>= 1.13.15), bison, zlib1g-dev, libsofia-sip-ua-dev (>= 1.13.17),
libspandsp3-dev, libspandsp3-dev,
# used to format the private freeswitch apt-repo key properly # used to format the private freeswitch apt-repo key properly
gnupg, gnupg,
@ -352,7 +355,7 @@ EOF
print_core_control () { print_core_control () {
cat <<EOF cat <<EOF
Package: freeswitch-all Package: freeswitch-all
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: freeswitch-meta-all (= \${binary:Version}), freeswitch-meta-all-dbg (= \${binary:Version}) Depends: freeswitch-meta-all (= \${binary:Version}), freeswitch-meta-all-dbg (= \${binary:Version})
Conflicts: freeswitch-all (<= 1.6.7) Conflicts: freeswitch-all (<= 1.6.7)
Description: Cross-Platform Scalable Multi-Protocol Soft Switch Description: Cross-Platform Scalable Multi-Protocol Soft Switch
@ -361,7 +364,7 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch
This is a package which depends on all packaged FreeSWITCH modules. This is a package which depends on all packaged FreeSWITCH modules.
Package: freeswitch Package: freeswitch
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${shlibs:Depends}, \${perl:Depends}, \${misc:Depends}, Depends: \${shlibs:Depends}, \${perl:Depends}, \${misc:Depends},
libfreeswitch1 (= \${binary:Version}) libfreeswitch1 (= \${binary:Version})
Recommends: Recommends:
@ -373,8 +376,8 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch
This package contains the FreeSWITCH core. This package contains the FreeSWITCH core.
Package: libfreeswitch1 Package: libfreeswitch1
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${shlibs:Depends}, \${misc:Depends}, libsofia-sip-ua0 (>= 1.13.15) Depends: \${shlibs:Depends}, \${misc:Depends}, libsofia-sip-ua0 (>= 1.13.17)
Recommends: Recommends:
Suggests: libfreeswitch1-dbg Suggests: libfreeswitch1-dbg
Conflicts: freeswitch-all (<= 1.6.7) Conflicts: freeswitch-all (<= 1.6.7)
@ -385,7 +388,7 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch
Package: python-esl Package: python-esl
Section: python Section: python
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${shlibs:Depends}, \${misc:Depends}, \${python:Depends} Depends: \${shlibs:Depends}, \${misc:Depends}, \${python:Depends}
Description: Cross-Platform Scalable Multi-Protocol Soft Switch Description: Cross-Platform Scalable Multi-Protocol Soft Switch
$(debian_wrap "${fs_description}") $(debian_wrap "${fs_description}")
@ -394,7 +397,7 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch
Package: libesl-perl Package: libesl-perl
Section: perl Section: perl
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${shlibs:Depends}, \${misc:Depends}, \${perl:Depends} Depends: \${shlibs:Depends}, \${misc:Depends}, \${perl:Depends}
Description: Cross-Platform Scalable Multi-Protocol Soft Switch Description: Cross-Platform Scalable Multi-Protocol Soft Switch
$(debian_wrap "${fs_description}") $(debian_wrap "${fs_description}")
@ -402,7 +405,7 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch
This package contains the Perl binding for FreeSWITCH Event Socket Library (ESL). This package contains the Perl binding for FreeSWITCH Event Socket Library (ESL).
Package: freeswitch-meta-bare Package: freeswitch-meta-bare
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends}, freeswitch (= \${binary:Version}) Depends: \${misc:Depends}, freeswitch (= \${binary:Version})
Recommends: Recommends:
freeswitch-doc (= \${binary:Version}), freeswitch-doc (= \${binary:Version}),
@ -420,7 +423,7 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch
bare FreeSWITCH install. bare FreeSWITCH install.
Package: freeswitch-meta-default Package: freeswitch-meta-default
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends}, freeswitch (= \${binary:Version}), Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
freeswitch-mod-commands (= \${binary:Version}), freeswitch-mod-commands (= \${binary:Version}),
freeswitch-mod-conference (= \${binary:Version}), freeswitch-mod-conference (= \${binary:Version}),
@ -462,7 +465,7 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch
reasonably basic FreeSWITCH install. reasonably basic FreeSWITCH install.
Package: freeswitch-meta-vanilla Package: freeswitch-meta-vanilla
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends}, freeswitch (= \${binary:Version}), Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
freeswitch-init, freeswitch-init,
freeswitch-mod-console (= \${binary:Version}), freeswitch-mod-console (= \${binary:Version}),
@ -511,7 +514,7 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch
running the FreeSWITCH vanilla example configuration. running the FreeSWITCH vanilla example configuration.
Package: freeswitch-meta-sorbet Package: freeswitch-meta-sorbet
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends}, freeswitch (= \${binary:Version}), Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
Recommends: Recommends:
freeswitch-init, freeswitch-init,
@ -594,7 +597,7 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch
modules except a few which aren't recommended. modules except a few which aren't recommended.
Package: freeswitch-meta-all Package: freeswitch-meta-all
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends}, freeswitch (= \${binary:Version}), Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
freeswitch-init, freeswitch-init,
freeswitch-lang (= \${binary:Version}), freeswitch-lang (= \${binary:Version}),
@ -673,7 +676,6 @@ Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
freeswitch-mod-event-multicast (= \${binary:Version}), freeswitch-mod-event-multicast (= \${binary:Version}),
freeswitch-mod-event-socket (= \${binary:Version}), freeswitch-mod-event-socket (= \${binary:Version}),
freeswitch-mod-json-cdr (= \${binary:Version}), freeswitch-mod-json-cdr (= \${binary:Version}),
freeswitch-mod-kazoo (= \${binary:Version}),
freeswitch-mod-snmp (= \${binary:Version}), freeswitch-mod-snmp (= \${binary:Version}),
freeswitch-mod-local-stream (= \${binary:Version}), freeswitch-mod-local-stream (= \${binary:Version}),
freeswitch-mod-native-file (= \${binary:Version}), freeswitch-mod-native-file (= \${binary:Version}),
@ -706,7 +708,7 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch
FreeSWITCH modules. FreeSWITCH modules.
Package: freeswitch-meta-codecs Package: freeswitch-meta-codecs
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends}, freeswitch (= \${binary:Version}), Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
freeswitch-mod-amr (= \${binary:Version}), freeswitch-mod-amr (= \${binary:Version}),
freeswitch-mod-amrwb (= \${binary:Version}), freeswitch-mod-amrwb (= \${binary:Version}),
@ -733,7 +735,7 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch
most FreeSWITCH codecs. most FreeSWITCH codecs.
Package: freeswitch-meta-codecs-dbg Package: freeswitch-meta-codecs-dbg
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends}, freeswitch (= \${binary:Version}), Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
freeswitch-mod-amr-dbg (= \${binary:Version}), freeswitch-mod-amr-dbg (= \${binary:Version}),
freeswitch-mod-amrwb-dbg (= \${binary:Version}), freeswitch-mod-amrwb-dbg (= \${binary:Version}),
@ -760,7 +762,7 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch
most FreeSWITCH codecs. most FreeSWITCH codecs.
Package: freeswitch-meta-conf Package: freeswitch-meta-conf
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends}, Depends: \${misc:Depends},
freeswitch-conf-curl (= \${binary:Version}), freeswitch-conf-curl (= \${binary:Version}),
freeswitch-conf-insideout (= \${binary:Version}), freeswitch-conf-insideout (= \${binary:Version}),
@ -774,7 +776,7 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch
examples for FreeSWITCH. examples for FreeSWITCH.
Package: freeswitch-meta-lang Package: freeswitch-meta-lang
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends}, Depends: \${misc:Depends},
freeswitch-lang-de (= \${binary:Version}), freeswitch-lang-de (= \${binary:Version}),
freeswitch-lang-en (= \${binary:Version}), freeswitch-lang-en (= \${binary:Version}),
@ -790,7 +792,7 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch
FreeSWITCH. FreeSWITCH.
Package: freeswitch-meta-mod-say Package: freeswitch-meta-mod-say
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends}, Depends: \${misc:Depends},
freeswitch-mod-say-de (= \${binary:Version}), freeswitch-mod-say-de (= \${binary:Version}),
freeswitch-mod-say-en (= \${binary:Version}), freeswitch-mod-say-en (= \${binary:Version}),
@ -815,7 +817,7 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch
FreeSWITCH. FreeSWITCH.
Package: freeswitch-meta-mod-say-dbg Package: freeswitch-meta-mod-say-dbg
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends}, Depends: \${misc:Depends},
freeswitch-mod-say-de-dbg (= \${binary:Version}), freeswitch-mod-say-de-dbg (= \${binary:Version}),
freeswitch-mod-say-en-dbg (= \${binary:Version}), freeswitch-mod-say-en-dbg (= \${binary:Version}),
@ -840,7 +842,7 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch
FreeSWITCH. FreeSWITCH.
Package: freeswitch-meta-all-dbg Package: freeswitch-meta-all-dbg
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends}, freeswitch (= \${binary:Version}), Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
freeswitch-meta-codecs-dbg (= \${binary:Version}), freeswitch-meta-codecs-dbg (= \${binary:Version}),
freeswitch-meta-mod-say (= \${binary:Version}), freeswitch-meta-mod-say (= \${binary:Version}),
@ -910,7 +912,6 @@ Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
freeswitch-mod-event-multicast-dbg (= \${binary:Version}), freeswitch-mod-event-multicast-dbg (= \${binary:Version}),
freeswitch-mod-event-socket-dbg (= \${binary:Version}), freeswitch-mod-event-socket-dbg (= \${binary:Version}),
freeswitch-mod-json-cdr-dbg (= \${binary:Version}), freeswitch-mod-json-cdr-dbg (= \${binary:Version}),
freeswitch-mod-kazoo-dbg (= \${binary:Version}),
freeswitch-mod-snmp-dbg (= \${binary:Version}), freeswitch-mod-snmp-dbg (= \${binary:Version}),
freeswitch-mod-local-stream-dbg (= \${binary:Version}), freeswitch-mod-local-stream-dbg (= \${binary:Version}),
freeswitch-mod-native-file-dbg (= \${binary:Version}), freeswitch-mod-native-file-dbg (= \${binary:Version}),
@ -945,7 +946,7 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch
Package: freeswitch-all-dbg Package: freeswitch-all-dbg
Section: debug Section: debug
Priority: optional Priority: optional
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends}, freeswitch-meta-all (= \${binary:Version}), freeswitch-meta-all-dbg (= \${binary:Version}) Depends: \${misc:Depends}, freeswitch-meta-all (= \${binary:Version}), freeswitch-meta-all-dbg (= \${binary:Version})
Description: debugging symbols for FreeSWITCH Description: debugging symbols for FreeSWITCH
$(debian_wrap "${fs_description}") $(debian_wrap "${fs_description}")
@ -955,7 +956,7 @@ Description: debugging symbols for FreeSWITCH
Package: freeswitch-dbg Package: freeswitch-dbg
Section: debug Section: debug
Priority: optional Priority: optional
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends}, freeswitch (= \${binary:Version}) Depends: \${misc:Depends}, freeswitch (= \${binary:Version})
Description: debugging symbols for FreeSWITCH Description: debugging symbols for FreeSWITCH
$(debian_wrap "${fs_description}") $(debian_wrap "${fs_description}")
@ -965,7 +966,7 @@ Description: debugging symbols for FreeSWITCH
Package: libfreeswitch1-dbg Package: libfreeswitch1-dbg
Section: debug Section: debug
Priority: optional Priority: optional
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends}, libfreeswitch1 (= \${binary:Version}) Depends: \${misc:Depends}, libfreeswitch1 (= \${binary:Version})
Description: debugging symbols for FreeSWITCH Description: debugging symbols for FreeSWITCH
$(debian_wrap "${fs_description}") $(debian_wrap "${fs_description}")
@ -974,7 +975,7 @@ Description: debugging symbols for FreeSWITCH
Package: libfreeswitch-dev Package: libfreeswitch-dev
Section: libdevel Section: libdevel
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends}, freeswitch Depends: \${misc:Depends}, freeswitch
Description: development libraries and header files for FreeSWITCH Description: development libraries and header files for FreeSWITCH
$(debian_wrap "${fs_description}") $(debian_wrap "${fs_description}")
@ -983,7 +984,7 @@ Description: development libraries and header files for FreeSWITCH
Package: freeswitch-doc Package: freeswitch-doc
Section: doc Section: doc
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends} Depends: \${misc:Depends}
Description: documentation for FreeSWITCH Description: documentation for FreeSWITCH
$(debian_wrap "${fs_description}") $(debian_wrap "${fs_description}")
@ -996,7 +997,7 @@ Description: documentation for FreeSWITCH
## languages ## languages
Package: freeswitch-lang Package: freeswitch-lang
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends}, Depends: \${misc:Depends},
freeswitch-lang-en (= \${binary:Version}) freeswitch-lang-en (= \${binary:Version})
Description: Language files for FreeSWITCH Description: Language files for FreeSWITCH
@ -1008,7 +1009,7 @@ Description: Language files for FreeSWITCH
## timezones ## timezones
Package: freeswitch-timezones Package: freeswitch-timezones
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends} Depends: \${misc:Depends}
Description: Timezone files for FreeSWITCH Description: Timezone files for FreeSWITCH
$(debian_wrap "${fs_description}") $(debian_wrap "${fs_description}")
@ -1022,7 +1023,7 @@ EOF
if [ ${use_sysvinit} = "true" ]; then if [ ${use_sysvinit} = "true" ]; then
cat <<EOF cat <<EOF
Package: freeswitch-sysvinit Package: freeswitch-sysvinit
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends}, lsb-base (>= 3.0-6), sysvinit | sysvinit-utils Depends: \${misc:Depends}, lsb-base (>= 3.0-6), sysvinit | sysvinit-utils
Conflicts: freeswitch-init Conflicts: freeswitch-init
Provides: freeswitch-init Provides: freeswitch-init
@ -1035,7 +1036,7 @@ EOF
else else
cat <<EOF cat <<EOF
Package: freeswitch-systemd Package: freeswitch-systemd
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends}, systemd Depends: \${misc:Depends}, systemd
Conflicts: freeswitch-init, freeswitch-all (<= 1.6.7) Conflicts: freeswitch-init, freeswitch-all (<= 1.6.7)
Provides: freeswitch-init Provides: freeswitch-init
@ -1053,7 +1054,7 @@ print_mod_control () {
cat <<EOF cat <<EOF
Package: freeswitch-${module_name//_/-} Package: freeswitch-${module_name//_/-}
Section: ${m_section} Section: ${m_section}
Architecture: amd64 armhf Architecture: amd64 armhf arm64
$(debian_wrap "Depends: \${shlibs:Depends}, \${misc:Depends}, libfreeswitch1 (= \${binary:Version}), ${depends}") $(debian_wrap "Depends: \${shlibs:Depends}, \${misc:Depends}, libfreeswitch1 (= \${binary:Version}), ${depends}")
$(debian_wrap "Recommends: ${recommends}") $(debian_wrap "Recommends: ${recommends}")
$(debian_wrap "Suggests: freeswitch-${module_name//_/-}-dbg, ${suggests}") $(debian_wrap "Suggests: freeswitch-${module_name//_/-}-dbg, ${suggests}")
@ -1068,7 +1069,7 @@ Description: ${description} for FreeSWITCH
Package: freeswitch-${module_name//_/-}-dbg Package: freeswitch-${module_name//_/-}-dbg
Section: debug Section: debug
Priority: optional Priority: optional
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends}, Depends: \${misc:Depends},
freeswitch-${module_name//_/-} (= \${binary:Version}) freeswitch-${module_name//_/-} (= \${binary:Version})
Description: ${description} for FreeSWITCH (debug) Description: ${description} for FreeSWITCH (debug)
@ -1133,7 +1134,7 @@ print_conf_overrides () {
print_conf_control () { print_conf_control () {
cat <<EOF cat <<EOF
Package: freeswitch-conf-${conf//_/-} Package: freeswitch-conf-${conf//_/-}
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends} Depends: \${misc:Depends}
Conflicts: freeswitch-all (<= 1.6.7) Conflicts: freeswitch-all (<= 1.6.7)
Description: FreeSWITCH ${conf} configuration Description: FreeSWITCH ${conf} configuration
@ -1167,7 +1168,7 @@ print_lang_control () {
esac esac
cat <<EOF cat <<EOF
Package: freeswitch-lang-${lang//_/-} Package: freeswitch-lang-${lang//_/-}
Architecture: amd64 armhf Architecture: amd64 armhf arm64
Depends: \${misc:Depends} Depends: \${misc:Depends}
Recommends: freeswitch-sounds-${lang} Recommends: freeswitch-sounds-${lang}
Conflicts: freeswitch-all (<= 1.6.7) Conflicts: freeswitch-all (<= 1.6.7)

View File

@ -542,12 +542,6 @@ Module: event_handlers/mod_json_cdr
Description: mod_json_cdr Description: mod_json_cdr
Adds mod_json_cdr. Adds mod_json_cdr.
Module: event_handlers/mod_kazoo
Description: mod_kazoo
Adds mod_kazoo.
Build-Depends: erlang-dev
Depends: erlang
Module: event_handlers/mod_odbc_cdr Module: event_handlers/mod_odbc_cdr
Description: mod_odbc_cdr Description: mod_odbc_cdr
Adds mod_odbc_cdr. Adds mod_odbc_cdr.

205
debian/util.sh vendored
View File

@ -135,51 +135,136 @@ get_nightly_revision_human () {
echo "git $(git rev-list -n1 --abbrev=7 --abbrev-commit HEAD) $(date -u '+%Y-%m-%d %H:%M:%SZ')" echo "git $(git rev-list -n1 --abbrev=7 --abbrev-commit HEAD) $(date -u '+%Y-%m-%d %H:%M:%SZ')"
} }
create_orig () { prep_create_orig () {
{ {
set -e set -e
local OPTIND OPTARG local OPTIND OPTARG
local uver="" hrev="" bundle_deps=true modules_list="" zl=9e local uver="" hrev="" bundle_deps=true soft_reset=false
while getopts 'bm:nv:z:' o "$@"; do
while getopts 'bm:nv:V:xz:' o "$@"; do
case "$o" in case "$o" in
m) modules_list="$OPTARG";; b) ;;
m) ;;
n) uver="nightly";; n) uver="nightly";;
v) uver="$OPTARG";; v) uver="$OPTARG";;
z) zl="$OPTARG";; V) uver="$OPTARG";;
x) soft_reset=true;;
z) ;;
esac esac
done done
shift $(($OPTIND-1)) shift $(($OPTIND-1))
if [ -z "$uver" ] || [ "$uver" = "nightly" ]; then if [ -z "$uver" ] || [ "$uver" = "nightly" ]; then
uver="$(get_nightly_version)" uver="$(get_nightly_version)"
hrev="$(get_nightly_revision_human)" hrev="$(get_nightly_revision_human)"
fi fi
local treeish="$1" dver="$(mk_dver "$uver")"
local orig="../freeswitch_$dver~$(lsb_release -sc).orig.tar.xz" local treeish="$1"
[ -n "$treeish" ] || treeish="HEAD" [ -n "$treeish" ] || treeish="HEAD"
check_repo_clean
git reset --hard "$treeish" if $soft_reset; then
git reset --soft "$treeish"
else
check_repo_clean
git reset --hard "$treeish"
fi
if $bundle_deps; then
(cd libs && getlibs)
fi
./build/set-fs-version.sh "$uver" "$hrev" # ToDo: Handle empty $hrev
echo "$uver" > .version
} 1>&2
echo "$uver"
}
create_orig () {
{
set -e
local OPTIND OPTARG
local bundle_deps=true modules_list="" soft_reset=false auto_orig=false zl=9e
local uver="$(prep_create_orig "$@")"
while getopts 'bm:nv:V:xz:' o "$@"; do
case "$o" in
b) ;;
m) modules_list="$OPTARG";;
n) ;;
v) ;;
V) auto_orig=true;;
x) soft_reset=true;;
z) zl="$OPTARG";;
esac
done
shift $(($OPTIND-1))
local commit_epoch=$(git log -1 --format=%ct)
local source_date=$(date -u -d @$commit_epoch +'%Y-%m-%d %H:%M:%S')
local orig git_archive_prefix
if $auto_orig; then
orig="../freeswitch_$(debian/version-omit_revision.pl).orig.tar.xz"
git_archive_prefix="freeswitch/"
else
orig="../freeswitch_$(mk_dver "$uver")~$(lsb_release -sc).orig.tar.xz"
git_archive_prefix="freeswitch-$uver/"
fi
mv .gitattributes .gitattributes.orig mv .gitattributes .gitattributes.orig
local -a args=(-e '\bdebian-ignore\b') local -a args=(-e '\bdebian-ignore\b')
test "$modules_list" = "non-dfsg" || args+=(-e '\bdfsg-nonfree\b') test "$modules_list" = "non-dfsg" || args+=(-e '\bdfsg-nonfree\b')
grep .gitattributes.orig "${args[@]}" \ grep .gitattributes.orig "${args[@]}" \
| while xread l; do | while xread l; do
echo "$l export-ignore" >> .gitattributes echo "$l export-ignore" >> .gitattributes
done done
if $bundle_deps; then if $bundle_deps; then
(cd libs && getlibs)
git add -f libs git add -f libs
fi fi
./build/set-fs-version.sh "$uver" "$hrev" && git add configure.ac
echo "$uver" > .version && git add -f .version git add -f configure.ac .version
git commit --allow-empty -m "nightly v$uver" git commit --allow-empty -m "nightly v$uver"
local tmpsrcdir="$(mktemp -d)"
git archive -v \ git archive -v \
--worktree-attributes \ --worktree-attributes \
--format=tar \ --format=tar \
--prefix=freeswitch-$uver/ \ --prefix=$git_archive_prefix \
HEAD \ HEAD | tar --extract --directory="$tmpsrcdir"
| xz -c -${zl}v > $orig
# https://www.gnu.org/software/tar/manual/html_section/Reproducibility.html
tar \
--sort=name \
--format=posix \
--pax-option='exthdr.name=%d/PaxHeaders/%f' \
--pax-option='delete=atime,delete=ctime' \
--clamp-mtime \
--mtime="$source_date" \
--numeric-owner \
--owner=0 \
--group=0 \
--mode='go+u,go-w' \
--create \
--directory="$tmpsrcdir" \
. | xz -v -c -${zl} > "$orig" && \
rm -rf "$tmpsrcdir"
echo "Source archive checksum:"
sha256sum $orig
mv .gitattributes.orig .gitattributes mv .gitattributes.orig .gitattributes
git reset --hard HEAD^ && git clean -fdx
if $soft_reset; then
git reset --soft HEAD^
else
git reset --hard HEAD^ && git clean -fdx
fi
} 1>&2 } 1>&2
echo $orig echo $orig
} }
@ -190,11 +275,12 @@ applications/mod_commands
EOF EOF
} }
create_dsc () { prep_create_dsc () {
{ {
set -e set -e
local OPTIND OPTARG modules_conf="" modules_list="" speed="normal" suite_postfix="" suite_postfix_p=false zl=9
local modules_add="" local OPTIND OPTARG modules_conf="" modules_add="" modules_list="" speed="normal"
while getopts 'a:f:m:p:s:u:z:' o "$@"; do while getopts 'a:f:m:p:s:u:z:' o "$@"; do
case "$o" in case "$o" in
a) avoid_mods_arch="$OPTARG";; a) avoid_mods_arch="$OPTARG";;
@ -202,47 +288,93 @@ create_dsc () {
m) modules_list="$OPTARG";; m) modules_list="$OPTARG";;
p) modules_add="$modules_add $OPTARG";; p) modules_add="$modules_add $OPTARG";;
s) speed="$OPTARG";; s) speed="$OPTARG";;
u) suite_postfix="$OPTARG"; suite_postfix_p=true;; u) ;;
z) zl="$OPTARG";; z) ;;
esac esac
done done
shift $(($OPTIND-1)) shift $(($OPTIND-1))
local distro="$(find_distro $1)" orig="$2"
local suite="$(find_suite $distro)" local distro="$(find_distro $1)"
local orig_ver="$(echo "$orig" | sed -e 's/^.*_//' -e 's/\.orig\.tar.*$//')"
local dver="${orig_ver}-1~${distro}+1"
$suite_postfix_p && { suite="${distro}${suite_postfix}"; }
[ -x "$(which dch)" ] \
|| err "package devscripts isn't installed"
if [ -n "$modules_conf" ]; then if [ -n "$modules_conf" ]; then
cp $modules_conf debian/modules.conf cp $modules_conf debian/modules.conf
fi fi
local bootstrap_args="" local bootstrap_args=""
if [ -n "$modules_list" ]; then if [ -n "$modules_list" ]; then
if [ "$modules_list" = "non-dfsg" ]; then if [ "$modules_list" = "non-dfsg" ]; then
bootstrap_args="-mnon-dfsg" bootstrap_args="-mnon-dfsg"
else set_modules_${modules_list}; fi else
set_modules_${modules_list}
fi
fi fi
if test -n "$modules_add"; then if test -n "$modules_add"; then
for x in $modules_add; do for x in $modules_add; do
bootstrap_args="$bootstrap_args -p${x}" bootstrap_args="$bootstrap_args -p${x}"
done done
fi fi
(cd debian && ./bootstrap.sh -a "$avoid_mods_arch" -c $distro $bootstrap_args) (cd debian && ./bootstrap.sh -a "$avoid_mods_arch" -c $distro $bootstrap_args)
case "$speed" in case "$speed" in
paranoid) sed -i ./debian/rules \ paranoid) sed -i ./debian/rules \
-e '/\.stamp-bootstrap:/{:l2 n; /\.\/bootstrap.sh -j/{s/ -j//; :l3 n; b l3}; b l2};' ;; -e '/\.stamp-bootstrap:/{:l2 n; /\.\/bootstrap.sh -j/{s/ -j//; :l3 n; b l3}; b l2};' ;;
reckless) sed -i ./debian/rules \ reckless) sed -i ./debian/rules \
-e '/\.stamp-build:/{:l2 n; /make/{s/$/ -j/; :l3 n; b l3}; b l2};' ;; -e '/\.stamp-build:/{:l2 n; /make/{s/$/ -j/; :l3 n; b l3}; b l2};' ;;
esac esac
} 1>&2
}
create_dsc () {
{
set -e
prep_create_dsc "$@"
local OPTIND OPTARG suite_postfix="" suite_postfix_p=false soft_reset=false zl=9
while getopts 'a:f:m:p:s:u:xz:' o "$@"; do
case "$o" in
a) ;;
f) ;;
m) ;;
p) ;;
s) ;;
u) suite_postfix="$OPTARG"; suite_postfix_p=true;;
x) soft_reset=true;;
z) zl="$OPTARG";;
esac
done
shift $(($OPTIND-1))
local distro="$(find_distro $1)" orig="$2"
local suite="$(find_suite $distro)"
local orig_ver="$(echo "$orig" | sed -e 's/^.*_//' -e 's/\.orig\.tar.*$//')"
local dver="${orig_ver}-1~${distro}+1"
$suite_postfix_p && { suite="${distro}${suite_postfix}"; }
[ -x "$(which dch)" ] \
|| err "package devscripts isn't installed"
[ "$zl" -ge "1" ] || zl=1 [ "$zl" -ge "1" ] || zl=1
git add debian/rules
dch -b -m -v "$dver" --force-distribution -D "$suite" "Nightly build." dch -b -m -v "$dver" --force-distribution -D "$suite" "Nightly build."
git add debian/changelog && git commit -m "nightly v$orig_ver"
git add debian/rules debian/changelog && git commit -m "nightly v$orig_ver"
dpkg-source -i.* -Zxz -z${zl} -b . dpkg-source -i.* -Zxz -z${zl} -b .
dpkg-genchanges -S > ../$(dsc_base)_source.changes dpkg-genchanges -S > ../$(dsc_base)_source.changes
local dsc="../$(dsc_base).dsc" local dsc="../$(dsc_base).dsc"
git reset --hard HEAD^ && git clean -fdx
if $soft_reset; then
git reset --soft HEAD^
else
git reset --hard HEAD^ && git clean -fdx
fi
} 1>&2 } 1>&2
echo $dsc echo $dsc
} }
@ -588,7 +720,7 @@ commands:
create-dbg-pkgs create-dbg-pkgs
create-dsc <distro> <orig-file> create-dsc <distro> <orig-file> (same for 'prep-create-dsc')
-f <modules.conf> -f <modules.conf>
Build only modules listed in this file Build only modules listed in this file
@ -600,14 +732,17 @@ commands:
Set FS bootstrap/build -j flags Set FS bootstrap/build -j flags
-u <suite-postfix> -u <suite-postfix>
Specify a custom suite postfix Specify a custom suite postfix
-x Use git soft reset instead of hard reset
-z Set compression level -z Set compression level
create-orig <treeish> create-orig <treeish> (same for 'prep_create_orig')
-m [ quicktest | non-dfsg ] -m [ quicktest | non-dfsg ]
Choose custom list of modules to build Choose custom list of modules to build
-n Nightly build -n Nightly build
-v Set version -v Set version
-V Set version (without replacing every '-' to '~')
-x Use git soft reset instead of hard reset
-z Set compression level -z Set compression level
EOF EOF
@ -629,7 +764,9 @@ case "$cmd" in
build-all) build_all "$@" ;; build-all) build_all "$@" ;;
build-debs) build_debs "$@" ;; build-debs) build_debs "$@" ;;
create-dbg-pkgs) create_dbg_pkgs ;; create-dbg-pkgs) create_dbg_pkgs ;;
prep-create-dsc) prep_create_dsc "$@" ;;
create-dsc) create_dsc "$@" ;; create-dsc) create_dsc "$@" ;;
prep-create-orig) prep_create_orig "$@" ;;
create-orig) create_orig "$@" ;; create-orig) create_orig "$@" ;;
*) usage ;; *) usage ;;
esac esac

22
debian/version-omit_revision.pl vendored Executable file
View File

@ -0,0 +1,22 @@
#!/usr/bin/perl
use strict;
use warnings;
use Dpkg::Version;
my $version;
open(my $fh, '-|', 'dpkg-parsechangelog -S version') or die "Failed to execute dpkg-parsechangelog: $!";
{
local $/;
$version = <$fh>;
}
close $fh;
$version =~ s/\s+$//;
die "No version found or empty output from dpkg-parsechangelog" unless defined $version and $version ne '';
my $v = Dpkg::Version->new($version);
my $vs = $v->as_string(omit_epoch => 1, omit_revision => 1);
print "$vs\n";

View File

@ -20,7 +20,9 @@ ARG FS_META_PACKAGE=freeswitch-meta-all
# https://github.com/docker-library/postgres/blob/master/9.4/Dockerfile # https://github.com/docker-library/postgres/blob/master/9.4/Dockerfile
# explicitly set user/group IDs # explicitly set user/group IDs
RUN groupadd -r freeswitch --gid=999 && useradd -r -g freeswitch --uid=999 freeswitch ARG FREESWITCH_UID=499
ARG FREESWITCH_GID=499
RUN groupadd -r freeswitch --gid=${FREESWITCH_GID} && useradd -r -g freeswitch --uid=${FREESWITCH_UID} freeswitch
# make the "en_US.UTF-8" locale so freeswitch will be utf-8 enabled by default # make the "en_US.UTF-8" locale so freeswitch will be utf-8 enabled by default
RUN apt-get update -qq \ RUN apt-get update -qq \

View File

@ -140,7 +140,7 @@ BuildRequires: curl-devel >= 7.19
BuildRequires: gcc-c++ BuildRequires: gcc-c++
BuildRequires: libtool >= 1.5.17 BuildRequires: libtool >= 1.5.17
BuildRequires: openssl-devel >= 1.0.1e BuildRequires: openssl-devel >= 1.0.1e
BuildRequires: sofia-sip-devel >= 1.13.15 BuildRequires: sofia-sip-devel >= 1.13.17
BuildRequires: spandsp3-devel >= 3.0 BuildRequires: spandsp3-devel >= 3.0
BuildRequires: pcre-devel BuildRequires: pcre-devel
BuildRequires: speex-devel BuildRequires: speex-devel
@ -952,16 +952,6 @@ Requires: %{name} = %{version}-%{release}
%description event-format-cdr %description event-format-cdr
JSON and XML Logger for the FreeSWITCH open source telephony platform JSON and XML Logger for the FreeSWITCH open source telephony platform
%package kazoo
Summary: Kazoo Module for the FreeSWITCH open source telephony platform
Group: System/Libraries
Requires: %{name} = %{version}-%{release}
Requires: erlang
BuildRequires: erlang
%description kazoo
Kazoo Module for FreeSWITCH.
%package event-multicast %package event-multicast
Summary: Multicast Event System for the FreeSWITCH open source telephony platform Summary: Multicast Event System for the FreeSWITCH open source telephony platform
Group: System/Libraries Group: System/Libraries
@ -1480,7 +1470,7 @@ ENDPOINTS_MODULES=" \
###################################################################################################################### ######################################################################################################################
EVENT_HANDLERS_MODULES="event_handlers/mod_cdr_csv event_handlers/mod_cdr_pg_csv event_handlers/mod_cdr_sqlite \ EVENT_HANDLERS_MODULES="event_handlers/mod_cdr_csv event_handlers/mod_cdr_pg_csv event_handlers/mod_cdr_sqlite \
event_handlers/mod_cdr_mongodb event_handlers/mod_format_cdr event_handlers/mod_erlang_event event_handlers/mod_event_multicast \ event_handlers/mod_cdr_mongodb event_handlers/mod_format_cdr event_handlers/mod_erlang_event event_handlers/mod_event_multicast \
event_handlers/mod_event_socket event_handlers/mod_json_cdr event_handlers/mod_kazoo event_handlers/mod_radius_cdr \ event_handlers/mod_event_socket event_handlers/mod_json_cdr event_handlers/mod_radius_cdr \
event_handlers/mod_snmp" event_handlers/mod_snmp"
%if %{build_mod_rayo} %if %{build_mod_rayo}
EVENT_HANDLERS_MODULES+=" event_handlers/mod_rayo" EVENT_HANDLERS_MODULES+=" event_handlers/mod_rayo"
@ -1916,7 +1906,6 @@ fi
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/http_cache.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/http_cache.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/ivr.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/ivr.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/java.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/java.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/kazoo.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/lcr.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/lcr.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/local_stream.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/local_stream.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/logfile.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/logfile.conf.xml
@ -2286,9 +2275,6 @@ fi
%files event-json-cdr %files event-json-cdr
%{MODINSTDIR}/mod_json_cdr.so* %{MODINSTDIR}/mod_json_cdr.so*
%files kazoo
%{MODINSTDIR}/mod_kazoo.so*
%files event-radius-cdr %files event-radius-cdr
%{MODINSTDIR}/mod_radius_cdr.so* %{MODINSTDIR}/mod_radius_cdr.so*

View File

@ -64,6 +64,9 @@ static int remap_prob(int v, int m) {
228, 229, 17, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 228, 229, 17, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
18, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 19, 18, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 19,
}; };
assert(m > 0);
v--; v--;
m--; m--;
if ((m << 1) <= MAX_PROB) if ((m << 1) <= MAX_PROB)

View File

@ -167,6 +167,8 @@ static void scale1d_c(const unsigned char *source, int source_step,
(void)source_length; (void)source_length;
assert(dest_scale);
/* These asserts are needed if there are boundary issues... */ /* These asserts are needed if there are boundary issues... */
/*assert ( dest_scale > source_scale );*/ /*assert ( dest_scale > source_scale );*/
/*assert ( (source_length-1) * dest_scale >= (dest_length-1) * source_scale /*assert ( (source_length-1) * dest_scale >= (dest_length-1) * source_scale

View File

@ -11,6 +11,8 @@
#ifndef VPX_VPX_SCALE_VPX_SCALE_H_ #ifndef VPX_VPX_SCALE_VPX_SCALE_H_
#define VPX_VPX_SCALE_VPX_SCALE_H_ #define VPX_VPX_SCALE_VPX_SCALE_H_
#include <assert.h>
#include "vpx_scale/yv12config.h" #include "vpx_scale/yv12config.h"
extern void vpx_scale_frame(YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst, extern void vpx_scale_frame(YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst,

View File

@ -260,7 +260,9 @@
/* Define to `__inline__' or `__inline' if that's what the C compiler /* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */ calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus #ifndef __cplusplus
#define inline #ifndef _WIN32
#define inline /* Do not define inline for Windows to avoid warnings/errors with winsock2.h usage of inline within the latest Windows SDKs */
#endif
#endif #endif
#if _MSC_VER >= 1900 #if _MSC_VER >= 1900

View File

@ -103,6 +103,8 @@ typedef struct icand_s {
switch_port_t rport; switch_port_t rport;
char *generation; char *generation;
uint8_t ready; uint8_t ready;
uint8_t responsive;
uint8_t use_candidate;
} icand_t; } icand_t;
#define MAX_CAND 50 #define MAX_CAND 50

View File

@ -141,6 +141,13 @@ typedef struct {
uint32_t address; uint32_t address;
} switch_stun_ip_t; } switch_stun_ip_t;
typedef struct {
uint8_t wasted;
uint8_t family;
uint16_t port;
uint8_t address[16];
} switch_stun_ipv6_t;
#if SWITCH_BYTE_ORDER == __BIG_ENDIAN #if SWITCH_BYTE_ORDER == __BIG_ENDIAN
typedef struct { typedef struct {

View File

@ -255,6 +255,10 @@ SWITCH_BEGIN_EXTERN_C
typedef uint8_t switch_byte_t; typedef uint8_t switch_byte_t;
typedef struct {
unsigned int value : 31;
} switch_uint31_t;
typedef enum { typedef enum {
SWITCH_PVT_PRIMARY = 0, SWITCH_PVT_PRIMARY = 0,
SWITCH_PVT_SECONDARY SWITCH_PVT_SECONDARY
@ -595,6 +599,13 @@ SWITCH_DECLARE_DATA extern switch_filenames SWITCH_GLOBAL_filenames;
#define SWITCH_ACCEPTABLE_INTERVAL(_i) (_i && _i <= SWITCH_MAX_INTERVAL && (_i % 10) == 0) #define SWITCH_ACCEPTABLE_INTERVAL(_i) (_i && _i <= SWITCH_MAX_INTERVAL && (_i % 10) == 0)
/* Check if RAND_MAX is a power of 2 minus 1 or in other words all bits set */
#if ((RAND_MAX) & ((RAND_MAX) + 1)) == 0 && (RAND_MAX) != 0
#define SWITCH_RAND_MAX RAND_MAX
#else
#define SWITCH_RAND_MAX 0x7fff
#endif
typedef enum { typedef enum {
SWITCH_RW_READ, SWITCH_RW_READ,
SWITCH_RW_WRITE SWITCH_RW_WRITE
@ -2656,10 +2667,12 @@ struct switch_live_array_s;
typedef struct switch_live_array_s switch_live_array_t; typedef struct switch_live_array_s switch_live_array_t;
typedef enum { typedef enum {
SDP_TYPE_REQUEST, SDP_OFFER,
SDP_TYPE_RESPONSE SDP_ANSWER
} switch_sdp_type_t; } switch_sdp_type_t;
#define SDP_TYPE_REQUEST SDP_OFFER
#define SDP_TYPE_RESPONSE SDP_ANSWER
typedef enum { typedef enum {
AEAD_AES_256_GCM_8, AEAD_AES_256_GCM_8,

View File

@ -1514,6 +1514,11 @@ SWITCH_DECLARE(switch_status_t) switch_digest_string(const char *digest_name, ch
SWITCH_DECLARE(char *) switch_must_strdup(const char *_s); SWITCH_DECLARE(char *) switch_must_strdup(const char *_s);
SWITCH_DECLARE(const char *) switch_memory_usage_stream(switch_stream_handle_t *stream); SWITCH_DECLARE(const char *) switch_memory_usage_stream(switch_stream_handle_t *stream);
/**
/ Compliant random number generator. Returns the value between 0 and 0x7fff (RAND_MAX).
**/
SWITCH_DECLARE(int) switch_rand(void);
SWITCH_END_EXTERN_C SWITCH_END_EXTERN_C
#endif #endif
/* For Emacs: /* For Emacs:

View File

@ -906,7 +906,7 @@ static void fs_rtp_parse_h263_rfc2190(h264_codec_context_t *context, AVPacket *p
#if (LIBAVCODEC_VERSION_MAJOR < LIBAVCODEC_V) #if (LIBAVCODEC_VERSION_MAJOR < LIBAVCODEC_V)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Should Not Happen!!! mb_info_pos=%d mb_info_count=%d mb_info_size=%d\n", mb_info_pos, mb_info_count, mb_info_size); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Should Not Happen!!! mb_info_pos=%d mb_info_count=%d mb_info_size=%d\n", mb_info_pos, mb_info_count, mb_info_size);
#else #else
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Should Not Happen!!! mb_info_pos=%d mb_info_count=%d mb_info_size=%ld\n", mb_info_pos, mb_info_count, mb_info_size); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Should Not Happen!!! mb_info_pos=%d mb_info_count=%d mb_info_size=%"SWITCH_SIZE_T_FMT"\n", mb_info_pos, mb_info_count, mb_info_size);
#endif #endif
} }
} }
@ -1581,7 +1581,6 @@ GCC_DIAG_ON(deprecated-declarations)
} else if (ret == AVERROR(EAGAIN)) { } else if (ret == AVERROR(EAGAIN)) {
/* we fully drain all the output in each encode call, so this should not ever happen */ /* we fully drain all the output in each encode call, so this should not ever happen */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9, "Error sending frame to encoder - BUG, should never happen\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9, "Error sending frame to encoder - BUG, should never happen\n");
ret = AVERROR_BUG;
goto error; goto error;
} else if (ret < 0) { } else if (ret < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error sending frame to encoder\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error sending frame to encoder\n");

View File

@ -1170,7 +1170,6 @@ GCC_DIAG_ON(deprecated-declarations)
} else if (ret == AVERROR(EAGAIN)) { } else if (ret == AVERROR(EAGAIN)) {
/* we fully drain all the output in each encode call, so this should not ever happen */ /* we fully drain all the output in each encode call, so this should not ever happen */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9, "Error sending frame to encoder on draining AVERROR_BUG - should never happen\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9, "Error sending frame to encoder on draining AVERROR_BUG - should never happen\n");
ret = AVERROR_BUG;
goto do_break; goto do_break;
} else if (ret < 0) { } else if (ret < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9, "Error sending frame to encoder on draining\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9, "Error sending frame to encoder on draining\n");
@ -1426,7 +1425,7 @@ static switch_status_t open_input_file(av_file_context_t *context, switch_file_h
av_dump_format(context->fc, 0, filename, 0); av_dump_format(context->fc, 0, filename, 0);
for (i = 0; i< context->fc->nb_streams; i++) { for (i = 0; i < context->fc->nb_streams; i++) {
enum AVMediaType codec_type = av_get_codec_type(context->fc->streams[i]); enum AVMediaType codec_type = av_get_codec_type(context->fc->streams[i]);
if (codec_type == AVMEDIA_TYPE_AUDIO && context->has_audio < 2 && idx < 2) { if (codec_type == AVMEDIA_TYPE_AUDIO && context->has_audio < 2 && idx < 2) {
@ -1554,7 +1553,9 @@ static switch_status_t open_input_file(av_file_context_t *context, switch_file_h
if (context->has_audio) { if (context->has_audio) {
AVCodecContext *c[2] = { NULL }; AVCodecContext *c[2] = { NULL };
c[0] = av_get_codec_context(&context->audio_st[0]); if (!(c[0] = av_get_codec_context(&context->audio_st[0]))) {
switch_goto_status(SWITCH_STATUS_FALSE, err);
}
if ((cc = av_get_codec_context(&context->audio_st[1]))) { if ((cc = av_get_codec_context(&context->audio_st[1]))) {
c[1] = cc; c[1] = cc;
@ -1568,9 +1569,7 @@ static switch_status_t open_input_file(av_file_context_t *context, switch_file_h
if (c[1]) { if (c[1]) {
context->audio_st[1].frame = av_frame_alloc(); context->audio_st[1].frame = av_frame_alloc();
switch_assert(context->audio_st[1].frame); switch_assert(context->audio_st[1].frame);
}
if (c[0] && c[1]) {
context->audio_st[0].channels = 1; context->audio_st[0].channels = 1;
context->audio_st[1].channels = 1; context->audio_st[1].channels = 1;
} else { } else {
@ -2016,7 +2015,6 @@ GCC_DIAG_ON(deprecated-declarations)
} else if (dret == AVERROR(EAGAIN)) { } else if (dret == AVERROR(EAGAIN)) {
/* we fully drain all the output in each decode call, so this should not ever happen */ /* we fully drain all the output in each decode call, so this should not ever happen */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9, "Error sending audio packet to decoder - BUG, should never happen\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9, "Error sending audio packet to decoder - BUG, should never happen\n");
dret = AVERROR_BUG;
goto do_continue; goto do_continue;
} else if (dret < 0) { } else if (dret < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9, "Error sending audio packet to decoder\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9, "Error sending audio packet to decoder\n");

View File

@ -2130,9 +2130,7 @@ static enum avmd_detection_mode avmd_process_sample(avmd_session_t *s, circ_buff
sma_buffer_t *sqa_amp_b = &buffer->sqa_amp_b; sma_buffer_t *sqa_amp_b = &buffer->sqa_amp_b;
if (sample_to_skip_n > 0) { if (sample_to_skip_n > 0) {
sample_to_skip_n--;
valid_amplitude = 0;
valid_omega = 0;
return AVMD_DETECT_NONE; return AVMD_DETECT_NONE;
} }
@ -2145,14 +2143,14 @@ static enum avmd_detection_mode avmd_process_sample(avmd_session_t *s, circ_buff
RESET_SMA_BUFFER(sma_amp_b); RESET_SMA_BUFFER(sma_amp_b);
RESET_SMA_BUFFER(sqa_amp_b); RESET_SMA_BUFFER(sqa_amp_b);
buffer->samples_streak_amp = s->settings.sample_n_continuous_streak_amp; buffer->samples_streak_amp = s->settings.sample_n_continuous_streak_amp;
sample_to_skip_n = s->settings.sample_n_to_skip;
} }
} else { } else {
if (ISINF(amplitude)) { if (ISINF(amplitude)) {
amplitude = buffer->amplitude_max; amplitude = buffer->amplitude_max;
} }
if (valid_amplitude == 1) { if (valid_amplitude == 1) {
APPEND_SMA_VAL(sma_amp_b, amplitude); /* append amplitude */ APPEND_SMA_VAL(sma_amp_b, amplitude); /* append amplitude */
APPEND_SMA_VAL(sqa_amp_b, amplitude * amplitude); APPEND_SMA_VAL(sqa_amp_b, amplitude * amplitude);
if (s->settings.require_continuous_streak_amp == 1) { if (s->settings.require_continuous_streak_amp == 1) {
if (buffer->samples_streak_amp > 0) { if (buffer->samples_streak_amp > 0) {
@ -2161,6 +2159,7 @@ static enum avmd_detection_mode avmd_process_sample(avmd_session_t *s, circ_buff
} }
} }
} }
if (sma_amp_b->sma > buffer->amplitude_max) { if (sma_amp_b->sma > buffer->amplitude_max) {
buffer->amplitude_max = sma_amp_b->sma; buffer->amplitude_max = sma_amp_b->sma;
} }
@ -2176,9 +2175,7 @@ static enum avmd_detection_mode avmd_process_sample(avmd_session_t *s, circ_buff
RESET_SMA_BUFFER(sma_b_fir); RESET_SMA_BUFFER(sma_b_fir);
RESET_SMA_BUFFER(sqa_b_fir); RESET_SMA_BUFFER(sqa_b_fir);
buffer->samples_streak = s->settings.sample_n_continuous_streak; buffer->samples_streak = s->settings.sample_n_continuous_streak;
sample_to_skip_n = s->settings.sample_n_to_skip;
} }
sample_to_skip_n = s->settings.sample_n_to_skip;
} else if (omega < -0.99999 || omega > 0.99999) { } else if (omega < -0.99999 || omega > 0.99999) {
valid_omega = 0; valid_omega = 0;
if (s->settings.require_continuous_streak == 1) { if (s->settings.require_continuous_streak == 1) {
@ -2187,7 +2184,6 @@ static enum avmd_detection_mode avmd_process_sample(avmd_session_t *s, circ_buff
RESET_SMA_BUFFER(sma_b_fir); RESET_SMA_BUFFER(sma_b_fir);
RESET_SMA_BUFFER(sqa_b_fir); RESET_SMA_BUFFER(sqa_b_fir);
buffer->samples_streak = s->settings.sample_n_continuous_streak; buffer->samples_streak = s->settings.sample_n_continuous_streak;
sample_to_skip_n = s->settings.sample_n_to_skip;
} }
} else { } else {
if (valid_omega) { if (valid_omega) {
@ -2216,20 +2212,26 @@ static enum avmd_detection_mode avmd_process_sample(avmd_session_t *s, circ_buff
if (((mode == AVMD_DETECT_AMP) || (mode == AVMD_DETECT_BOTH)) && (valid_amplitude == 1)) { if (((mode == AVMD_DETECT_AMP) || (mode == AVMD_DETECT_BOTH)) && (valid_amplitude == 1)) {
v_amp = sqa_amp_b->sma - (sma_amp_b->sma * sma_amp_b->sma); /* calculate variance of amplitude (biased estimator) */ v_amp = sqa_amp_b->sma - (sma_amp_b->sma * sma_amp_b->sma); /* calculate variance of amplitude (biased estimator) */
if ((mode == AVMD_DETECT_AMP) && (avmd_decision_amplitude(s, buffer, v_amp, AVMD_AMPLITUDE_RSD_THRESHOLD) == 1)) { if ((mode == AVMD_DETECT_AMP) && (avmd_decision_amplitude(s, buffer, v_amp, AVMD_AMPLITUDE_RSD_THRESHOLD) == 1)) {
return AVMD_DETECT_AMP; return AVMD_DETECT_AMP;
} }
} }
if (((mode == AVMD_DETECT_FREQ) || (mode == AVMD_DETECT_BOTH)) && (valid_omega == 1)) { if (((mode == AVMD_DETECT_FREQ) || (mode == AVMD_DETECT_BOTH)) && (valid_omega == 1)) {
v_fir = sqa_b_fir->sma - (sma_b_fir->sma * sma_b_fir->sma); /* calculate variance of filtered samples */ v_fir = sqa_b_fir->sma - (sma_b_fir->sma * sma_b_fir->sma); /* calculate variance of filtered samples */
if ((mode == AVMD_DETECT_FREQ) && (avmd_decision_freq(s, buffer, v_fir, AVMD_VARIANCE_RSD_THRESHOLD) == 1)) { if ((mode == AVMD_DETECT_FREQ) && (avmd_decision_freq(s, buffer, v_fir, AVMD_VARIANCE_RSD_THRESHOLD) == 1)) {
return AVMD_DETECT_FREQ; return AVMD_DETECT_FREQ;
} }
if (mode == AVMD_DETECT_BOTH) { if (mode == AVMD_DETECT_BOTH) {
if ((avmd_decision_amplitude(s, buffer, v_amp, AVMD_AMPLITUDE_RSD_THRESHOLD) == 1) && (avmd_decision_freq(s, buffer, v_fir, AVMD_VARIANCE_RSD_THRESHOLD) == 1)) { if ((avmd_decision_amplitude(s, buffer, v_amp, AVMD_AMPLITUDE_RSD_THRESHOLD) == 1) && (avmd_decision_freq(s, buffer, v_fir, AVMD_VARIANCE_RSD_THRESHOLD) == 1)) {
return AVMD_DETECT_BOTH; return AVMD_DETECT_BOTH;
} }
} }
} }
return AVMD_DETECT_NONE; return AVMD_DETECT_NONE;
} }

View File

@ -1316,15 +1316,15 @@ void conference_loop_output(conference_member_t *member)
uint32_t flush_len; uint32_t flush_len;
uint32_t low_count, bytes; uint32_t low_count, bytes;
call_list_t *call_list, *cp; call_list_t *call_list, *cp;
switch_codec_implementation_t read_impl = { 0 }, real_read_impl = { 0 }; switch_codec_implementation_t real_read_impl = { 0 };
int sanity; int sanity;
switch_core_session_get_read_impl(member->session, &read_impl); switch_core_session_get_read_impl(member->session, &member->read_impl);
switch_core_session_get_real_read_impl(member->session, &real_read_impl); switch_core_session_get_real_read_impl(member->session, &real_read_impl);
channel = switch_core_session_get_channel(member->session); channel = switch_core_session_get_channel(member->session);
interval = read_impl.microseconds_per_packet / 1000; interval = member->read_impl.microseconds_per_packet / 1000;
samples = switch_samples_per_packet(member->conference->rate, interval); samples = switch_samples_per_packet(member->conference->rate, interval);
//csamples = samples; //csamples = samples;
tsamples = real_read_impl.samples_per_packet; tsamples = real_read_impl.samples_per_packet;

View File

@ -1363,7 +1363,7 @@ void conference_xlist(conference_obj_t *conference, switch_xml_t x_conference, i
void conference_jlist(conference_obj_t *conference, cJSON *json_conferences) void conference_jlist(conference_obj_t *conference, cJSON *json_conferences)
{ {
conference_member_t *member = NULL; conference_member_t *member = NULL;
static cJSON *json_conference, *json_conference_variables, *json_conference_members, *json_conference_member, *json_conference_member_flags; cJSON *json_conference, *json_conference_variables, *json_conference_members, *json_conference_member, *json_conference_member_flags;
switch_event_header_t *hp; switch_event_header_t *hp;
switch_assert(conference != NULL); switch_assert(conference != NULL);

View File

@ -593,7 +593,7 @@ SWITCH_STANDARD_APP(filter_codecs_function)
r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE); r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
if (data && r_sdp) { if (data && r_sdp) {
switch_core_media_merge_sdp_codec_string(session, r_sdp, SDP_TYPE_REQUEST, data); switch_core_media_merge_sdp_codec_string(session, r_sdp, SDP_OFFER, data);
switch_channel_set_variable(channel, "filter_codec_string", data); switch_channel_set_variable(channel, "filter_codec_string", data);
} else { } else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Incomplete data\n"); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Incomplete data\n");

View File

@ -40,6 +40,11 @@ SWITCH_MODULE_DEFINITION(mod_fsv, mod_fsv_load, NULL, NULL);
#define VID_BIT (1 << 31) #define VID_BIT (1 << 31)
#define VERSION 4202 #define VERSION 4202
typedef struct fsv_video_data_s {
uint32_t size;
uint8_t data[];
} fsv_video_data_t;
struct file_header { struct file_header {
int32_t version; int32_t version;
char video_codec_name[32]; char video_codec_name[32];
@ -983,15 +988,16 @@ again:
} }
if (size & VID_BIT) { /* video */ if (size & VID_BIT) { /* video */
uint8_t *video_data = malloc(sizeof(size) + size); fsv_video_data_t *video_data;
switch_size_t read_size; switch_size_t read_size;
switch_assert(video_data);
size &= ~VID_BIT; size &= ~VID_BIT;
video_data = malloc(sizeof(fsv_video_data_t) + size);
switch_assert(video_data);
read_size = size; read_size = size;
*(uint32_t *)video_data = size; video_data->size = size;
status = switch_file_read(context->fd, video_data + sizeof(size), &read_size); status = switch_file_read(context->fd, video_data->data, &read_size);
if (status != SWITCH_STATUS_SUCCESS || read_size != size) { if (status != SWITCH_STATUS_SUCCESS || read_size != size) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
@ -1033,7 +1039,7 @@ static switch_status_t fsv_file_read_video(switch_file_handle_t *handle, switch_
fsv_file_context *context = handle->private_info; fsv_file_context *context = handle->private_info;
switch_image_t *dup = NULL; switch_image_t *dup = NULL;
switch_status_t status = SWITCH_STATUS_SUCCESS; switch_status_t status = SWITCH_STATUS_SUCCESS;
void *video_packet = NULL; fsv_video_data_t *video_packet = NULL;
switch_time_t start = switch_time_now(); switch_time_t start = switch_time_now();
switch_status_t decode_status = SWITCH_STATUS_MORE_DATA; switch_status_t decode_status = SWITCH_STATUS_MORE_DATA;
int new_img = 0; int new_img = 0;
@ -1047,8 +1053,9 @@ static switch_status_t fsv_file_read_video(switch_file_handle_t *handle, switch_
switch_rtp_hdr_t *rtp; switch_rtp_hdr_t *rtp;
while (1) { while (1) {
video_packet = NULL;
switch_mutex_lock(context->mutex); switch_mutex_lock(context->mutex);
status = switch_queue_trypop(context->video_queue, &video_packet); status = switch_queue_trypop(context->video_queue, (void**)&video_packet);
switch_mutex_unlock(context->mutex); switch_mutex_unlock(context->mutex);
if (status != SWITCH_STATUS_SUCCESS || !video_packet) { if (status != SWITCH_STATUS_SUCCESS || !video_packet) {
@ -1065,13 +1072,13 @@ static switch_status_t fsv_file_read_video(switch_file_handle_t *handle, switch_
break; break;
} }
size = *(uint32_t *)video_packet; size = video_packet->size;
if (size > sizeof(context->video_packet_buffer)) { if (size > sizeof(context->video_packet_buffer)) {
free(video_packet); free(video_packet);
return SWITCH_STATUS_BREAK; return SWITCH_STATUS_BREAK;
} }
memcpy(context->video_packet_buffer, (uint8_t *)video_packet + sizeof(uint32_t), size); memcpy(context->video_packet_buffer, video_packet->data, size);
free(video_packet); free(video_packet);
video_packet = NULL; video_packet = NULL;
@ -1093,14 +1100,15 @@ static switch_status_t fsv_file_read_video(switch_file_handle_t *handle, switch_
uint32_t size; uint32_t size;
switch_rtp_hdr_t *rtp; switch_rtp_hdr_t *rtp;
switch_mutex_lock(context->mutex); video_packet = NULL;
status = switch_queue_trypop(context->video_queue, &video_packet); switch_mutex_lock(context->mutex);
status = switch_queue_trypop(context->video_queue, (void**)&video_packet);
switch_mutex_unlock(context->mutex); switch_mutex_unlock(context->mutex);
if (status != SWITCH_STATUS_SUCCESS || !video_packet) break; if (status != SWITCH_STATUS_SUCCESS || !video_packet) break;
size = *(uint32_t *)video_packet; size = video_packet->size;
rtp = (switch_rtp_hdr_t *)((uint8_t *)video_packet + sizeof(uint32_t)); rtp = (switch_rtp_hdr_t *)(video_packet->data);
rtp_frame.packet = rtp; rtp_frame.packet = rtp;
rtp_frame.packetlen = size; rtp_frame.packetlen = size;

View File

@ -250,6 +250,7 @@ static switch_status_t switch_amr_init(switch_codec_t *codec, switch_codec_flag_
int x, i, argc, fmtptmp_pos; int x, i, argc, fmtptmp_pos;
char *argv[10]; char *argv[10];
char fmtptmp[128]; char fmtptmp[128];
char *fmtp_dup = NULL;
encoding = (flags & SWITCH_CODEC_FLAG_ENCODE); encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
decoding = (flags & SWITCH_CODEC_FLAG_DECODE); decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
@ -283,13 +284,19 @@ static switch_status_t switch_amr_init(switch_codec_t *codec, switch_codec_flag_
switch_set_flag(context, AMR_OPT_OCTET_ALIGN); switch_set_flag(context, AMR_OPT_OCTET_ALIGN);
} }
if (codec->fmtp_in) { if (codec->fmtp_in) {
argc = switch_separate_string(codec->fmtp_in, ';', argv, (sizeof(argv) / sizeof(argv[0]))); fmtp_dup = strdup(codec->fmtp_in);
switch_assert(fmtp_dup);
argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0])));
for (x = 0; x < argc; x++) { for (x = 0; x < argc; x++) {
char *data = argv[x]; char *data = argv[x];
char *arg; char *arg;
while (*data && *data == ' ') { while (*data && *data == ' ') {
data++; data++;
} }
if ((arg = strchr(data, '='))) { if ((arg = strchr(data, '='))) {
*arg++ = '\0'; *arg++ = '\0';
if (!strcasecmp(data, "octet-align")) { if (!strcasecmp(data, "octet-align")) {
@ -325,13 +332,17 @@ static switch_status_t switch_amr_init(switch_codec_t *codec, switch_codec_flag_
} else if (!strcasecmp(data, "mode-set")) { } else if (!strcasecmp(data, "mode-set")) {
int y, m_argc; int y, m_argc;
char *m_argv[SWITCH_AMR_MODES-1]; char *m_argv[SWITCH_AMR_MODES-1];
m_argc = switch_separate_string(arg, ',', m_argv, (sizeof(m_argv) / sizeof(m_argv[0]))); m_argc = switch_separate_string(arg, ',', m_argv, (sizeof(m_argv) / sizeof(m_argv[0])));
for (y = 0; y < m_argc; y++) { for (y = 0; y < m_argc; y++) {
context->enc_modes |= (1 << atoi(m_argv[y])); context->enc_modes |= (1 << atoi(m_argv[y]));
} }
} }
} }
} }
free(fmtp_dup);
} }
if (context->enc_modes) { if (context->enc_modes) {
@ -475,13 +486,15 @@ static switch_status_t switch_amr_decode(switch_codec_t *codec,
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
#else #else
struct amr_context *context = codec->private_info; struct amr_context *context = codec->private_info;
unsigned char *buf = encoded_data; unsigned char buf[SWITCH_AMR_OUT_MAX_SIZE];
uint8_t tmp[SWITCH_AMR_OUT_MAX_SIZE]; uint8_t tmp[SWITCH_AMR_OUT_MAX_SIZE];
if (!context) { if (!context || encoded_data_len > SWITCH_AMR_OUT_MAX_SIZE) {
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
memcpy(buf, encoded_data, encoded_data_len);
if (globals.debug) { if (globals.debug) {
switch_amr_info(codec, buf, encoded_data_len, switch_test_flag(context, AMR_OPT_OCTET_ALIGN) ? 1 : 0, "AMR decoder"); switch_amr_info(codec, buf, encoded_data_len, switch_test_flag(context, AMR_OPT_OCTET_ALIGN) ? 1 : 0, "AMR decoder");
} }

View File

@ -95,23 +95,23 @@ extern switch_bool_t switch_amrwb_pack_be(unsigned char *shift_buf, int n)
extern switch_bool_t switch_amrwb_unpack_be(unsigned char *encoded_buf, uint8_t *tmp, int encoded_len) extern switch_bool_t switch_amrwb_unpack_be(unsigned char *encoded_buf, uint8_t *tmp, int encoded_len)
{ {
int framesz, index, ft; int framesz, index;
uint8_t shift_tocs[2] = {0x00, 0x00}; uint8_t shift_tocs[2] = {0x00, 0x00};
uint8_t *shift_buf; uint8_t *shift_buf;
memcpy(shift_tocs, encoded_buf, 2); memcpy(shift_tocs, encoded_buf, 2);
/* shift for BE */ /* shift for BE */
switch_amr_array_lshift(4, shift_tocs, 2); switch_amr_array_lshift(4, shift_tocs, 2);
ft = shift_tocs[0] >> 3;
ft &= ~(1 << 5); /* Frame Type*/
shift_buf = encoded_buf + 1; /* skip CMR */ shift_buf = encoded_buf + 1; /* skip CMR */
/* shift for BE */ /* shift for BE */
switch_amr_array_lshift(2, shift_buf, encoded_len - 1); switch_amr_array_lshift(2, shift_buf, encoded_len - 1);
/* get frame size */ /* get frame size */
index = ((shift_tocs[0] >> 3) & 0x0f); index = ((shift_tocs[0] >> 3) & 0x0f);
if (index > 10 && index != 0xe && index != 0xf) { if (index > 10 && index != 0xe && index != 0xf) {
return SWITCH_FALSE; return SWITCH_FALSE;
} }
framesz = switch_amrwb_frame_sizes[index]; framesz = switch_amrwb_frame_sizes[index];
tmp[0] = shift_tocs[0]; /* save TOC */ tmp[0] = shift_tocs[0]; /* save TOC */
memcpy(&tmp[1], shift_buf, framesz); memcpy(&tmp[1], shift_buf, framesz);

View File

@ -191,6 +191,7 @@ static switch_status_t switch_amrwb_init(switch_codec_t *codec, switch_codec_fla
if (codec->fmtp_in) { if (codec->fmtp_in) {
codec->fmtp_out = switch_core_strdup(codec->memory_pool, codec->fmtp_in); codec->fmtp_out = switch_core_strdup(codec->memory_pool, codec->fmtp_in);
} }
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
#else #else
struct amrwb_context *context = NULL; struct amrwb_context *context = NULL;
@ -198,11 +199,13 @@ static switch_status_t switch_amrwb_init(switch_codec_t *codec, switch_codec_fla
int x, i, argc, fmtptmp_pos; int x, i, argc, fmtptmp_pos;
char *argv[10]; char *argv[10];
char fmtptmp[128]; char fmtptmp[128];
char *fmtp_dup = NULL;
encoding = (flags & SWITCH_CODEC_FLAG_ENCODE); encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
decoding = (flags & SWITCH_CODEC_FLAG_DECODE); decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
if (!(encoding || decoding) || (!(context = switch_core_alloc(codec->memory_pool, sizeof(struct amrwb_context))))) { if (!(encoding || decoding) || (!(context = switch_core_alloc(codec->memory_pool, sizeof(struct amrwb_context))))) {
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} else { } else {
@ -222,13 +225,19 @@ static switch_status_t switch_amrwb_init(switch_codec_t *codec, switch_codec_fla
} }
if (codec->fmtp_in) { if (codec->fmtp_in) {
argc = switch_separate_string(codec->fmtp_in, ';', argv, (sizeof(argv) / sizeof(argv[0]))); fmtp_dup = strdup(codec->fmtp_in);
switch_assert(fmtp_dup);
argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0])));
for (x = 0; x < argc; x++) { for (x = 0; x < argc; x++) {
char *data = argv[x]; char *data = argv[x];
char *arg; char *arg;
while (*data && *data == ' ') { while (*data && *data == ' ') {
data++; data++;
} }
if ((arg = strchr(data, '='))) { if ((arg = strchr(data, '='))) {
*arg++ = '\0'; *arg++ = '\0';
if (!strcasecmp(data, "octet-align")) { if (!strcasecmp(data, "octet-align")) {
@ -264,7 +273,9 @@ static switch_status_t switch_amrwb_init(switch_codec_t *codec, switch_codec_fla
} else if (!strcasecmp(data, "mode-set")) { } else if (!strcasecmp(data, "mode-set")) {
int y, m_argc; int y, m_argc;
char *m_argv[SWITCH_AMRWB_MODES-1]; /* AMRWB has 9 modes */ char *m_argv[SWITCH_AMRWB_MODES-1]; /* AMRWB has 9 modes */
m_argc = switch_separate_string(arg, ',', m_argv, (sizeof(m_argv) / sizeof(m_argv[0]))); m_argc = switch_separate_string(arg, ',', m_argv, (sizeof(m_argv) / sizeof(m_argv[0])));
for (y = 0; y < m_argc; y++) { for (y = 0; y < m_argc; y++) {
context->enc_modes |= (1 << atoi(m_argv[y])); context->enc_modes |= (1 << atoi(m_argv[y]));
context->enc_mode = atoi(m_argv[y]); context->enc_mode = atoi(m_argv[y]);
@ -272,6 +283,8 @@ static switch_status_t switch_amrwb_init(switch_codec_t *codec, switch_codec_fla
} }
} }
} }
free(fmtp_dup);
} }
if (context->enc_modes && !globals.mode_set_overwrite) { if (context->enc_modes && !globals.mode_set_overwrite) {
@ -285,6 +298,7 @@ static switch_status_t switch_amrwb_init(switch_codec_t *codec, switch_codec_fla
/* re-create mode-set */ /* re-create mode-set */
fmtptmp_pos = switch_snprintf(fmtptmp, sizeof(fmtptmp), "mode-set="); fmtptmp_pos = switch_snprintf(fmtptmp, sizeof(fmtptmp), "mode-set=");
for (i = 0; SWITCH_AMRWB_MODES-1 > i; ++i) { for (i = 0; SWITCH_AMRWB_MODES-1 > i; ++i) {
if (context->enc_modes & (1 << i)) { if (context->enc_modes & (1 << i)) {
fmtptmp_pos += switch_snprintf(fmtptmp + fmtptmp_pos, sizeof(fmtptmp) - fmtptmp_pos, fmtptmp_pos > strlen("mode-set=") ? ",%d" : "%d", i); fmtptmp_pos += switch_snprintf(fmtptmp + fmtptmp_pos, sizeof(fmtptmp) - fmtptmp_pos, fmtptmp_pos > strlen("mode-set=") ? ",%d" : "%d", i);
@ -301,12 +315,13 @@ static switch_status_t switch_amrwb_init(switch_codec_t *codec, switch_codec_fla
} }
if (!globals.volte) { if (!globals.volte) {
fmtptmp_pos += switch_snprintf(fmtptmp + fmtptmp_pos, sizeof(fmtptmp) - fmtptmp_pos, ";octet-align=%d", switch_snprintf(fmtptmp + fmtptmp_pos, sizeof(fmtptmp) - fmtptmp_pos, ";octet-align=%d",
switch_test_flag(context, AMRWB_OPT_OCTET_ALIGN) ? 1 : 0); switch_test_flag(context, AMRWB_OPT_OCTET_ALIGN) ? 1 : 0);
} else { } else {
fmtptmp_pos += switch_snprintf(fmtptmp + fmtptmp_pos, sizeof(fmtptmp) - fmtptmp_pos, ";octet-align=%d;max-red=0;mode-change-capability=2", switch_snprintf(fmtptmp + fmtptmp_pos, sizeof(fmtptmp) - fmtptmp_pos, ";octet-align=%d;max-red=0;mode-change-capability=2",
switch_test_flag(context, AMRWB_OPT_OCTET_ALIGN) ? 1 : 0); switch_test_flag(context, AMRWB_OPT_OCTET_ALIGN) ? 1 : 0);
} }
codec->fmtp_out = switch_core_strdup(codec->memory_pool, fmtptmp); codec->fmtp_out = switch_core_strdup(codec->memory_pool, fmtptmp);
context->encoder_state = NULL; context->encoder_state = NULL;
@ -401,13 +416,15 @@ static switch_status_t switch_amrwb_decode(switch_codec_t *codec,
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
#else #else
struct amrwb_context *context = codec->private_info; struct amrwb_context *context = codec->private_info;
unsigned char *buf = encoded_data; unsigned char buf[SWITCH_AMRWB_OUT_MAX_SIZE];
uint8_t tmp[SWITCH_AMRWB_OUT_MAX_SIZE]; uint8_t tmp[SWITCH_AMRWB_OUT_MAX_SIZE];
if (!context) { if (!context || encoded_data_len > SWITCH_AMRWB_OUT_MAX_SIZE) {
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
memcpy(buf, encoded_data, encoded_data_len);
if (globals.debug) { if (globals.debug) {
switch_amrwb_info(codec, buf, encoded_data_len, switch_test_flag(context, AMRWB_OPT_OCTET_ALIGN) ? 1 : 0, "AMRWB decoder"); switch_amrwb_info(codec, buf, encoded_data_len, switch_test_flag(context, AMRWB_OPT_OCTET_ALIGN) ? 1 : 0, "AMRWB decoder");
} }

View File

@ -930,7 +930,7 @@ static switch_status_t switch_opus_decode(switch_codec_t *codec,
if (samples < 0) { if (samples < 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Decoder Error: %s fs:%u plc:%s!\n", switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Decoder Error: %s fs:%u plc:%s!\n",
opus_strerror(samples), frame_size, plc ? "true" : "false"); opus_strerror(samples), frame_size, plc ? "true" : "false");
return SWITCH_STATUS_NOOP; return SWITCH_STATUS_FALSE;
} }
*decoded_data_len = samples * 2 * (!context->codec_settings.sprop_stereo ? codec->implementation->number_of_channels : 2); *decoded_data_len = samples * 2 * (!context->codec_settings.sprop_stereo ? codec->implementation->number_of_channels : 2);

View File

@ -81,13 +81,13 @@ public:
std::string value = pair[1]; std::string value = pair[1];
if ("server" == key || "host" == key) { if ("server" == key || "host" == key) {
_host = value; _host = std::move(value);
} else if ("uid" == key || "user" == key || "username" == key) { } else if ("uid" == key || "user" == key || "username" == key) {
_user = value; _user = std::move(value);
} else if ("pwd" == key || "passwd" == key || "password" == key) { } else if ("pwd" == key || "passwd" == key || "password" == key) {
_passwd = value; _passwd = std::move(value);
} else if ("database" == key || "db" == key) { } else if ("database" == key || "db" == key) {
_db = value; _db = std::move(value);
} else if ("port" == key) { } else if ("port" == key) {
_port = std::stoi(value); _port = std::stoi(value);
} else if ("option" == key || "options" == key) { } else if ("option" == key || "options" == key) {

View File

@ -641,7 +641,7 @@ switch_status_t mariadb_send_query(mariadb_handle_t *handle, const char* sql)
switch_safe_free(err_str); switch_safe_free(err_str);
/* We are waiting for 500 ms and random time is not more than 500 ms. /* We are waiting for 500 ms and random time is not more than 500 ms.
This is necessary so that the delay on the primary and secondary servers does not coincide and deadlock does not occur again. */ This is necessary so that the delay on the primary and secondary servers does not coincide and deadlock does not occur again. */
switch_yield(500 + (rand() & 511)); switch_yield(500 + (switch_rand() & 511));
goto again; goto again;
} }

View File

@ -1429,7 +1429,7 @@ static switch_status_t null_tech_init(null_private_t *tech_pvt, switch_core_sess
// switch_core_media_check_video_codecs(session); // switch_core_media_check_video_codecs(session);
// switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_AUDIO, 0); // switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_AUDIO, 0);
// switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_VIDEO, 0); // switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_VIDEO, 0);
// switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, "127.0.0.1", 2000, NULL, 0); // switch_core_media_gen_local_sdp(session, SDP_OFFER, "127.0.0.1", 2000, NULL, 0);
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s\n", mparams.local_sdp_str); // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s\n", mparams.local_sdp_str);
} }

View File

@ -488,7 +488,7 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
if (sofia_test_pflag(tech_pvt->profile, PFLAG_DESTROY)) { if (sofia_test_pflag(tech_pvt->profile, PFLAG_DESTROY)) {
sofia_set_flag(tech_pvt, TFLAG_BYE); sofia_set_flag(tech_pvt, TFLAG_BYE);
} else if (tech_pvt->nh && !sofia_test_flag(tech_pvt, TFLAG_BYE)) { } else if (tech_pvt->nh && !sofia_test_flag(tech_pvt, TFLAG_BYE)) {
char reason[128] = ""; char *reason = switch_core_session_sprintf(session, "");
char *bye_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_BYE_HEADER_PREFIX); char *bye_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_BYE_HEADER_PREFIX);
const char *val = NULL; const char *val = NULL;
const char *max_forwards = switch_channel_get_variable(channel, SWITCH_MAX_FORWARDS_VARIABLE); const char *max_forwards = switch_channel_get_variable(channel, SWITCH_MAX_FORWARDS_VARIABLE);
@ -499,15 +499,15 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
if (!val || switch_false(val)) { if (!val || switch_false(val)) {
if ((val = switch_channel_get_variable(tech_pvt->channel, "sip_reason"))) { if ((val = switch_channel_get_variable(tech_pvt->channel, "sip_reason"))) {
switch_snprintf(reason, sizeof(reason), "%s", val); reason = switch_core_session_sprintf(session, "%s", val);
} else { } else {
if ((switch_channel_test_flag(channel, CF_INTERCEPT) || cause == SWITCH_CAUSE_PICKED_OFF || cause == SWITCH_CAUSE_LOSE_RACE) if ((switch_channel_test_flag(channel, CF_INTERCEPT) || cause == SWITCH_CAUSE_PICKED_OFF || cause == SWITCH_CAUSE_LOSE_RACE)
&& !switch_true(switch_channel_get_variable(channel, "ignore_completed_elsewhere"))) { && !switch_true(switch_channel_get_variable(channel, "ignore_completed_elsewhere"))) {
switch_snprintf(reason, sizeof(reason), "SIP;cause=200;text=\"Call completed elsewhere\""); reason = switch_core_session_sprintf(session, "SIP;cause=200;text=\"Call completed elsewhere\"");
} else if (cause > 0 && cause < 128) { } else if (cause > 0 && cause < 128) {
switch_snprintf(reason, sizeof(reason), "Q.850;cause=%d;text=\"%s\"", cause, switch_channel_cause2str(cause)); reason = switch_core_session_sprintf(session, "Q.850;cause=%d;text=\"%s\"", cause, switch_channel_cause2str(cause));
} else { } else {
switch_snprintf(reason, sizeof(reason), "SIP;cause=%d;text=\"%s\"", cause, switch_channel_cause2str(cause)); reason = switch_core_session_sprintf(session, "SIP;cause=%d;text=\"%s\"", cause, switch_channel_cause2str(cause));
} }
} }
} }
@ -790,7 +790,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE); switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
tech_pvt->mparams.local_sdp_str = NULL; tech_pvt->mparams.local_sdp_str = NULL;
switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0); switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0);
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0); switch_core_media_gen_local_sdp(session, SDP_ANSWER, NULL, 0, NULL, 0);
} else if (is_3pcc_proxy) { } else if (is_3pcc_proxy) {
if (!(sofia_test_pflag(tech_pvt->profile, PFLAG_3PCC_PROXY))) { if (!(sofia_test_pflag(tech_pvt->profile, PFLAG_3PCC_PROXY))) {
@ -802,7 +802,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
} else { } else {
switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0); switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0);
switch_core_media_prepare_codecs(session, 1); switch_core_media_prepare_codecs(session, 1);
switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 1); switch_core_media_gen_local_sdp(session, SDP_OFFER, NULL, 0, NULL, 1);
sofia_set_flag_locked(tech_pvt, TFLAG_3PCC); sofia_set_flag_locked(tech_pvt, TFLAG_3PCC);
} }
@ -889,7 +889,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE); switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
if (zstr(r_sdp) || sofia_media_tech_media(tech_pvt, r_sdp, SDP_TYPE_REQUEST) != SWITCH_STATUS_SUCCESS) { if (zstr(r_sdp) || sofia_media_tech_media(tech_pvt, r_sdp, SDP_OFFER) != SWITCH_STATUS_SUCCESS) {
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR"); switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR");
//switch_mutex_lock(tech_pvt->sofia_mutex); //switch_mutex_lock(tech_pvt->sofia_mutex);
//nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE, TAG_END()); //nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE, TAG_END());
@ -904,7 +904,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
return status; return status;
} }
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0); switch_core_media_gen_local_sdp(session, SDP_ANSWER, NULL, 0, NULL, 0);
if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) { if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
} }
@ -1598,7 +1598,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
ip = switch_channel_get_variable(channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE); ip = switch_channel_get_variable(channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE);
port = switch_channel_get_variable(channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE); port = switch_channel_get_variable(channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE);
if (ip && port) { if (ip && port) {
switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, ip, (switch_port_t)atoi(port), msg->string_arg, 1); switch_core_media_gen_local_sdp(session, SDP_OFFER, ip, (switch_port_t)atoi(port), msg->string_arg, 1);
} }
if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) { if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
@ -1783,7 +1783,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) { if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE); switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
if (sofia_media_tech_media(tech_pvt, r_sdp, SDP_TYPE_REQUEST) != SWITCH_STATUS_SUCCESS) { if (sofia_media_tech_media(tech_pvt, r_sdp, SDP_OFFER) != SWITCH_STATUS_SUCCESS) {
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR"); switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR");
status = SWITCH_STATUS_FALSE; status = SWITCH_STATUS_FALSE;
goto end_lock; goto end_lock;
@ -1793,7 +1793,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
} }
switch_core_media_set_sdp_codec_string(tech_pvt->session, r_sdp, SDP_TYPE_RESPONSE); switch_core_media_set_sdp_codec_string(tech_pvt->session, r_sdp, SDP_ANSWER);
switch_channel_set_variable(tech_pvt->channel, "absolute_codec_string", switch_channel_get_variable(tech_pvt->channel, "ep_codec_string")); switch_channel_set_variable(tech_pvt->channel, "absolute_codec_string", switch_channel_get_variable(tech_pvt->channel, "ep_codec_string"));
switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE); switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
@ -1802,7 +1802,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
goto end_lock; goto end_lock;
} }
switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 1); switch_core_media_gen_local_sdp(session, SDP_OFFER, NULL, 0, NULL, 1);
if (!msg->numeric_arg) { if (!msg->numeric_arg) {
if (send_invite) { if (send_invite) {
@ -2256,7 +2256,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
switch_channel_clear_flag(tech_pvt->channel, CF_AWAITING_STREAM_CHANGE); switch_channel_clear_flag(tech_pvt->channel, CF_AWAITING_STREAM_CHANGE);
switch_core_session_local_crypto_key(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO); switch_core_session_local_crypto_key(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0); switch_core_media_gen_local_sdp(session, SDP_ANSWER, NULL, 0, NULL, 0);
if (sofia_use_soa(tech_pvt)) { if (sofia_use_soa(tech_pvt)) {
nua_respond(tech_pvt->nh, SIP_200_OK, nua_respond(tech_pvt->nh, SIP_200_OK,
@ -2584,7 +2584,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE); switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
if (zstr(r_sdp) || sofia_media_tech_media(tech_pvt, r_sdp, SDP_TYPE_REQUEST) != SWITCH_STATUS_SUCCESS) { if (zstr(r_sdp) || sofia_media_tech_media(tech_pvt, r_sdp, SDP_OFFER) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
"CODEC NEGOTIATION ERROR. SDP:\n%s\n", r_sdp ? r_sdp : "NO SDP!"); "CODEC NEGOTIATION ERROR. SDP:\n%s\n", r_sdp ? r_sdp : "NO SDP!");
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR"); switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR");
@ -2599,7 +2599,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
goto end_lock; goto end_lock;
} }
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0); switch_core_media_gen_local_sdp(session, SDP_ANSWER, NULL, 0, NULL, 0);
if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) { if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
} }

View File

@ -776,7 +776,7 @@ struct sofia_profile {
int watchdog_enabled; int watchdog_enabled;
switch_mutex_t *gw_mutex; switch_mutex_t *gw_mutex;
uint32_t queued_events; uint32_t queued_events;
uint32_t last_cseq; switch_uint31_t last_cseq;
int tls_only; int tls_only;
int tls_verify_date; int tls_verify_date;
enum tport_tls_verify_policy tls_verify_policy; enum tport_tls_verify_policy tls_verify_policy;

View File

@ -6683,7 +6683,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
tech_pvt->mparams.last_sdp_response = NULL; tech_pvt->mparams.last_sdp_response = NULL;
if (sip->sip_payload && sip->sip_payload->pl_data) { if (sip->sip_payload && sip->sip_payload->pl_data) {
switch_core_media_set_sdp_codec_string(session, sip->sip_payload->pl_data, SDP_TYPE_RESPONSE); switch_core_media_set_sdp_codec_string(session, sip->sip_payload->pl_data, SDP_ANSWER);
if (!zstr(tech_pvt->mparams.prev_sdp_response) && !strcmp(tech_pvt->mparams.prev_sdp_response, sip->sip_payload->pl_data)) { if (!zstr(tech_pvt->mparams.prev_sdp_response) && !strcmp(tech_pvt->mparams.prev_sdp_response, sip->sip_payload->pl_data)) {
tech_pvt->mparams.last_sdp_response = tech_pvt->mparams.prev_sdp_response; tech_pvt->mparams.last_sdp_response = tech_pvt->mparams.prev_sdp_response;
@ -7506,9 +7506,9 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
switch_channel_mark_pre_answered(channel); switch_channel_mark_pre_answered(channel);
} }
//if ((sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) || switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND)) { //if ((sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) || switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND)) {
// switch_core_media_set_sdp_codec_string(session, r_sdp, status < 200 ? SDP_TYPE_REQUEST : SDP_TYPE_RESPONSE); // switch_core_media_set_sdp_codec_string(session, r_sdp, status < 200 ? SDP_OFFER : SDP_ANSWER);
//} //}
switch_core_media_set_sdp_codec_string(session, r_sdp, SDP_TYPE_REQUEST); switch_core_media_set_sdp_codec_string(session, r_sdp, SDP_OFFER);
sofia_glue_pass_sdp(tech_pvt, (char *) r_sdp); sofia_glue_pass_sdp(tech_pvt, (char *) r_sdp);
sofia_set_flag(tech_pvt, TFLAG_NEW_SDP); sofia_set_flag(tech_pvt, TFLAG_NEW_SDP);
@ -7680,7 +7680,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
} }
} else { } else {
if (sofia_media_tech_media(tech_pvt, (char *) r_sdp, SDP_TYPE_REQUEST) != SWITCH_STATUS_SUCCESS) { if (sofia_media_tech_media(tech_pvt, (char *) r_sdp, SDP_OFFER) != SWITCH_STATUS_SUCCESS) {
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR"); switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR");
nua_respond(nh, SIP_488_NOT_ACCEPTABLE, nua_respond(nh, SIP_488_NOT_ACCEPTABLE,
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),TAG_END()); TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),TAG_END());
@ -7776,7 +7776,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_FALSE); switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_FALSE);
if (tech_pvt->mparams.num_codecs) { if (tech_pvt->mparams.num_codecs) {
match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_REQUEST); match = sofia_media_negotiate_sdp(session, r_sdp, SDP_OFFER);
} }
if (!match) { if (!match) {
@ -7785,7 +7785,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),TAG_END()); TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),TAG_END());
} }
} else { } else {
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0); switch_core_media_gen_local_sdp(session, SDP_ANSWER, NULL, 0, NULL, 0);
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED"); switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED");
sofia_set_flag_locked(tech_pvt, TFLAG_READY); sofia_set_flag_locked(tech_pvt, TFLAG_READY);
@ -7909,7 +7909,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
uint8_t match = 0; uint8_t match = 0;
if (tech_pvt->mparams.num_codecs) { if (tech_pvt->mparams.num_codecs) {
match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_REQUEST); match = sofia_media_negotiate_sdp(session, r_sdp, SDP_OFFER);
} }
if (!match) { if (!match) {
@ -7992,10 +7992,11 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
switch_channel_hangup(channel, SWITCH_CAUSE_MANDATORY_IE_MISSING); switch_channel_hangup(channel, SWITCH_CAUSE_MANDATORY_IE_MISSING);
} else { } else {
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED_NOSDP"); switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED_NOSDP");
switch_channel_set_flag(channel, CF_3PCC);
switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0); switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0);
switch_core_media_prepare_codecs(session, 1); switch_core_media_prepare_codecs(session, 1);
switch_channel_set_state(channel, CS_HIBERNATE); switch_channel_set_state(channel, CS_HIBERNATE);
switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 0); switch_core_media_gen_local_sdp(session, SDP_OFFER, NULL, 0, NULL, 0);
sofia_set_flag_locked(tech_pvt, TFLAG_3PCC); sofia_set_flag_locked(tech_pvt, TFLAG_3PCC);
if (sofia_use_soa(tech_pvt)) { if (sofia_use_soa(tech_pvt)) {
@ -8067,10 +8068,10 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
switch_channel_set_flag(channel, CF_NOSDP_REINVITE); switch_channel_set_flag(channel, CF_NOSDP_REINVITE);
if (switch_channel_var_true(channel, "sip_unhold_nosdp")) { if (switch_channel_var_true(channel, "sip_unhold_nosdp")) {
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, "sendrecv", switch_core_media_gen_local_sdp(session, SDP_ANSWER, NULL, 0, "sendrecv",
zstr(tech_pvt->mparams.local_sdp_str) || !switch_channel_test_flag(channel, CF_PROXY_MODE)); zstr(tech_pvt->mparams.local_sdp_str) || !switch_channel_test_flag(channel, CF_PROXY_MODE));
} else { } else {
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, switch_core_media_gen_local_sdp(session, SDP_ANSWER, NULL, 0, NULL,
zstr(tech_pvt->mparams.local_sdp_str) || !switch_channel_test_flag(channel, CF_PROXY_MODE)); zstr(tech_pvt->mparams.local_sdp_str) || !switch_channel_test_flag(channel, CF_PROXY_MODE));
} }
@ -8116,13 +8117,13 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
sofia_set_flag(tech_pvt, TFLAG_SDP); sofia_set_flag(tech_pvt, TFLAG_SDP);
match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_RESPONSE); match = sofia_media_negotiate_sdp(session, r_sdp, SDP_ANSWER);
if (match) { if (match) {
if (switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0) != SWITCH_STATUS_SUCCESS) { if (switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0) != SWITCH_STATUS_SUCCESS) {
goto done; goto done;
} }
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0); switch_core_media_gen_local_sdp(session, SDP_ANSWER, NULL, 0, NULL, 0);
if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) { if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Early Media RTP Error!\n"); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Early Media RTP Error!\n");
@ -8191,7 +8192,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE); switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
if (sofia_media_tech_media(tech_pvt, r_sdp, SDP_TYPE_REQUEST) != SWITCH_STATUS_SUCCESS) { if (sofia_media_tech_media(tech_pvt, r_sdp, SDP_OFFER) != SWITCH_STATUS_SUCCESS) {
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR"); switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR");
switch_core_session_rwunlock(other_session); switch_core_session_rwunlock(other_session);
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
@ -8210,7 +8211,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
} }
} }
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 1); switch_core_media_gen_local_sdp(session, SDP_ANSWER, NULL, 0, NULL, 1);
if (sofia_use_soa(tech_pvt)) { if (sofia_use_soa(tech_pvt)) {
nua_respond(tech_pvt->nh, SIP_200_OK, nua_respond(tech_pvt->nh, SIP_200_OK,
@ -8320,7 +8321,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
switch_channel_set_flag(tech_pvt->channel, CF_REINVITE); switch_channel_set_flag(tech_pvt->channel, CF_REINVITE);
if (tech_pvt->mparams.num_codecs){ if (tech_pvt->mparams.num_codecs){
match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_REQUEST); match = sofia_media_negotiate_sdp(session, r_sdp, SDP_OFFER);
} }
if (!match) { if (!match) {
@ -8369,7 +8370,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0); switch_core_media_gen_local_sdp(session, SDP_ANSWER, NULL, 0, NULL, 0);
if (sofia_use_soa(tech_pvt)){ if (sofia_use_soa(tech_pvt)){
nua_respond(tech_pvt->nh, SIP_200_OK, nua_respond(tech_pvt->nh, SIP_200_OK,
SIPTAG_CONTACT_STR(tech_pvt->reply_contact), SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
@ -8419,7 +8420,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
switch_channel_set_flag(tech_pvt->channel, CF_REINVITE); switch_channel_set_flag(tech_pvt->channel, CF_REINVITE);
if (tech_pvt->mparams.num_codecs) { if (tech_pvt->mparams.num_codecs) {
match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_REQUEST); match = sofia_media_negotiate_sdp(session, r_sdp, SDP_OFFER);
} }
@ -8438,7 +8439,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
goto done; goto done;
} }
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0); switch_core_media_gen_local_sdp(session, SDP_ANSWER, NULL, 0, NULL, 0);
if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) { if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Reinvite RTP Error!\n"); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Reinvite RTP Error!\n");
@ -8462,7 +8463,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
if (is_ok) { if (is_ok) {
if (switch_core_session_local_crypto_key(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO)) { if (switch_core_session_local_crypto_key(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO)) {
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0); switch_core_media_gen_local_sdp(session, SDP_ANSWER, NULL, 0, NULL, 0);
} }
if (!switch_channel_test_flag(tech_pvt->channel, CF_AWAITING_STREAM_CHANGE)) { if (!switch_channel_test_flag(tech_pvt->channel, CF_AWAITING_STREAM_CHANGE)) {
@ -8507,13 +8508,13 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
if (tech_pvt->mparams.num_codecs) { if (tech_pvt->mparams.num_codecs) {
match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_RESPONSE); match = sofia_media_negotiate_sdp(session, r_sdp, SDP_ANSWER);
} }
if (match) { if (match) {
if (switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0) != SWITCH_STATUS_SUCCESS) { if (switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0) != SWITCH_STATUS_SUCCESS) {
goto done; goto done;
} }
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0); switch_core_media_gen_local_sdp(session, SDP_ANSWER, NULL, 0, NULL, 0);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Processing updated SDP\n"); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Processing updated SDP\n");
switch_channel_set_flag(tech_pvt->channel, CF_REINVITE); switch_channel_set_flag(tech_pvt->channel, CF_REINVITE);
@ -8571,9 +8572,9 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
if (tech_pvt->mparams.num_codecs) { if (tech_pvt->mparams.num_codecs) {
if (sofia_test_flag(tech_pvt, TFLAG_GOT_ACK)) { if (sofia_test_flag(tech_pvt, TFLAG_GOT_ACK)) {
match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_REQUEST); match = sofia_media_negotiate_sdp(session, r_sdp, SDP_OFFER);
} else { } else {
match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_RESPONSE); match = sofia_media_negotiate_sdp(session, r_sdp, SDP_ANSWER);
} }
} }
@ -8668,7 +8669,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
uint8_t match = 0; uint8_t match = 0;
match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_RESPONSE); match = sofia_media_negotiate_sdp(session, r_sdp, SDP_ANSWER);
sofia_set_flag_locked(tech_pvt, TFLAG_ANS); sofia_set_flag_locked(tech_pvt, TFLAG_ANS);
@ -10466,7 +10467,7 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia
if (r_sdp) { if (r_sdp) {
switch_core_media_set_sdp_codec_string(session, r_sdp, SDP_TYPE_REQUEST); switch_core_media_set_sdp_codec_string(session, r_sdp, SDP_OFFER);
} }

View File

@ -1158,7 +1158,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
} }
if (!switch_channel_get_private(tech_pvt->channel, "t38_options") || zstr(tech_pvt->mparams.local_sdp_str)) { if (!switch_channel_get_private(tech_pvt->channel, "t38_options") || zstr(tech_pvt->mparams.local_sdp_str)) {
switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 0); switch_core_media_gen_local_sdp(session, SDP_OFFER, NULL, 0, NULL, 0);
} }
sofia_set_flag_locked(tech_pvt, TFLAG_READY); sofia_set_flag_locked(tech_pvt, TFLAG_READY);

View File

@ -2112,12 +2112,12 @@ static int sofia_dialog_probe_callback(void *pArg, int argc, char **argv, char *
#define SOFIA_PRESENCE_COLLISION_DELTA 50 #define SOFIA_PRESENCE_COLLISION_DELTA 50
#define SOFIA_PRESENCE_ROLLOVER_YEAR (86400 * 365 * SOFIA_PRESENCE_COLLISION_DELTA) #define SOFIA_PRESENCE_ROLLOVER_YEAR (86400 * 365 * SOFIA_PRESENCE_COLLISION_DELTA)
static uint32_t check_presence_epoch(void) static switch_uint31_t check_presence_epoch(void)
{ {
time_t now = switch_epoch_time_now(NULL); time_t now = switch_epoch_time_now(NULL);
uint32_t callsequence = (uint32_t)((now - mod_sofia_globals.presence_epoch) * SOFIA_PRESENCE_COLLISION_DELTA); switch_uint31_t callsequence = { .value = (uint32_t)((now - mod_sofia_globals.presence_epoch) * SOFIA_PRESENCE_COLLISION_DELTA) };
if (!mod_sofia_globals.presence_year || callsequence >= SOFIA_PRESENCE_ROLLOVER_YEAR) { if (!mod_sofia_globals.presence_year || callsequence.value >= SOFIA_PRESENCE_ROLLOVER_YEAR) {
struct tm tm; struct tm tm;
switch_mutex_lock(mod_sofia_globals.mutex); switch_mutex_lock(mod_sofia_globals.mutex);
tm = *(localtime(&now)); tm = *(localtime(&now));
@ -2125,7 +2125,7 @@ static uint32_t check_presence_epoch(void)
if (tm.tm_year != mod_sofia_globals.presence_year) { if (tm.tm_year != mod_sofia_globals.presence_year) {
mod_sofia_globals.presence_epoch = (uint32_t)now - (tm.tm_yday * 86400) - (tm.tm_hour * 60 * 60) - (tm.tm_min * 60) - tm.tm_sec; mod_sofia_globals.presence_epoch = (uint32_t)now - (tm.tm_yday * 86400) - (tm.tm_hour * 60 * 60) - (tm.tm_min * 60) - tm.tm_sec;
mod_sofia_globals.presence_year = tm.tm_year; mod_sofia_globals.presence_year = tm.tm_year;
callsequence = (uint32_t)(((uint32_t)now - mod_sofia_globals.presence_epoch) * SOFIA_PRESENCE_COLLISION_DELTA); callsequence.value = (uint32_t)(((uint32_t)now - mod_sofia_globals.presence_epoch) * SOFIA_PRESENCE_COLLISION_DELTA);
} }
switch_mutex_unlock(mod_sofia_globals.mutex); switch_mutex_unlock(mod_sofia_globals.mutex);
@ -2136,17 +2136,17 @@ static uint32_t check_presence_epoch(void)
uint32_t sofia_presence_get_cseq(sofia_profile_t *profile) uint32_t sofia_presence_get_cseq(sofia_profile_t *profile)
{ {
uint32_t callsequence; switch_uint31_t callsequence;
int diff = 0; int diff = 0;
switch_mutex_lock(profile->ireg_mutex); switch_mutex_lock(profile->ireg_mutex);
callsequence = check_presence_epoch(); callsequence = check_presence_epoch();
if (profile->last_cseq) { if (profile->last_cseq.value) {
diff = callsequence - profile->last_cseq; diff = (int)callsequence.value - (int)profile->last_cseq.value;
if (diff <= 0 && diff > -100000) { if (diff <= 0 && diff > -100000) {
callsequence = ++profile->last_cseq; callsequence.value = ++profile->last_cseq.value;
} }
} }
@ -2154,8 +2154,7 @@ uint32_t sofia_presence_get_cseq(sofia_profile_t *profile)
switch_mutex_unlock(profile->ireg_mutex); switch_mutex_unlock(profile->ireg_mutex);
return callsequence; return (uint32_t)callsequence.value;
} }

View File

@ -1320,7 +1320,7 @@ static void tech_reattach(verto_pvt_t *tech_pvt, jsock_t *jsock)
switch_channel_set_flag(tech_pvt->channel, CF_REATTACHED); switch_channel_set_flag(tech_pvt->channel, CF_REATTACHED);
switch_channel_set_flag(tech_pvt->channel, CF_REINVITE); switch_channel_set_flag(tech_pvt->channel, CF_REINVITE);
switch_channel_set_flag(tech_pvt->channel, CF_RECOVERING); switch_channel_set_flag(tech_pvt->channel, CF_RECOVERING);
switch_core_media_gen_local_sdp(tech_pvt->session, SDP_TYPE_REQUEST, NULL, 0, NULL, 0); switch_core_media_gen_local_sdp(tech_pvt->session, SDP_OFFER, NULL, 0, NULL, 0);
switch_channel_clear_flag(tech_pvt->channel, CF_REINVITE); switch_channel_clear_flag(tech_pvt->channel, CF_REINVITE);
switch_channel_clear_flag(tech_pvt->channel, CF_RECOVERING); switch_channel_clear_flag(tech_pvt->channel, CF_RECOVERING);
switch_core_session_request_video_refresh(tech_pvt->session); switch_core_session_request_video_refresh(tech_pvt->session);
@ -2405,7 +2405,7 @@ static switch_status_t verto_connect(switch_core_session_t *session, const char
} }
} }
switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 0); switch_core_media_gen_local_sdp(session, SDP_OFFER, NULL, 0, NULL, 0);
} }
msg = jrpc_new_req(method, tech_pvt->call_id, &params); msg = jrpc_new_req(method, tech_pvt->call_id, &params);
@ -2641,7 +2641,7 @@ static switch_status_t verto_media(switch_core_session_t *session)
switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE); switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
if (tech_pvt->r_sdp) { if (tech_pvt->r_sdp) {
if (verto_tech_media(tech_pvt, tech_pvt->r_sdp, SDP_TYPE_REQUEST) != SWITCH_STATUS_SUCCESS) { if (verto_tech_media(tech_pvt, tech_pvt->r_sdp, SDP_OFFER) != SWITCH_STATUS_SUCCESS) {
switch_channel_set_variable(tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR"); switch_channel_set_variable(tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR");
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
@ -2653,7 +2653,7 @@ static switch_status_t verto_media(switch_core_session_t *session)
return status; return status;
} }
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0); switch_core_media_gen_local_sdp(session, SDP_ANSWER, NULL, 0, NULL, 0);
if (switch_core_media_activate_rtp(tech_pvt->session) != SWITCH_STATUS_SUCCESS) { if (switch_core_media_activate_rtp(tech_pvt->session) != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
@ -2963,7 +2963,7 @@ static switch_bool_t verto__answer_func(const char *method, cJSON *params, jsock
switch_channel_set_variable(tech_pvt->channel, SWITCH_R_SDP_VARIABLE, sdp); switch_channel_set_variable(tech_pvt->channel, SWITCH_R_SDP_VARIABLE, sdp);
switch_channel_set_variable(tech_pvt->channel, "verto_client_address", jsock->name); switch_channel_set_variable(tech_pvt->channel, "verto_client_address", jsock->name);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote SDP %s:\n%s\n", switch_channel_get_name(tech_pvt->channel), sdp); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote SDP %s:\n%s\n", switch_channel_get_name(tech_pvt->channel), sdp);
switch_core_media_set_sdp_codec_string(session, sdp, SDP_TYPE_RESPONSE); switch_core_media_set_sdp_codec_string(session, sdp, SDP_ANSWER);
if (!switch_channel_var_true(switch_core_session_get_channel(session),"verto_skip_set_user")) { if (!switch_channel_var_true(switch_core_session_get_channel(session),"verto_skip_set_user")) {
switch_ivr_set_user(session, jsock->uid); switch_ivr_set_user(session, jsock->uid);
@ -2978,7 +2978,7 @@ static switch_bool_t verto__answer_func(const char *method, cJSON *params, jsock
if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE)) { if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE)) {
pass_sdp(tech_pvt); pass_sdp(tech_pvt);
} else { } else {
if (verto_tech_media(tech_pvt, tech_pvt->r_sdp, SDP_TYPE_RESPONSE) != SWITCH_STATUS_SUCCESS) { if (verto_tech_media(tech_pvt, tech_pvt->r_sdp, SDP_ANSWER) != SWITCH_STATUS_SUCCESS) {
switch_channel_set_variable(tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR"); switch_channel_set_variable(tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR");
cJSON_AddItemToObject(obj, "message", cJSON_CreateString("CODEC ERROR")); cJSON_AddItemToObject(obj, "message", cJSON_CreateString("CODEC ERROR"));
err = 1; err = 1;
@ -3448,8 +3448,8 @@ static switch_bool_t verto__modify_func(const char *method, cJSON *params, jsock
//switch_channel_set_flag(tech_pvt->channel, CF_VIDEO_BREAK); //switch_channel_set_flag(tech_pvt->channel, CF_VIDEO_BREAK);
//switch_core_session_kill_channel(tech_pvt->session, SWITCH_SIG_BREAK); //switch_core_session_kill_channel(tech_pvt->session, SWITCH_SIG_BREAK);
if (switch_core_media_negotiate_sdp(tech_pvt->session, tech_pvt->r_sdp, &p, SDP_TYPE_REQUEST)) { if (switch_core_media_negotiate_sdp(tech_pvt->session, tech_pvt->r_sdp, &p, SDP_OFFER)) {
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0); switch_core_media_gen_local_sdp(session, SDP_ANSWER, NULL, 0, NULL, 0);
if (switch_core_media_activate_rtp(tech_pvt->session) != SWITCH_STATUS_SUCCESS) { if (switch_core_media_activate_rtp(tech_pvt->session) != SWITCH_STATUS_SUCCESS) {
switch_channel_set_variable(tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "MEDIA ERROR"); switch_channel_set_variable(tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "MEDIA ERROR");
@ -3606,8 +3606,8 @@ static switch_bool_t verto__attach_func(const char *method, cJSON *params, jsock
//switch_channel_set_flag(tech_pvt->channel, CF_VIDEO_BREAK); //switch_channel_set_flag(tech_pvt->channel, CF_VIDEO_BREAK);
//switch_core_session_kill_channel(tech_pvt->session, SWITCH_SIG_BREAK); //switch_core_session_kill_channel(tech_pvt->session, SWITCH_SIG_BREAK);
if (switch_core_media_negotiate_sdp(tech_pvt->session, tech_pvt->r_sdp, &p, SDP_TYPE_RESPONSE)) { if (switch_core_media_negotiate_sdp(tech_pvt->session, tech_pvt->r_sdp, &p, SDP_ANSWER)) {
//switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0); //switch_core_media_gen_local_sdp(session, SDP_ANSWER, NULL, 0, NULL, 0);
if (switch_core_media_activate_rtp(tech_pvt->session) != SWITCH_STATUS_SUCCESS) { if (switch_core_media_activate_rtp(tech_pvt->session) != SWITCH_STATUS_SUCCESS) {
switch_channel_set_variable(tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "MEDIA ERROR"); switch_channel_set_variable(tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "MEDIA ERROR");
@ -4020,7 +4020,7 @@ static switch_bool_t verto__invite_func(const char *method, cJSON *params, jsock
tech_pvt->channel = channel; tech_pvt->channel = channel;
tech_pvt->jsock_uuid = switch_core_session_strdup(session, jsock->uuid_str); tech_pvt->jsock_uuid = switch_core_session_strdup(session, jsock->uuid_str);
tech_pvt->r_sdp = switch_core_session_strdup(session, sdp); tech_pvt->r_sdp = switch_core_session_strdup(session, sdp);
switch_core_media_set_sdp_codec_string(session, sdp, SDP_TYPE_REQUEST); switch_core_media_set_sdp_codec_string(session, sdp, SDP_OFFER);
switch_core_session_set_private_class(session, tech_pvt, SWITCH_PVT_SECONDARY); switch_core_session_set_private_class(session, tech_pvt, SWITCH_PVT_SECONDARY);
tech_pvt->call_id = switch_core_session_strdup(session, call_id); tech_pvt->call_id = switch_core_session_strdup(session, call_id);

View File

@ -231,7 +231,7 @@ static void mod_amqp_command_response(mod_amqp_command_profile_t *profile, char
} }
/* Construct the api response */ /* Construct the api response */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Preparing api command response: [%s]\n", (char *)stream.data); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Preparing api command response: [%s]\n", (char *)stream.data);
message = cJSON_CreateObject(); message = cJSON_CreateObject();
cJSON_AddItemToObject(message, "output", cJSON_CreateString((const char *) stream.data)); cJSON_AddItemToObject(message, "output", cJSON_CreateString((const char *) stream.data));

View File

@ -173,7 +173,7 @@ static switch_status_t socket_logger(const switch_log_node_t *node, switch_log_l
switch_status_t qstatus; switch_status_t qstatus;
switch_mutex_lock(globals.listener_mutex); switch_mutex_lock(globals.listener_mutex);
for (l = listen_list.listeners; l; l = l->next) { for (l = listen_list.listeners; l; l = l->next) {
if (switch_test_flag(l, LFLAG_LOG) && l->level >= node->level) { if (switch_test_flag(l, LFLAG_LOG) && l->level >= node->level && switch_test_flag(l, LFLAG_RUNNING)) {
switch_log_node_t *dnode = switch_log_node_dup(node); switch_log_node_t *dnode = switch_log_node_dup(node);
qstatus = switch_queue_trypush(l->log_queue, dnode); qstatus = switch_queue_trypush(l->log_queue, dnode);
if (qstatus == SWITCH_STATUS_SUCCESS) { if (qstatus == SWITCH_STATUS_SUCCESS) {
@ -302,7 +302,7 @@ static void event_handler(switch_event_t *event)
} }
} }
if (l->expire_time || !switch_test_flag(l, LFLAG_EVENTS)) { if (l->expire_time || !switch_test_flag(l, LFLAG_EVENTS) || !switch_test_flag(l, LFLAG_RUNNING)) {
last = l; last = l;
continue; continue;
} }

View File

@ -1,37 +0,0 @@
include $(top_srcdir)/build/modmake.rulesam
MODNAME=mod_kazoo
if HAVE_ERLANG
KAZOO_DEFS=kazoo_definitions.o
mod_LTLIBRARIES = mod_kazoo.la
mod_kazoo_la_SOURCES = mod_kazoo.c kazoo_utils.c kazoo_dptools.c kazoo_tweaks.c
mod_kazoo_la_SOURCES += kazoo_api.c kazoo_commands.c kazoo_config.c
mod_kazoo_la_SOURCES += kazoo_message.c
mod_kazoo_la_SOURCES += kazoo_ei_config.c kazoo_ei_utils.c kazoo_event_stream.c
mod_kazoo_la_SOURCES += kazoo_fetch_agent.c kazoo_node.c
mod_kazoo_la_SOURCES += kazoo_endpoints.c
mod_kazoo_la_SOURCES += kazoo_cdr.c
mod_kazoo_la_SOURCES += kz_node.c
mod_kazoo_la_CFLAGS = $(AM_CFLAGS) @ERLANG_CFLAGS@ -D_REENTRANT -DERLANG_VERSION=@ERLANG_VERSION@ -DERLANG_MAJOR=@ERLANG_MAJOR@ -DERLANG_MINOR=@ERLANG_MINOR@
mod_kazoo_la_LIBADD = $(KAZOO_DEFS) $(switch_builddir)/libfreeswitch.la
mod_kazoo_la_LDFLAGS = -avoid-version -module -no-undefined -shared @ERLANG_LDFLAGS@
BUILT_SOURCES = $(KAZOO_DEFS)
$(KAZOO_DEFS): kazoo.conf.xml
.S.o: $<
@$(CC) $(CFLAGS) -o $@ -c $<
install-exec-am:
@install `which epmd` $(DESTDIR)$(bindir)/fs_epmd
else
install: error
all: error
error:
$(error You must install erlang to build this module)
endif

File diff suppressed because it is too large Load Diff

View File

@ -1,573 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Karl Anderson <karl@2600hz.com>
* Darren Schreiber <darren@2600hz.com>
*
*
* mod_kazoo.c -- Socket Controlled Event Handler
*
*/
#include "mod_kazoo.h"
#define KAZOO_DESC "kazoo information"
#define KAZOO_SYNTAX "<command> [<args>]"
#define API_COMMAND_DISCONNECT 0
#define API_COMMAND_REMOTE_IP 1
#define API_COMMAND_STREAMS 2
#define API_COMMAND_BINDINGS 3
#define API_COMMAND_OPTION 4
#define API_NODE_OPTION_FRAMING 0
#define API_NODE_OPTION_KEEPALIVE 1
#define API_NODE_OPTION_LEGACY 2
#define API_NODE_OPTION_MAX 99
static const char *node_runtime_options[] = {
"event-stream-framing",
"event-stream-keepalive",
"enable-legacy",
NULL
};
static int api_find_node_option(char *option) {
int i;
for(i = 0; node_runtime_options[i] != NULL; i++) {
if(!strcasecmp(option, node_runtime_options[i])) {
return i;
}
}
return API_NODE_OPTION_MAX;
}
static switch_status_t api_get_node_option(ei_node_t *ei_node, switch_stream_handle_t *stream, char *arg) {
int option = api_find_node_option(arg);
switch_status_t ret = SWITCH_STATUS_SUCCESS;
switch (option) {
case API_NODE_OPTION_FRAMING:
stream->write_function(stream, "+OK %i", ei_node->event_stream_framing);
break;
case API_NODE_OPTION_KEEPALIVE:
stream->write_function(stream, "+OK %i", ei_node->event_stream_keepalive);
break;
case API_NODE_OPTION_LEGACY:
stream->write_function(stream, "+OK %s", ei_node->legacy ? "true" : "false");
break;
default:
stream->write_function(stream, "-ERR invalid option %s", arg);
ret = SWITCH_STATUS_NOTFOUND;
break;
}
return ret;
}
static switch_status_t api_set_node_option(ei_node_t *ei_node, switch_stream_handle_t *stream, char *name, char *value) {
int option = api_find_node_option(name);
short val;
switch_status_t ret = SWITCH_STATUS_SUCCESS;
switch (option) {
case API_NODE_OPTION_FRAMING:
val = atoi(value);
if (val != 1 && val != 2 && val != 4) {
stream->write_function(stream, "-ERR Invalid event stream framing value (%i)", val);
ret = SWITCH_STATUS_GENERR;
} else {
stream->write_function(stream, "+OK %i", val);
ei_node->event_stream_framing = val;
}
break;
case API_NODE_OPTION_KEEPALIVE:
val = switch_true(value);
stream->write_function(stream, "+OK %i", val);
ei_node->event_stream_keepalive = val;
break;
case API_NODE_OPTION_LEGACY:
ei_node->legacy = switch_true(value);
stream->write_function(stream, "+OK %s", ei_node->legacy ? "true" : "false");
break;
default:
stream->write_function(stream, "-ERR invalid option %s", name);
ret = SWITCH_STATUS_NOTFOUND;
break;
}
return ret;
}
static switch_status_t api_erlang_status(switch_stream_handle_t *stream) {
switch_sockaddr_t *sa;
uint16_t port;
char ipbuf[48];
const char *ip_addr;
ei_node_t *ei_node;
switch_socket_addr_get(&sa, SWITCH_FALSE, kazoo_globals.acceptor);
port = switch_sockaddr_get_port(sa);
ip_addr = switch_get_addr(ipbuf, sizeof (ipbuf), sa);
stream->write_function(stream, "Running %s\n", VERSION);
stream->write_function(stream, "Listening for new Erlang connections on %s:%u with cookie %s\n", ip_addr, port, kazoo_globals.ei_cookie);
stream->write_function(stream, "Registered as Erlang node %s, visible as %s\n", kazoo_globals.ei_cnode.thisnodename, kazoo_globals.ei_cnode.thisalivename);
if (kazoo_globals.ei_compat_rel) {
stream->write_function(stream, "Using Erlang compatibility mode: %d\n", kazoo_globals.ei_compat_rel);
}
switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock);
ei_node = kazoo_globals.ei_nodes;
if (!ei_node) {
stream->write_function(stream, "No erlang nodes connected\n");
} else {
stream->write_function(stream, "Connected to:\n");
while(ei_node != NULL) {
unsigned int year, day, hour, min, sec, delta;
delta = (switch_micro_time_now() - ei_node->created_time) / 1000000;
sec = delta % 60;
min = delta / 60 % 60;
hour = delta / 3600 % 24;
day = delta / 86400 % 7;
year = delta / 31556926 % 12;
stream->write_function(stream, " %s (%s:%d) up %d years, %d days, %d hours, %d minutes, %d seconds\n"
,ei_node->peer_nodename, ei_node->remote_ip, ei_node->remote_port, year, day, hour, min, sec);
ei_node = ei_node->next;
}
}
switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t api_erlang_event_filter(switch_stream_handle_t *stream) {
switch_hash_index_t *hi = NULL;
int column = 0;
int idx = 0;
for (hi = (switch_hash_index_t *)switch_core_hash_first_iter(kazoo_globals.event_filter, hi); hi; hi = switch_core_hash_next(&hi)) {
const void *key;
void *val;
switch_core_hash_this(hi, &key, NULL, &val);
stream->write_function(stream, "%-50s", (char *)key);
if (++column > 2) {
stream->write_function(stream, "\n");
column = 0;
}
}
if (++column > 2) {
stream->write_function(stream, "\n");
}
while(kazoo_globals.kazoo_var_prefixes[idx] != NULL) {
char var[100];
char *prefix = kazoo_globals.kazoo_var_prefixes[idx];
sprintf(var, "%s*", prefix);
stream->write_function(stream, "%-50s", var);
idx++;
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t api_erlang_nodes_list(switch_stream_handle_t *stream) {
ei_node_t *ei_node;
switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock);
ei_node = kazoo_globals.ei_nodes;
while(ei_node != NULL) {
stream->write_function(stream, "%s (%s)\n", ei_node->peer_nodename, ei_node->remote_ip);
ei_node = ei_node->next;
}
switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t api_erlang_nodes_count(switch_stream_handle_t *stream) {
ei_node_t *ei_node;
int count = 0;
switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock);
ei_node = kazoo_globals.ei_nodes;
while(ei_node != NULL) {
count++;
ei_node = ei_node->next;
}
switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
stream->write_function(stream, "%d\n", count);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t api_complete_erlang_node(const char *line, const char *cursor, switch_console_callback_match_t **matches) {
switch_console_callback_match_t *my_matches = NULL;
switch_status_t status = SWITCH_STATUS_FALSE;
ei_node_t *ei_node;
switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock);
ei_node = kazoo_globals.ei_nodes;
while(ei_node != NULL) {
switch_console_push_match(&my_matches, ei_node->peer_nodename);
ei_node = ei_node->next;
}
switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
if (my_matches) {
*matches = my_matches;
status = SWITCH_STATUS_SUCCESS;
}
return status;
}
static switch_status_t handle_node_api_event_stream(ei_event_stream_t *event_stream, switch_stream_handle_t *stream) {
ei_event_binding_t *binding;
int column = 0;
switch_mutex_lock(event_stream->socket_mutex);
if (event_stream->connected == SWITCH_FALSE) {
switch_sockaddr_t *sa;
uint16_t port;
char ipbuf[48] = {0};
const char *ip_addr;
switch_socket_addr_get(&sa, SWITCH_TRUE, event_stream->acceptor);
port = switch_sockaddr_get_port(sa);
ip_addr = switch_get_addr(ipbuf, sizeof (ipbuf), sa);
if (zstr(ip_addr)) {
ip_addr = kazoo_globals.ip;
}
stream->write_function(stream, "%s:%d -> disconnected\n"
,ip_addr, port);
} else {
unsigned int year, day, hour, min, sec, delta;
delta = (switch_micro_time_now() - event_stream->connected_time) / 1000000;
sec = delta % 60;
min = delta / 60 % 60;
hour = delta / 3600 % 24;
day = delta / 86400 % 7;
year = delta / 31556926 % 12;
stream->write_function(stream, "%s:%d -> %s:%d for %d years, %d days, %d hours, %d minutes, %d seconds\n"
,event_stream->local_ip, event_stream->local_port
,event_stream->remote_ip, event_stream->remote_port
,year, day, hour, min, sec);
}
binding = event_stream->bindings;
while(binding != NULL) {
if (binding->type == SWITCH_EVENT_CUSTOM) {
stream->write_function(stream, "CUSTOM %-43s", binding->subclass_name);
} else {
stream->write_function(stream, "%-50s", switch_event_name(binding->type));
}
if (++column > 2) {
stream->write_function(stream, "\n");
column = 0;
}
binding = binding->next;
}
switch_mutex_unlock(event_stream->socket_mutex);
if (!column) {
stream->write_function(stream, "\n");
} else {
stream->write_function(stream, "\n\n");
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t handle_node_api_event_streams(ei_node_t *ei_node, switch_stream_handle_t *stream) {
ei_event_stream_t *event_stream;
switch_mutex_lock(ei_node->event_streams_mutex);
event_stream = ei_node->event_streams;
while(event_stream != NULL) {
handle_node_api_event_stream(event_stream, stream);
event_stream = event_stream->next;
}
switch_mutex_unlock(ei_node->event_streams_mutex);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t handle_node_api_command(ei_node_t *ei_node, switch_stream_handle_t *stream, uint32_t command) {
unsigned int year, day, hour, min, sec, delta;
switch (command) {
case API_COMMAND_DISCONNECT:
stream->write_function(stream, "Disconnecting erlang node %s at managers request\n", ei_node->peer_nodename);
switch_clear_flag(ei_node, LFLAG_RUNNING);
break;
case API_COMMAND_REMOTE_IP:
delta = (switch_micro_time_now() - ei_node->created_time) / 1000000;
sec = delta % 60;
min = delta / 60 % 60;
hour = delta / 3600 % 24;
day = delta / 86400 % 7;
year = delta / 31556926 % 12;
stream->write_function(stream, "Uptime %d years, %d days, %d hours, %d minutes, %d seconds\n", year, day, hour, min, sec);
stream->write_function(stream, "Local Address %s:%d\n", ei_node->local_ip, ei_node->local_port);
stream->write_function(stream, "Remote Address %s:%d\n", ei_node->remote_ip, ei_node->remote_port);
break;
case API_COMMAND_STREAMS:
handle_node_api_event_streams(ei_node, stream);
break;
case API_COMMAND_BINDINGS:
handle_api_command_streams(ei_node, stream);
break;
default:
break;
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t api_erlang_node_command(switch_stream_handle_t *stream, const char *nodename, uint32_t command) {
ei_node_t *ei_node;
switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock);
ei_node = kazoo_globals.ei_nodes;
while(ei_node != NULL) {
int length = strlen(ei_node->peer_nodename);
if (!strncmp(ei_node->peer_nodename, nodename, length)) {
handle_node_api_command(ei_node, stream, command);
switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
return SWITCH_STATUS_SUCCESS;
}
ei_node = ei_node->next;
}
switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
return SWITCH_STATUS_NOTFOUND;
}
static switch_status_t handle_node_api_command_arg(ei_node_t *ei_node, switch_stream_handle_t *stream, uint32_t command, char *arg) {
switch (command) {
case API_COMMAND_OPTION:
return api_get_node_option(ei_node, stream, arg);
break;
default:
break;
}
return SWITCH_STATUS_NOTFOUND;
}
static switch_status_t handle_node_api_command_args(ei_node_t *ei_node, switch_stream_handle_t *stream, uint32_t command, int argc, char *argv[]) {
switch (command) {
case API_COMMAND_OPTION:
return api_set_node_option(ei_node, stream, argv[0], argv[1]);
break;
default:
break;
}
return SWITCH_STATUS_NOTFOUND;
}
static switch_status_t api_erlang_node_command_arg(switch_stream_handle_t *stream, const char *nodename, uint32_t command, char *arg) {
ei_node_t *ei_node;
switch_status_t ret = SWITCH_STATUS_NOTFOUND;
switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock);
ei_node = kazoo_globals.ei_nodes;
while(ei_node != NULL) {
int length = strlen(ei_node->peer_nodename);
if (!strncmp(ei_node->peer_nodename, nodename, length)) {
ret = handle_node_api_command_arg(ei_node, stream, command, arg);
switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
return ret ;
}
ei_node = ei_node->next;
}
switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
return ret;
}
static switch_status_t api_erlang_node_command_args(switch_stream_handle_t *stream, const char *nodename, uint32_t command, int argc, char *argv[]) {
ei_node_t *ei_node;
switch_status_t ret = SWITCH_STATUS_NOTFOUND;
switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock);
ei_node = kazoo_globals.ei_nodes;
while(ei_node != NULL) {
int length = strlen(ei_node->peer_nodename);
if (!strncmp(ei_node->peer_nodename, nodename, length)) {
ret = handle_node_api_command_args(ei_node, stream, command, argc, argv);
switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
return ret;
}
ei_node = ei_node->next;
}
switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
return ret;
}
SWITCH_STANDARD_API(exec_api_cmd)
{
char *argv[1024] = { 0 };
int unknown_command = 1, argc = 0;
char *mycmd = NULL;
const char *usage_string = "USAGE:\n"
"--------------------------------------------------------------------------------------------------------------------\n"
"erlang status - provides an overview of the current status\n"
"erlang event_filter - lists the event headers that will be sent to Erlang nodes\n"
"erlang nodes list - lists connected Erlang nodes (usefull for monitoring tools)\n"
"erlang nodes count - provides a count of connected Erlang nodes (usefull for monitoring tools)\n"
"erlang node <node_name> disconnect - disconnects an Erlang node\n"
"erlang node <node_name> connection - Shows the connection info\n"
"erlang node <node_name> event_streams - lists the event streams for an Erlang node\n"
"erlang node <node_name> fetch_bindings - lists the XML fetch bindings for an Erlang node\n"
"---------------------------------------------------------------------------------------------------------------------\n";
if (zstr(cmd)) {
stream->write_function(stream, "%s", usage_string);
return SWITCH_STATUS_SUCCESS;
}
if (!(mycmd = strdup(cmd))) {
return SWITCH_STATUS_MEMERR;
}
if (!(argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
stream->write_function(stream, "%s", usage_string);
switch_safe_free(mycmd);
return SWITCH_STATUS_SUCCESS;
}
if (zstr(argv[0])) {
stream->write_function(stream, "%s", usage_string);
switch_safe_free(mycmd);
return SWITCH_STATUS_SUCCESS;
}
if (!strncmp(argv[0], "status", 7)) {
unknown_command = 0;
api_erlang_status(stream);
} else if (!strncmp(argv[0], "event_filter", 13)) {
unknown_command = 0;
api_erlang_event_filter(stream);
} else if (!strncmp(argv[0], "nodes", 6) && !zstr(argv[1])) {
if (!strncmp(argv[1], "list", 6)) {
unknown_command = 0;
api_erlang_nodes_list(stream);
} else if (!strncmp(argv[1], "count", 6)) {
unknown_command = 0;
api_erlang_nodes_count(stream);
}
} else if (!strncmp(argv[0], "node", 6) && !zstr(argv[1]) && !zstr(argv[2])) {
if (!strncmp(argv[2], "disconnect", 11)) {
unknown_command = 0;
api_erlang_node_command(stream, argv[1], API_COMMAND_DISCONNECT);
} else if (!strncmp(argv[2], "connection", 11)) {
unknown_command = 0;
api_erlang_node_command(stream, argv[1], API_COMMAND_REMOTE_IP);
} else if (!strncmp(argv[2], "event_streams", 14)) {
unknown_command = 0;
api_erlang_node_command(stream, argv[1], API_COMMAND_STREAMS);
} else if (!strncmp(argv[2], "fetch_bindings", 15)) {
unknown_command = 0;
api_erlang_node_command(stream, argv[1], API_COMMAND_BINDINGS);
} else if (!strncmp(argv[2], "option", 7) && !zstr(argv[3])) {
unknown_command = 0;
if(argc > 4 && !zstr(argv[4]))
api_erlang_node_command_args(stream, argv[1], API_COMMAND_OPTION, argc - 3, &argv[3]);
else
api_erlang_node_command_arg(stream, argv[1], API_COMMAND_OPTION, argv[3]);
}
}
if (unknown_command) {
stream->write_function(stream, "%s", usage_string);
}
switch_safe_free(mycmd);
return SWITCH_STATUS_SUCCESS;
}
void add_cli_api(switch_loadable_module_interface_t **module_interface)
{
switch_api_interface_t *api_interface = NULL;
SWITCH_ADD_API(api_interface, "erlang", KAZOO_DESC, exec_api_cmd, KAZOO_SYNTAX);
switch_console_set_complete("add erlang status");
switch_console_set_complete("add erlang event_filter");
switch_console_set_complete("add erlang nodes list");
switch_console_set_complete("add erlang nodes count");
switch_console_set_complete("add erlang node ::erlang::node disconnect");
switch_console_set_complete("add erlang node ::erlang::node connection");
switch_console_set_complete("add erlang node ::erlang::node event_streams");
switch_console_set_complete("add erlang node ::erlang::node fetch_bindings");
switch_console_add_complete_func("::erlang::node", api_complete_erlang_node);
}
void remove_cli_api()
{
switch_console_set_complete("del erlang");
switch_console_del_complete_func("::erlang::node");
}
/* 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:
*/

View File

@ -1,630 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Luis Azedo <luis@2600hz.com>
*
* mod_hacks.c -- hacks with state handlers
*
*/
#include "mod_kazoo.h"
#define MY_EVENT_JSON_CDR "KZ_CDR"
#define maybe_add_json_string(_json, _name, _string) \
if (!zstr(_string)) cJSON_AddItemToObject(_json, _name, cJSON_CreateString((char *)_string))
static void kz_switch_ivr_set_json_profile_data(cJSON *json, switch_caller_profile_t *caller_profile)
{
cJSON *soft = NULL;
profile_node_t *pn = NULL;
maybe_add_json_string(json, "Username", caller_profile->username);
maybe_add_json_string(json, "Dialplan", caller_profile->dialplan);
maybe_add_json_string(json, "ANI", caller_profile->ani);
maybe_add_json_string(json, "ANIII", caller_profile->aniii);
maybe_add_json_string(json, "Caller-ID-Name", caller_profile->caller_id_name);
maybe_add_json_string(json, "Caller-ID-Number", caller_profile->caller_id_number);
maybe_add_json_string(json, "Caller-ID-Original-Name", caller_profile->orig_caller_id_name);
maybe_add_json_string(json, "Caller-ID-Original-Number", caller_profile->orig_caller_id_number);
maybe_add_json_string(json, "Network-Address", caller_profile->network_addr);
maybe_add_json_string(json, "RDNIS", caller_profile->rdnis);
maybe_add_json_string(json, "Destination-Number", caller_profile->destination_number);
maybe_add_json_string(json, "Callee-ID-Name", caller_profile->callee_id_name);
maybe_add_json_string(json, "Callee-ID-Number", caller_profile->callee_id_number);
maybe_add_json_string(json, "UUID", caller_profile->uuid);
maybe_add_json_string(json, "Source", caller_profile->source);
maybe_add_json_string(json, "Context", caller_profile->context);
maybe_add_json_string(json, "Channel-Name", caller_profile->chan_name);
maybe_add_json_string(json, "Profile-UUID", caller_profile->uuid_str);
maybe_add_json_string(json, "Profile-Clone-Of", caller_profile->clone_of);
maybe_add_json_string(json, "Transfer-Source", caller_profile->transfer_source);
cJSON_AddItemToObject(json, "Direction", cJSON_CreateString(caller_profile->direction == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound"));
cJSON_AddItemToObject(json, "Logical-Direction", cJSON_CreateString(caller_profile->logical_direction == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound"));
soft = cJSON_CreateObject();
for (pn = caller_profile->soft; pn; pn = pn->next) {
maybe_add_json_string(soft, pn->var, pn->val);
}
cJSON_AddItemToObject(json, "Directory", soft);
}
SWITCH_DECLARE(void) kz_switch_ivr_set_json_call_flaws(cJSON *json, switch_core_session_t *session, switch_media_type_t type)
{
const char *name = (type == SWITCH_MEDIA_TYPE_VIDEO) ? "Video" : "Audio";
cJSON *j_stat;
switch_rtp_stats_t *stats = switch_core_media_get_stats(session, type, NULL);
if (!stats) return;
if (!stats->inbound.error_log && !stats->outbound.error_log) return;
j_stat = cJSON_CreateObject();
cJSON_AddItemToObject(json, name, j_stat);
if (stats->inbound.error_log) {
cJSON *j_err_log, *j_err, *j_in;
switch_error_period_t *ep;
j_in = cJSON_CreateObject();
cJSON_AddItemToObject(j_stat, "Inbound", j_in);
j_err_log = cJSON_CreateArray();
cJSON_AddItemToObject(j_in, "Error-Log", j_err_log);
for(ep = stats->inbound.error_log; ep; ep = ep->next) {
if (!(ep->start && ep->stop)) continue;
j_err = cJSON_CreateObject();
cJSON_AddItemToObject(j_err, "Start", cJSON_CreateNumber(ep->start));
cJSON_AddItemToObject(j_err, "Stop", cJSON_CreateNumber(ep->stop));
cJSON_AddItemToObject(j_err, "Flaws", cJSON_CreateNumber(ep->flaws));
cJSON_AddItemToObject(j_err, "Consecutive-Flaws", cJSON_CreateNumber(ep->consecutive_flaws));
cJSON_AddItemToObject(j_err, "Duration-MS", cJSON_CreateNumber((ep->stop - ep->start) / 1000));
cJSON_AddItemToArray(j_err_log, j_err);
}
}
if (stats->outbound.error_log) {
cJSON *j_err_log, *j_err, *j_out;
switch_error_period_t *ep;
j_out = cJSON_CreateObject();
cJSON_AddItemToObject(j_stat, "Outbound", j_out);
j_err_log = cJSON_CreateArray();
cJSON_AddItemToObject(j_out, "Error-Log", j_err_log);
for(ep = stats->outbound.error_log; ep; ep = ep->next) {
if (!(ep->start && ep->stop)) continue;
j_err = cJSON_CreateObject();
cJSON_AddItemToObject(j_err, "Start", cJSON_CreateNumber(ep->start));
cJSON_AddItemToObject(j_err, "Stop", cJSON_CreateNumber(ep->stop));
cJSON_AddItemToObject(j_err, "Flaws", cJSON_CreateNumber(ep->flaws));
cJSON_AddItemToObject(j_err, "Consecutive-Flaws", cJSON_CreateNumber(ep->consecutive_flaws));
cJSON_AddItemToObject(j_err, "Duration-MS", cJSON_CreateNumber((ep->stop - ep->start) / 1000));
cJSON_AddItemToArray(j_err_log, j_err);
}
}
}
#define add_jstat(_j, _i, _s) \
switch_snprintf(var_val, sizeof(var_val), "%" SWITCH_SIZE_T_FMT, _i); \
cJSON_AddItemToObject(_j, _s, cJSON_CreateNumber(_i))
SWITCH_DECLARE(void) kz_switch_ivr_set_json_call_stats(cJSON *json, switch_core_session_t *session, switch_media_type_t type)
{
const char *name = (type == SWITCH_MEDIA_TYPE_VIDEO) ? "Video" : "Audio";
cJSON *j_stat, *j_in, *j_out;
switch_rtp_stats_t *stats = switch_core_media_get_stats(session, type, NULL);
char var_val[35] = "";
if (!stats) return;
j_stat = cJSON_CreateObject();
j_in = cJSON_CreateObject();
j_out = cJSON_CreateObject();
cJSON_AddItemToObject(json, name, j_stat);
cJSON_AddItemToObject(j_stat, "Inbound", j_in);
cJSON_AddItemToObject(j_stat, "Outbound", j_out);
stats->inbound.std_deviation = sqrt(stats->inbound.variance);
add_jstat(j_in, stats->inbound.raw_bytes, "Raw-Bytes");
add_jstat(j_in, stats->inbound.media_bytes, "Media-Bytes");
add_jstat(j_in, stats->inbound.packet_count, "Packet-Count");
add_jstat(j_in, stats->inbound.media_packet_count, "Media-Packet-Count");
add_jstat(j_in, stats->inbound.skip_packet_count, "Skip-Packet-Count");
add_jstat(j_in, stats->inbound.jb_packet_count, "Jitter-Packet-Count");
add_jstat(j_in, stats->inbound.dtmf_packet_count, "DTMF-Packet-Count");
add_jstat(j_in, stats->inbound.cng_packet_count, "CNG-Packet-Count");
add_jstat(j_in, stats->inbound.flush_packet_count, "Flush-Packet-Count");
add_jstat(j_in, stats->inbound.largest_jb_size, "Largest-JB-Size");
add_jstat(j_in, stats->inbound.min_variance, "Jitter-Min-Variance");
add_jstat(j_in, stats->inbound.max_variance, "Jitter-Max-Variance");
add_jstat(j_in, stats->inbound.lossrate, "Jitter-Loss-Rate");
add_jstat(j_in, stats->inbound.burstrate, "Jitter-Burst-Rate");
add_jstat(j_in, stats->inbound.mean_interval, "Mean-Interval");
add_jstat(j_in, stats->inbound.flaws, "Flaw-Total");
add_jstat(j_in, stats->inbound.R, "Quality-Percentage");
add_jstat(j_in, stats->inbound.mos, "MOS");
add_jstat(j_out, stats->outbound.raw_bytes, "Raw-Bytes");
add_jstat(j_out, stats->outbound.media_bytes, "Media-Bytes");
add_jstat(j_out, stats->outbound.packet_count, "Packet-Count");
add_jstat(j_out, stats->outbound.media_packet_count, "Media-Packet-Count");
add_jstat(j_out, stats->outbound.skip_packet_count, "Skip-Packet-Count");
add_jstat(j_out, stats->outbound.dtmf_packet_count, "DTMF-Packet-Count");
add_jstat(j_out, stats->outbound.cng_packet_count, "CNG-Packet-Count");
add_jstat(j_out, stats->rtcp.packet_count, "RTCP-Packet-Count");
add_jstat(j_out, stats->rtcp.octet_count, "RTCP-Octet-Count");
}
static switch_status_t kz_report_channel_flaws(switch_core_session_t *session, switch_event_t *cdr_event)
{
cJSON *callStats = cJSON_CreateObject();
kz_switch_ivr_set_json_call_flaws(callStats, session, SWITCH_MEDIA_TYPE_AUDIO);
kz_switch_ivr_set_json_call_flaws(callStats, session, SWITCH_MEDIA_TYPE_VIDEO);
switch_event_add_header_string_nodup(cdr_event, SWITCH_STACK_BOTTOM, "_json_channel_media_errors", cJSON_PrintUnformatted(callStats));
cJSON_Delete(callStats);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t kz_report_channel_stats(switch_core_session_t *session, switch_event_t *cdr_event)
{
cJSON *callStats = cJSON_CreateObject();
kz_switch_ivr_set_json_call_stats(callStats, session, SWITCH_MEDIA_TYPE_AUDIO);
kz_switch_ivr_set_json_call_stats(callStats, session, SWITCH_MEDIA_TYPE_VIDEO);
switch_event_add_header_string_nodup(cdr_event, SWITCH_STACK_BOTTOM, "_json_channel_stats", cJSON_PrintUnformatted(callStats));
cJSON_Delete(callStats);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t kz_report_app_log(switch_core_session_t *session, switch_event_t *cdr_event)
{
switch_app_log_t *ap, *app_log = switch_core_session_get_app_log(session);
cJSON *j_apps = NULL;
if (!app_log) {
return SWITCH_STATUS_FALSE;
}
j_apps = cJSON_CreateArray();
for (ap = app_log; ap; ap = ap->next) {
cJSON *j_application = cJSON_CreateObject();
cJSON_AddItemToObject(j_application, "app_name", cJSON_CreateString(ap->app));
cJSON_AddItemToObject(j_application, "app_data", cJSON_CreateString(ap->arg));
cJSON_AddItemToObject(j_application, "app_stamp", cJSON_CreateNumber(ap->stamp));
cJSON_AddItemToArray(j_apps, j_application);
}
switch_event_add_header_string_nodup(cdr_event, SWITCH_STACK_BOTTOM, "_json_application_log", cJSON_PrintUnformatted(j_apps));
cJSON_Delete(j_apps);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t kz_report_callflow_extension(switch_caller_profile_t *caller_profile, cJSON *j_profile)
{
cJSON *j_caller_extension, *j_caller_extension_apps, *j_application, *j_inner_extension;
if (caller_profile->caller_extension) {
switch_caller_application_t *ap;
j_caller_extension = cJSON_CreateObject();
j_caller_extension_apps = cJSON_CreateArray();
cJSON_AddItemToObject(j_profile, "extension", j_caller_extension);
cJSON_AddItemToObject(j_caller_extension, "name", cJSON_CreateString(caller_profile->caller_extension->extension_name));
cJSON_AddItemToObject(j_caller_extension, "number", cJSON_CreateString(caller_profile->caller_extension->extension_number));
cJSON_AddItemToObject(j_caller_extension, "applications", j_caller_extension_apps);
if (caller_profile->caller_extension->current_application) {
cJSON_AddItemToObject(j_caller_extension, "current_app", cJSON_CreateString(caller_profile->caller_extension->current_application->application_name));
}
for (ap = caller_profile->caller_extension->applications; ap; ap = ap->next) {
j_application = cJSON_CreateObject();
cJSON_AddItemToArray(j_caller_extension_apps, j_application);
if (ap == caller_profile->caller_extension->current_application) {
cJSON_AddItemToObject(j_application, "last_executed", cJSON_CreateString("true"));
}
cJSON_AddItemToObject(j_application, "app_name", cJSON_CreateString(ap->application_name));
cJSON_AddItemToObject(j_application, "app_data", cJSON_CreateString(switch_str_nil(ap->application_data)));
}
if (caller_profile->caller_extension->children) {
switch_caller_profile_t *cp = NULL;
j_inner_extension = cJSON_CreateArray();
cJSON_AddItemToObject(j_caller_extension, "sub_extensions", j_inner_extension);
for (cp = caller_profile->caller_extension->children; cp; cp = cp->next) {
if (!cp->caller_extension) {
continue;
}
j_caller_extension = cJSON_CreateObject();
cJSON_AddItemToArray(j_inner_extension, j_caller_extension);
cJSON_AddItemToObject(j_caller_extension, "name", cJSON_CreateString(cp->caller_extension->extension_name));
cJSON_AddItemToObject(j_caller_extension, "number", cJSON_CreateString(cp->caller_extension->extension_number));
cJSON_AddItemToObject(j_caller_extension, "dialplan", cJSON_CreateString((char *)cp->dialplan));
if (cp->caller_extension->current_application) {
cJSON_AddItemToObject(j_caller_extension, "current_app", cJSON_CreateString(cp->caller_extension->current_application->application_name));
}
j_caller_extension_apps = cJSON_CreateArray();
cJSON_AddItemToObject(j_caller_extension, "applications", j_caller_extension_apps);
for (ap = cp->caller_extension->applications; ap; ap = ap->next) {
j_application = cJSON_CreateObject();
cJSON_AddItemToArray(j_caller_extension_apps, j_application);
if (ap == cp->caller_extension->current_application) {
cJSON_AddItemToObject(j_application, "last_executed", cJSON_CreateString("true"));
}
cJSON_AddItemToObject(j_application, "app_name", cJSON_CreateString(ap->application_name));
cJSON_AddItemToObject(j_application, "app_data", cJSON_CreateString(switch_str_nil(ap->application_data)));
}
}
}
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t kz_report_callflow(switch_core_session_t *session, switch_event_t *cdr_event)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_caller_profile_t *caller_profile;
cJSON *j_main_cp, *j_times, *j_callflow, *j_profile, *j_o;
caller_profile = switch_channel_get_caller_profile(channel);
j_callflow = cJSON_CreateArray();
while (caller_profile) {
j_profile = cJSON_CreateObject();
if (!zstr(caller_profile->dialplan)) {
cJSON_AddItemToObject(j_profile, "dialplan", cJSON_CreateString((char *)caller_profile->dialplan));
}
if (!zstr(caller_profile->profile_index)) {
cJSON_AddItemToObject(j_profile, "profile_index", cJSON_CreateString((char *)caller_profile->profile_index));
}
kz_report_callflow_extension(caller_profile, j_profile);
j_main_cp = cJSON_CreateObject();
cJSON_AddItemToObject(j_profile, "Caller-Profile", j_main_cp);
kz_switch_ivr_set_json_profile_data(j_main_cp, caller_profile);
if (caller_profile->originator_caller_profile) {
j_o = cJSON_CreateObject();
cJSON_AddItemToObject(j_main_cp, "originator", j_o);
kz_switch_ivr_set_json_profile_data(j_o, caller_profile->originator_caller_profile);
kz_report_callflow_extension(caller_profile->originator_caller_profile, j_o);
}
if (caller_profile->originatee_caller_profile) {
j_o = cJSON_CreateObject();
cJSON_AddItemToObject(j_main_cp, "originatee", j_o);
kz_switch_ivr_set_json_profile_data(j_o, caller_profile->originatee_caller_profile);
kz_report_callflow_extension(caller_profile->originatee_caller_profile, j_o);
}
if (caller_profile->times) {
j_times = cJSON_CreateObject();
cJSON_AddItemToObject(j_profile, "Time", j_times);
cJSON_AddItemToObject(j_times, "Created", cJSON_CreateNumber(caller_profile->times->created));
cJSON_AddItemToObject(j_times, "Profile-Created", cJSON_CreateNumber(caller_profile->times->profile_created));
cJSON_AddItemToObject(j_times, "Progress", cJSON_CreateNumber(caller_profile->times->progress));
cJSON_AddItemToObject(j_times, "Progress-Media", cJSON_CreateNumber(caller_profile->times->progress_media));
cJSON_AddItemToObject(j_times, "Answered", cJSON_CreateNumber(caller_profile->times->answered));
cJSON_AddItemToObject(j_times, "Bridged", cJSON_CreateNumber(caller_profile->times->bridged));
cJSON_AddItemToObject(j_times, "Last-Hold", cJSON_CreateNumber(caller_profile->times->last_hold));
cJSON_AddItemToObject(j_times, "Hold-Accumulated", cJSON_CreateNumber(caller_profile->times->hold_accum));
cJSON_AddItemToObject(j_times, "Hangup", cJSON_CreateNumber(caller_profile->times->hungup));
cJSON_AddItemToObject(j_times, "Resurrect", cJSON_CreateNumber(caller_profile->times->resurrected));
cJSON_AddItemToObject(j_times, "Transfer", cJSON_CreateNumber(caller_profile->times->transferred));
}
cJSON_AddItemToArray(j_callflow, j_profile);
caller_profile = caller_profile->next;
}
switch_event_add_header_string_nodup(cdr_event, SWITCH_STACK_BOTTOM, "_json_callflow", cJSON_PrintUnformatted(j_callflow));
cJSON_Delete(j_callflow);
return SWITCH_STATUS_SUCCESS;
}
#define ORIGINATED_LEGS_VARIABLE "originated_legs"
#define ORIGINATED_LEGS_ITEM_DELIM ';'
#define ORIGINATE_CAUSES_VARIABLE "originate_causes"
#define ORIGINATE_CAUSES_ITEM_DELIM ';'
static switch_status_t kz_report_originated_legs(switch_core_session_t *session, switch_event_t *cdr_event)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
cJSON *j_originated = cJSON_CreateArray();
const char *originated_legs_var = NULL, *originate_causes_var = NULL;
int idx = 0;
while(1) {
char *argv_leg[10] = { 0 }, *argv_cause[10] = { 0 };
char *originated_legs, *originate_causes;
cJSON *j_originated_leg;
originated_legs_var = switch_channel_get_variable_dup(channel, ORIGINATED_LEGS_VARIABLE, SWITCH_FALSE, idx);
originate_causes_var = switch_channel_get_variable_dup(channel, ORIGINATE_CAUSES_VARIABLE, SWITCH_FALSE, idx);
if (zstr(originated_legs_var) || zstr(originate_causes_var)) {
break;
}
originated_legs = strdup(originated_legs_var);
originate_causes = strdup(originate_causes_var);
switch_separate_string(originated_legs, ORIGINATED_LEGS_ITEM_DELIM, argv_leg, (sizeof(argv_leg) / sizeof(argv_leg[0])));
switch_separate_string(originate_causes, ORIGINATE_CAUSES_ITEM_DELIM, argv_cause, (sizeof(argv_cause) / sizeof(argv_cause[0])));
j_originated_leg = cJSON_CreateObject();
cJSON_AddItemToObject(j_originated_leg, "Call-ID", cJSON_CreateString(argv_leg[0]));
cJSON_AddItemToObject(j_originated_leg, "Caller-ID-Name", cJSON_CreateString(argv_leg[1]));
cJSON_AddItemToObject(j_originated_leg, "Caller-ID-Number", cJSON_CreateString(argv_leg[2]));
cJSON_AddItemToObject(j_originated_leg, "Result", cJSON_CreateString(argv_cause[1]));
cJSON_AddItemToArray(j_originated, j_originated_leg);
switch_safe_free(originated_legs);
switch_safe_free(originate_causes);
idx++;
}
switch_event_add_header_string_nodup(cdr_event, SWITCH_STACK_BOTTOM, "_json_originated_legs", cJSON_PrintUnformatted(j_originated));
cJSON_Delete(j_originated);
return SWITCH_STATUS_SUCCESS;
}
#define MAX_HISTORY 50
#define HST_ARRAY_DELIM "|:"
#define HST_ITEM_DELIM ':'
static void kz_report_transfer_history_item(char* value, cJSON *json)
{
char *argv[4] = { 0 };
char *item = strdup(value);
int argc = switch_separate_string(item, HST_ITEM_DELIM, argv, (sizeof(argv) / sizeof(argv[0])));
cJSON *jitem = cJSON_CreateObject();
char *epoch = NULL, *callid = NULL, *type = NULL;
int add = 0;
if(argc == 4) {
add = 1;
epoch = argv[0];
callid = argv[1];
type = argv[2];
if(!strncmp(type, "bl_xfer", 7)) {
//char *split = strchr(argv[3], '/');
//if(split) *(split++) = '\0';
cJSON_AddItemToObject(jitem, "Caller-Profile-ID", cJSON_CreateString(callid));
cJSON_AddItemToObject(jitem, "Type", cJSON_CreateString("blind"));
cJSON_AddItemToObject(jitem, "Extension", cJSON_CreateString(argv[3]));
cJSON_AddItemToObject(jitem, "Timestamp", cJSON_CreateNumber(strtod(epoch, NULL)));
} else if(!strncmp(type, "att_xfer", 8)) {
char *split = strchr(argv[3], '/');
if(split) {
*(split++) = '\0';
cJSON_AddItemToObject(jitem, "Caller-Profile-ID", cJSON_CreateString(callid));
cJSON_AddItemToObject(jitem, "Type", cJSON_CreateString("attended"));
cJSON_AddItemToObject(jitem, "Transferee", cJSON_CreateString(argv[3]));
cJSON_AddItemToObject(jitem, "Transferer", cJSON_CreateString(split));
cJSON_AddItemToObject(jitem, "Timestamp", cJSON_CreateNumber(strtod(epoch, NULL)));
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TRANSFER TYPE '%s' NOT HANDLED => %s\n", type, item);
add = 0;
}
} else if(!strncmp(type, "uuid_br", 7)) {
cJSON_AddItemToObject(jitem, "Caller-Profile-ID", cJSON_CreateString(callid));
cJSON_AddItemToObject(jitem, "Type", cJSON_CreateString("bridge"));
cJSON_AddItemToObject(jitem, "Other-Leg", cJSON_CreateString(argv[3]));
cJSON_AddItemToObject(jitem, "Timestamp", cJSON_CreateNumber(strtod(epoch, NULL)));
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TRANSFER TYPE '%s' NOT HANDLED => %s\n", type, item);
add = 0;
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TRANSFER TYPE SPLIT ERROR %i => %s\n", argc, item);
}
if(add) {
cJSON_AddItemToArray(json, jitem);
} else {
cJSON_Delete(jitem);
}
switch_safe_free(item);
}
static switch_status_t kz_report_transfer_history(switch_core_session_t *session, switch_event_t *cdr_event, const char* var_name)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
cJSON *j_transfer = NULL;
char *tmp_history = NULL, *history = NULL, *argv[MAX_HISTORY] = { 0 };
char event_header[50];
int n, argc = 0;
const char *transfer_var = switch_channel_get_variable_dup(channel, var_name, SWITCH_FALSE, -1);
if (zstr(transfer_var)) {
return SWITCH_STATUS_SUCCESS;
}
if (!(tmp_history = strdup(transfer_var))) {
return SWITCH_STATUS_SUCCESS;
}
sprintf(event_header, "_json_%s", var_name);
history = tmp_history;
j_transfer = cJSON_CreateArray();
if (!strncmp(history, "ARRAY::", 7)) {
history += 7;
argc = switch_separate_string_string(history, HST_ARRAY_DELIM, argv, (sizeof(argv) / sizeof(argv[0])));
for(n=0; n < argc; n++) {
kz_report_transfer_history_item(argv[n], j_transfer);
}
switch_event_add_header_string_nodup(cdr_event, SWITCH_STACK_BOTTOM, event_header, cJSON_PrintUnformatted(j_transfer));
} else if (strchr(history, HST_ITEM_DELIM)) {
kz_report_transfer_history_item(history, j_transfer);
switch_event_add_header_string_nodup(cdr_event, SWITCH_STACK_BOTTOM, event_header, cJSON_PrintUnformatted(j_transfer));
}
cJSON_Delete(j_transfer);
switch_safe_free(tmp_history);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t kz_report(switch_core_session_t *session, switch_event_t *cdr_event)
{
kz_report_app_log(session, cdr_event);
kz_report_callflow(session, cdr_event);
kz_report_channel_stats(session, cdr_event);
kz_report_channel_flaws(session, cdr_event);
kz_report_originated_legs(session, cdr_event);
kz_report_transfer_history(session, cdr_event, SWITCH_TRANSFER_HISTORY_VARIABLE);
kz_report_transfer_history(session, cdr_event, SWITCH_TRANSFER_SOURCE_VARIABLE);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t kz_cdr_on_reporting(switch_core_session_t *session)
{
switch_event_t *cdr_event = NULL;
switch_channel_t *channel = switch_core_session_get_channel(session);
if (switch_event_create_subclass(&cdr_event, SWITCH_EVENT_CUSTOM, MY_EVENT_JSON_CDR) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "error creating event for report data!\n");
return SWITCH_STATUS_FALSE;
}
kz_report(session, cdr_event);
switch_channel_event_set_data(channel, cdr_event);
switch_event_fire(&cdr_event);
return SWITCH_STATUS_SUCCESS;
}
static switch_state_handler_table_t kz_cdr_state_handlers = {
/*.on_init */ NULL,
/*.on_routing */ NULL,
/*.on_execute */ NULL,
/*.on_hangup */ NULL,
/*.on_exchange_media */ NULL,
/*.on_soft_execute */ NULL,
/*.on_consume_media */ NULL,
/*.on_hibernate */ NULL,
/*.on_reset */ NULL,
/*.on_park */ NULL,
/*.on_reporting */ kz_cdr_on_reporting
};
static void kz_cdr_register_state_handlers()
{
switch_core_add_state_handler(&kz_cdr_state_handlers);
}
static void kz_cdr_unregister_state_handlers()
{
switch_core_remove_state_handler(&kz_cdr_state_handlers);
}
static void kz_cdr_register_events()
{
if (switch_event_reserve_subclass(MY_EVENT_JSON_CDR) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_JSON_CDR);
}
}
static void kz_cdr_unregister_events()
{
switch_event_free_subclass(MY_EVENT_JSON_CDR);
}
void kz_cdr_start()
{
kz_cdr_register_events();
kz_cdr_register_state_handlers();
}
void kz_cdr_stop()
{
kz_cdr_unregister_state_handlers();
kz_cdr_unregister_events();
}
/* 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:
*/

View File

@ -1,592 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Karl Anderson <karl@2600hz.com>
* Darren Schreiber <darren@2600hz.com>
*
*
* kazoo_commands.c -- clones of mod_commands commands slightly modified for kazoo
*
*/
#include "mod_kazoo.h"
#include <curl/curl.h>
#include <switch_curl.h>
#define UUID_SET_DESC "Set a variable"
#define UUID_SET_SYNTAX "<uuid> <var> [value]"
#define UUID_MULTISET_DESC "Set multiple variables"
#define UUID_MULTISET_SYNTAX "<uuid> <var>=<value>;<var>=<value>..."
#define KZ_HTTP_PUT_DESC "upload a local freeswitch file to a url"
#define KZ_HTTP_PUT_SYNTAX "localfile url"
#define KZ_FIRST_OF_DESC "returns first-of existing event header in params"
#define KZ_FIRST_OF_SYNTAX "list of headers to check"
#define MAX_FIRST_OF 25
SWITCH_STANDARD_API(kz_first_of)
{
char delim = '|';
char *mycmd = NULL, *mycmd_dup = NULL, *argv[MAX_FIRST_OF] = { 0 };
int n, argc = 0;
switch_event_header_t *header = NULL;
switch_channel_t *channel = NULL;
if (zstr(cmd)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid arg\n");
return SWITCH_STATUS_GENERR;
}
if ( session ) {
channel = switch_core_session_get_channel(session);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "GOT CHANNEL\n");
}
mycmd_dup = mycmd = strdup(cmd);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "FIRST-OF %s\n", mycmd);
if (!zstr(mycmd) && *mycmd == '^' && *(mycmd+1) == '^') {
mycmd += 2;
delim = *mycmd++;
}
argc = switch_separate_string(mycmd, delim, argv, (sizeof(argv) / sizeof(argv[0])));
for(n=0; n < argc; n++) {
char* item = argv[n];
if(*item == '#' || *item == '!' || *item == '?') {
if(*(++item) != '\0') {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "RETURNING default %s\n", item);
stream->write_function(stream, item);
break;
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "CHECKING %s\n", item);
if (channel) {
const char *var = switch_channel_get_variable_dup(channel, item, SWITCH_FALSE, -1);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "CHECKING CHANNEL %s\n", item);
if (var) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "GOT FROM CHANNEL %s => %s\n", item, var);
stream->write_function(stream, var);
break;
}
if (!strncmp(item, "variable_", 9)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "CHECKING CHANNEL %s\n", item+9);
var = switch_channel_get_variable_dup(channel, item+9, SWITCH_FALSE, -1);
if (var) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "GOT FROM CHANNEL %s => %s\n", item+9, var);
stream->write_function(stream, var);
break;
}
}
}
header = switch_event_get_header_ptr(stream->param_event, item);
if(header) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "RETURNING %s : %s\n", item, header->value);
stream->write_function(stream, header->value);
break;
}
}
}
switch_safe_free(mycmd_dup);
return SWITCH_STATUS_SUCCESS;
}
switch_status_t kz_uuid_setvar(int urldecode, const char *cmd, switch_core_session_t *session, switch_stream_handle_t *stream)
{
switch_core_session_t *psession = NULL;
char *mycmd = NULL, *argv[3] = { 0 };
int argc = 0;
if (!zstr(cmd) && (mycmd = strdup(cmd))) {
argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
if ((argc == 2 || argc == 3) && !zstr(argv[0])) {
char *uuid = argv[0];
char *var_name = argv[1];
char *var_value = NULL;
if (argc == 3) {
var_value = argv[2];
}
if ((psession = switch_core_session_locate(uuid))) {
switch_channel_t *channel;
switch_event_t *event;
channel = switch_core_session_get_channel(psession);
if (zstr(var_name)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No variable name specified.\n");
stream->write_function(stream, "-ERR No variable specified\n");
} else {
if(urldecode) {
switch_url_decode(var_value);
}
switch_channel_set_variable(channel, var_name, var_value);
kz_check_set_profile_var(channel, var_name, var_value);
stream->write_function(stream, "+OK\n");
}
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
switch_event_fire(&event);
}
switch_core_session_rwunlock(psession);
} else {
stream->write_function(stream, "-ERR No such channel!\n");
}
goto done;
}
}
stream->write_function(stream, "-USAGE: %s\n", UUID_SET_SYNTAX);
done:
switch_safe_free(mycmd);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_STANDARD_API(uuid_setvar_function)
{
return kz_uuid_setvar(0, cmd, session, stream);
}
SWITCH_STANDARD_API(uuid_setvar_encoded_function)
{
return kz_uuid_setvar(1, cmd, session, stream);
}
switch_status_t kz_uuid_setvar_multi(int urldecode, const char *cmd, switch_core_session_t *session, switch_stream_handle_t *stream)
{
switch_core_session_t *psession = NULL;
char delim = ';';
char *mycmd = NULL, *vars, *argv[64] = { 0 };
int argc = 0;
char *var_name, *var_value = NULL;
if (!zstr(cmd) && (mycmd = strdup(cmd))) {
char *uuid = mycmd;
if (!(vars = strchr(uuid, ' '))) {
goto done;
}
*vars++ = '\0';
if (*vars == '^' && *(vars+1) == '^') {
vars += 2;
delim = *vars++;
}
if ((psession = switch_core_session_locate(uuid))) {
switch_channel_t *channel = switch_core_session_get_channel(psession);
switch_event_t *event;
int x, y = 0;
argc = switch_separate_string(vars, delim, argv, (sizeof(argv) / sizeof(argv[0])));
for (x = 0; x < argc; x++) {
var_name = argv[x];
if (var_name && (var_value = strchr(var_name, '='))) {
*var_value++ = '\0';
}
if (zstr(var_name)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No variable name specified.\n");
stream->write_function(stream, "-ERR No variable specified\n");
} else {
if(urldecode) {
switch_url_decode(var_value);
}
switch_channel_set_variable(channel, var_name, var_value);
kz_check_set_profile_var(channel, var_name, var_value);
y++;
}
}
/* keep kazoo nodes in sync */
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
switch_event_fire(&event);
}
switch_core_session_rwunlock(psession);
if (y) {
stream->write_function(stream, "+OK\n");
goto done;
}
} else {
stream->write_function(stream, "-ERR No such channel!\n");
}
}
stream->write_function(stream, "-USAGE: %s\n", UUID_MULTISET_SYNTAX);
done:
switch_safe_free(mycmd);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_STANDARD_API(uuid_setvar_multi_function)
{
return kz_uuid_setvar_multi(0, cmd, session, stream);
}
SWITCH_STANDARD_API(uuid_setvar_multi_encoded_function)
{
return kz_uuid_setvar_multi(1, cmd, session, stream);
}
static size_t body_callback(char *buffer, size_t size, size_t nitems, void *userdata)
{
return size * nitems;
}
static size_t header_callback(char *buffer, size_t size, size_t nitems, void *userdata)
{
switch_event_t* event = (switch_event_t*)userdata;
int len = strlen(buffer);
char buf[1024];
if(len > 2 && len < 1024) {
snprintf(buf, sizeof(buf), "%s", buffer);
switch_event_add_header_string(event, SWITCH_STACK_PUSH | SWITCH_STACK_BOTTOM, "Reply-Headers", buf);
}
return nitems * size;
}
SWITCH_STANDARD_API(kz_http_put)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_memory_pool_t *lpool = NULL;
switch_memory_pool_t *pool = NULL;
char *args = NULL;
char *argv[10] = { 0 };
int argc = 0;
switch_event_t *params = NULL;
char *url = NULL;
char *filename = NULL;
int delete_file = 0;
switch_curl_slist_t *headers = NULL; /* optional linked-list of HTTP headers */
char *ext; /* file extension, used for MIME type identification */
const char *mime_type = "application/octet-stream";
char *buf = NULL;
char *error = NULL;
CURL *curl_handle = NULL;
long httpRes = 0;
struct stat file_info = {0};
FILE *file_to_put = NULL;
if (session) {
pool = switch_core_session_get_pool(session);
} else {
switch_core_new_memory_pool(&lpool);
pool = lpool;
}
if (zstr(cmd)) {
stream->write_function(stream, "USAGE: %s\n", KZ_HTTP_PUT_SYNTAX);
status = SWITCH_STATUS_SUCCESS;
goto done;
}
args = strdup(cmd);
argc = switch_separate_string(args, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
if (argc != 2) {
stream->write_function(stream, "USAGE: %s\n", KZ_HTTP_PUT_SYNTAX);
status = SWITCH_STATUS_SUCCESS;
goto done;
}
/* parse params and get profile */
url = switch_core_strdup(pool, argv[0]);
if (*url == '{') {
if (switch_event_create_brackets(url, '{', '}', ',', &params, &url, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) {
status = SWITCH_STATUS_FALSE;
stream->write_function(stream, "-ERR error parsing parameters\n");
goto done;
}
}
filename = switch_core_strdup(pool, argv[1]);
/* guess what type of mime content this is going to be */
if ((ext = strrchr(filename, '.'))) {
ext++;
if (!(mime_type = switch_core_mime_ext2type(ext))) {
mime_type = "application/octet-stream";
}
}
buf = switch_mprintf("Content-Type: %s", mime_type);
headers = switch_curl_slist_append(headers, buf);
/* open file and get the file size */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "opening %s for upload to %s\n", filename, url);
/* libcurl requires FILE* */
file_to_put = fopen(filename, "rb");
if (!file_to_put) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "fopen() error: %s\n", strerror(errno));
stream->write_function(stream, "-ERR error opening file\n");
status = SWITCH_STATUS_FALSE;
goto done;
}
if (fstat(fileno(file_to_put), &file_info) == -1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "fstat() error: %s\n", strerror(errno));
stream->write_function(stream, "-ERR fstat error\n");
goto done;
}
curl_handle = switch_curl_easy_init();
if (!curl_handle) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "switch_curl_easy_init() failure\n");
status = SWITCH_STATUS_FALSE;
stream->write_function(stream, "-ERR switch_curl_easy init failure\n");
goto done;
}
switch_curl_easy_setopt(curl_handle, CURLOPT_UPLOAD, 1);
#if !defined(LIBCURL_VERSION_NUM) || (LIBCURL_VERSION_NUM < 0x070c01)
switch_curl_easy_setopt(curl_handle, CURLOPT_PUT, 1);
#endif
switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
switch_curl_easy_setopt(curl_handle, CURLOPT_URL, url);
switch_curl_easy_setopt(curl_handle, CURLOPT_READDATA, file_to_put);
switch_curl_easy_setopt(curl_handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10);
switch_curl_easy_setopt(curl_handle, CURLOPT_FAILONERROR, 1);
switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-kazoo/1.0");
switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, stream->param_event);
switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_callback);
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, body_callback);
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
switch_curl_easy_perform(curl_handle);
switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes);
switch_curl_easy_cleanup(curl_handle);
if (httpRes == 200 || httpRes == 201 || httpRes == 202 || httpRes == 204) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s saved to %s\n", filename, url);
switch_event_add_header(stream->param_event, SWITCH_STACK_BOTTOM, "API-Output", "%s saved to %s", filename, url);
stream->write_function(stream, "+OK %s saved to %s", filename, url);
delete_file = 1;
} else {
error = switch_mprintf("Received HTTP error %ld trying to save %s to %s", httpRes, filename, url);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", error);
switch_event_add_header(stream->param_event, SWITCH_STACK_BOTTOM, "API-Error", "%s", error);
switch_event_add_header(stream->param_event, SWITCH_STACK_BOTTOM, "API-HTTP-Error", "%ld", httpRes);
stream->write_function(stream, "-ERR %s", error);
status = SWITCH_STATUS_GENERR;
}
done:
if (file_to_put) {
fclose(file_to_put);
if(delete_file) {
remove(filename);
}
}
if (headers) {
switch_curl_slist_free_all(headers);
}
switch_safe_free(buf);
switch_safe_free(error);
switch_safe_free(args);
if (lpool) {
switch_core_destroy_memory_pool(&lpool);
}
if (params) {
switch_event_destroy(&params);
}
return status;
}
SWITCH_STANDARD_API(kz_expand_api)
{
char *p = NULL, *input = NULL;
char *uuid = NULL, *mycmd;
if (zstr(cmd)) {
stream->write_function(stream, "-ERR invalid input");
return SWITCH_STATUS_GENERR;
}
if (!(mycmd = strdup(cmd))) {
stream->write_function(stream, "-ERR no memory");
return SWITCH_STATUS_GENERR;
}
if (!strncasecmp(mycmd, "uuid:", 5)) {
uuid = mycmd + 5;
if ((input = strchr(uuid, ' ')) != NULL) {
*input++ = '\0';
} else {
stream->write_function(stream, "-ERR invalid argument");
switch_safe_free(mycmd);
return SWITCH_STATUS_GENERR;
}
} else {
input = mycmd;
}
p = kz_expand(input, uuid);
stream->write_function(stream, "+OK %s", p);
if (p != input) {
switch_safe_free(p);
}
switch_safe_free(mycmd);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_STANDARD_API(kz_eval_api)
{
char *p = NULL, *input = NULL;
char *uuid = NULL, *mycmd;
switch_core_session_t *nsession = NULL;
switch_channel_t *channel = NULL;
if (zstr(cmd)) {
stream->write_function(stream, "-ERR invalid input");
return SWITCH_STATUS_GENERR;
}
if (!(mycmd = strdup(cmd))) {
stream->write_function(stream, "-ERR no memory");
return SWITCH_STATUS_GENERR;
}
if (!strncasecmp(mycmd, "uuid:", 5)) {
uuid = mycmd + 5;
if ((input = strchr(uuid, ' ')) != NULL) {
*input++ = '\0';
if ((nsession = switch_core_session_locate(uuid)) != NULL) {
channel = switch_core_session_get_channel(nsession);
} else {
stream->write_function(stream, "-ERR invalid session");
switch_safe_free(mycmd);
return SWITCH_STATUS_GENERR;
}
} else {
stream->write_function(stream, "-ERR invalid argument");
switch_safe_free(mycmd);
return SWITCH_STATUS_GENERR;
}
} else if (session == NULL) {
stream->write_function(stream, "-ERR invalid argument");
switch_safe_free(mycmd);
return SWITCH_STATUS_GENERR;
} else {
channel = switch_core_session_get_channel(session);
input = mycmd;
}
p = switch_channel_expand_variables_check(channel, input, NULL, NULL, 0);
stream->write_function(stream, "+OK %s", p);
if (p != input) {
switch_safe_free(p);
}
switch_safe_free(mycmd);
if (nsession) {
switch_core_session_rwunlock(nsession);
}
return SWITCH_STATUS_SUCCESS;
}
#define KZ_CONTACT_DESC "returns kazoo contact"
#define KZ_CONTACT_SYNTAX "endpoint@account"
SWITCH_STANDARD_API(kz_contact_fun)
{
switch_event_t *params = NULL;
const char *var = NULL;
switch_xml_t xml_node = NULL;
switch_xml_t xml_root = NULL;
const char *reply = "error/subscriber_absent";
if (!cmd) {
stream->write_function(stream, "%s", reply);
return SWITCH_STATUS_SUCCESS;
}
switch_event_create(&params, SWITCH_EVENT_REQUEST_PARAMS);
switch_assert(params);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "action", "call");
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Fetch-Exclude-Cache", "true");
/*
if (stream->param_event) {
switch_event_merge(params, stream->param_event);
}
*/
/*
if (session) {
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Fetch-Call-UUID", switch_core_session_get_uuid(session));
} else if (stream->param_event && (var = switch_event_get_header(stream->param_event, "ent_originate_aleg_uuid")) != NULL) {
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Fetch-Call-UUID", var);
}
*/
if (switch_xml_locate("directory", "location", "id", cmd, &xml_root, &xml_node, params, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "%s", reply);
return SWITCH_STATUS_SUCCESS;
}
var = switch_xml_attr(xml_node, "value");
if (!zstr(var)) {
reply = var;
}
stream->write_function(stream, "%s", reply);
switch_xml_free(xml_root);
return SWITCH_STATUS_SUCCESS;
}
void add_kz_commands(switch_loadable_module_interface_t **module_interface) {
switch_api_interface_t *api_interface = NULL;
SWITCH_ADD_API(api_interface, "kz_uuid_setvar_multi", UUID_SET_DESC, uuid_setvar_multi_function, UUID_MULTISET_SYNTAX);
SWITCH_ADD_API(api_interface, "kz_uuid_setvar_multi_encoded", UUID_SET_DESC, uuid_setvar_multi_encoded_function, UUID_MULTISET_SYNTAX);
switch_console_set_complete("add kz_uuid_setvar_multi ::console::list_uuid");
switch_console_set_complete("add kz_uuid_setvar_multi_encoded ::console::list_uuid");
SWITCH_ADD_API(api_interface, "kz_uuid_setvar", UUID_MULTISET_DESC, uuid_setvar_function, UUID_SET_SYNTAX);
SWITCH_ADD_API(api_interface, "kz_uuid_setvar_encoded", UUID_MULTISET_DESC, uuid_setvar_encoded_function, UUID_SET_SYNTAX);
switch_console_set_complete("add kz_uuid_setvar ::console::list_uuid");
switch_console_set_complete("add kz_uuid_setvar_encoded ::console::list_uuid");
SWITCH_ADD_API(api_interface, "kz_http_put", KZ_HTTP_PUT_DESC, kz_http_put, KZ_HTTP_PUT_SYNTAX);
SWITCH_ADD_API(api_interface, "first-of", KZ_FIRST_OF_DESC, kz_first_of, KZ_FIRST_OF_SYNTAX);
SWITCH_ADD_API(api_interface, "kz_expand", KZ_FIRST_OF_DESC, kz_expand_api, KZ_FIRST_OF_SYNTAX);
SWITCH_ADD_API(api_interface, "kz_eval", KZ_FIRST_OF_DESC, kz_eval_api, KZ_FIRST_OF_SYNTAX);
SWITCH_ADD_API(api_interface, "kz_contact", KZ_CONTACT_DESC, kz_contact_fun, KZ_CONTACT_SYNTAX);
}

View File

@ -1,553 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Based on mod_skel by
* Anthony Minessale II <anthm@freeswitch.org>
*
* Contributor(s):
*
* Daniel Bryars <danb@aeriandi.com>
* Tim Brown <tim.brown@aeriandi.com>
* Anthony Minessale II <anthm@freeswitch.org>
* William King <william.king@quentustech.com>
* Mike Jerris <mike@jerris.com>
*
* kazoo.c -- Sends FreeSWITCH events to an AMQP broker
*
*/
#include "mod_kazoo.h"
static const char *LOG_LEVEL_NAMES[] = {
"SWITCH_LOG_DEBUG10",
"SWITCH_LOG_DEBUG9",
"SWITCH_LOG_DEBUG8",
"SWITCH_LOG_DEBUG7",
"SWITCH_LOG_DEBUG6",
"SWITCH_LOG_DEBUG5",
"SWITCH_LOG_DEBUG4",
"SWITCH_LOG_DEBUG3",
"SWITCH_LOG_DEBUG2",
"SWITCH_LOG_DEBUG1",
"SWITCH_LOG_DEBUG",
"SWITCH_LOG_INFO",
"SWITCH_LOG_NOTICE",
"SWITCH_LOG_WARNING",
"SWITCH_LOG_ERROR",
"SWITCH_LOG_CRIT",
"SWITCH_LOG_ALERT",
"SWITCH_LOG_CONSOLE",
"SWITCH_LOG_INVALID",
"SWITCH_LOG_UNINIT",
NULL
};
static const switch_log_level_t LOG_LEVEL_VALUES[] = {
SWITCH_LOG_DEBUG10,
SWITCH_LOG_DEBUG9,
SWITCH_LOG_DEBUG8,
SWITCH_LOG_DEBUG7,
SWITCH_LOG_DEBUG6,
SWITCH_LOG_DEBUG5,
SWITCH_LOG_DEBUG4,
SWITCH_LOG_DEBUG3,
SWITCH_LOG_DEBUG2,
SWITCH_LOG_DEBUG1,
SWITCH_LOG_DEBUG,
SWITCH_LOG_INFO,
SWITCH_LOG_NOTICE,
SWITCH_LOG_WARNING,
SWITCH_LOG_ERROR,
SWITCH_LOG_CRIT,
SWITCH_LOG_ALERT,
SWITCH_LOG_CONSOLE,
SWITCH_LOG_INVALID,
SWITCH_LOG_UNINIT
};
switch_log_level_t log_str2level(const char *str)
{
int x = 0;
switch_log_level_t level = SWITCH_LOG_INVALID;
if (switch_is_number(str)) {
x = atoi(str);
if (x > SWITCH_LOG_INVALID) {
return SWITCH_LOG_INVALID - 1;
} else if (x < 0) {
return 0;
} else {
return x;
}
}
for (x = 0;; x++) {
if (!LOG_LEVEL_NAMES[x]) {
break;
}
if (!strcasecmp(LOG_LEVEL_NAMES[x], str)) {
level = LOG_LEVEL_VALUES[x]; //(switch_log_level_t) x;
break;
}
}
return level;
}
switch_status_t kazoo_config_loglevels(switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_loglevels_ptr *ptr)
{
switch_xml_t xml_level, xml_logging;
kazoo_loglevels_ptr loglevels = (kazoo_loglevels_ptr) switch_core_alloc(pool, sizeof(kazoo_loglevels_t));
loglevels->failed_log_level = SWITCH_LOG_ALERT;
loglevels->filtered_event_log_level = SWITCH_LOG_DEBUG1;
loglevels->filtered_field_log_level = SWITCH_LOG_DEBUG1;
loglevels->info_log_level = SWITCH_LOG_INFO;
loglevels->warn_log_level = SWITCH_LOG_WARNING;
loglevels->success_log_level = SWITCH_LOG_DEBUG;
loglevels->time_log_level = SWITCH_LOG_DEBUG1;
loglevels->trace_log_level = SWITCH_LOG_DEBUG1;
loglevels->debug_log_level = SWITCH_LOG_DEBUG;
loglevels->error_log_level = SWITCH_LOG_ERROR;
loglevels->hashing_log_level = SWITCH_LOG_DEBUG1;
if ((xml_logging = switch_xml_child(cfg, "logging")) != NULL) {
for (xml_level = switch_xml_child(xml_logging, "log"); xml_level; xml_level = xml_level->next) {
char *var = (char *) switch_xml_attr_soft(xml_level, "name");
char *val = (char *) switch_xml_attr_soft(xml_level, "value");
if (!var) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "logging param missing 'name' attribute\n");
continue;
}
if (!val) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "logging param[%s] missing 'value' attribute\n", var);
continue;
}
if (!strncmp(var, "success", 7)) {
loglevels->success_log_level = log_str2level(val);
} else if (!strncmp(var, "failed", 6)) {
loglevels->failed_log_level = log_str2level(val);
} else if (!strncmp(var, "info", 4)) {
loglevels->info_log_level = log_str2level(val);
} else if (!strncmp(var, "warn", 4)) {
loglevels->warn_log_level = log_str2level(val);
} else if (!strncmp(var, "time", 4)) {
loglevels->time_log_level = log_str2level(val);
} else if (!strncmp(var, "filtered-event", 14)) {
loglevels->filtered_event_log_level = log_str2level(val);
} else if (!strncmp(var, "filtered-field", 14)) {
loglevels->filtered_field_log_level = log_str2level(val);
} else if (!strncmp(var, "trace", 5)) {
loglevels->trace_log_level = log_str2level(val);
} else if (!strncmp(var, "debug", 5)) {
loglevels->debug_log_level = log_str2level(val);
} else if (!strncmp(var, "error", 5)) {
loglevels->error_log_level = log_str2level(val);
} else if (!strncmp(var, "hashing", 7)) {
loglevels->hashing_log_level = log_str2level(val);
}
} /* xml_level for loop */
}
*ptr = loglevels;
return SWITCH_STATUS_SUCCESS;
}
switch_status_t kazoo_config_filters(switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_filter_ptr *ptr)
{
switch_xml_t filters, filter;
// char *routing_key = NULL;
kazoo_filter_ptr root = NULL, prv = NULL, cur = NULL;
if ((filters = switch_xml_child(cfg, "filters")) != NULL) {
for (filter = switch_xml_child(filters, "filter"); filter; filter = filter->next) {
const char *var = switch_xml_attr(filter, "name");
const char *val = switch_xml_attr(filter, "value");
const char *type = switch_xml_attr(filter, "type");
const char *compare = switch_xml_attr(filter, "compare");
cur = (kazoo_filter_ptr) switch_core_alloc(pool, sizeof(kazoo_filter));
memset(cur, 0, sizeof(kazoo_filter));
if(prv == NULL) {
root = prv = cur;
} else {
prv->next = cur;
prv = cur;
}
cur->type = FILTER_EXCLUDE;
cur->compare = FILTER_COMPARE_VALUE;
if(var)
cur->name = switch_core_strdup(pool, var);
if(val)
cur->value = switch_core_strdup(pool, val);
if(type) {
if (!strncmp(type, "exclude", 7)) {
cur->type = FILTER_EXCLUDE;
} else if (!strncmp(type, "include", 7)) {
cur->type = FILTER_INCLUDE;
}
}
if(compare) {
if (!strncmp(compare, "value", 7)) {
cur->compare = FILTER_COMPARE_VALUE;
} else if (!strncmp(compare, "prefix", 6)) {
cur->compare = FILTER_COMPARE_PREFIX;
} else if (!strncmp(compare, "list", 4)) {
cur->compare = FILTER_COMPARE_LIST;
} else if (!strncmp(compare, "exists", 6)) {
cur->compare = FILTER_COMPARE_EXISTS;
} else if (!strncmp(compare, "regex", 5)) {
cur->compare = FILTER_COMPARE_REGEX;
} else if (!strncmp(compare, "field", 5)) {
cur->compare = FILTER_COMPARE_FIELD;
}
}
if(cur->value == NULL)
cur->compare = FILTER_COMPARE_EXISTS;
if(cur->compare == FILTER_COMPARE_LIST) {
cur->list.size = switch_separate_string(cur->value, '|', cur->list.value, MAX_LIST_FIELDS);
}
}
}
*ptr = root;
return SWITCH_STATUS_SUCCESS;
}
switch_status_t kazoo_config_field(kazoo_config_ptr definitions, switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_field_ptr *ptr)
{
const char *var = switch_xml_attr(cfg, "name");
const char *val = switch_xml_attr(cfg, "value");
const char *as = switch_xml_attr(cfg, "as");
const char *type = switch_xml_attr(cfg, "type");
const char *exclude_prefix = switch_xml_attr(cfg, "exclude-prefix");
const char *serialize_as = switch_xml_attr(cfg, "serialize-as");
const char *as_array = switch_xml_attr(cfg, "as-array");
kazoo_field_ptr cur = (kazoo_field_ptr) switch_core_alloc(pool, sizeof(kazoo_field));
cur->in_type = FIELD_NONE;
cur->out_type = JSON_NONE;
if(var)
cur->name = switch_core_strdup(pool, var);
if(val)
cur->value = switch_core_strdup(pool, val);
if(as)
cur->as = switch_core_strdup(pool, as);
if(type) {
if (!strncmp(type, "copy", 4)) {
cur->in_type = FIELD_COPY;
} else if (!strncmp(type, "static", 6)) {
cur->in_type = FIELD_STATIC;
} else if (!strncmp(type, "first-of", 8)) {
cur->in_type = FIELD_FIRST_OF;
} else if (!strncmp(type, "expand", 6)) {
cur->in_type = FIELD_EXPAND;
} else if (!strncmp(type, "prefix", 10)) {
cur->in_type = FIELD_PREFIX;
} else if (!strncmp(type, "group", 5)) {
cur->in_type = FIELD_GROUP;
} else if (!strncmp(type, "reference", 9)) {
cur->in_type = FIELD_REFERENCE;
}
}
if(serialize_as) {
if (!strncmp(serialize_as, "string", 5)) {
cur->out_type = JSON_STRING;
} else if (!strncmp(serialize_as, "number", 6)) {
cur->out_type = JSON_NUMBER;
} else if (!strncmp(serialize_as, "boolean", 7)) {
cur->out_type = JSON_BOOLEAN;
} else if (!strncmp(serialize_as, "object", 6)) {
cur->out_type = JSON_OBJECT;
} else if (!strncmp(serialize_as, "raw", 6)) {
cur->out_type = JSON_RAW;
}
}
if(as_array) {
cur->out_type_as_array = switch_true(as_array);
}
if(exclude_prefix)
cur->exclude_prefix = switch_true(exclude_prefix);
kazoo_config_filters(pool, cfg, &cur->filter);
kazoo_config_fields(definitions, pool, cfg, &cur->children);
if(cur->children != NULL
&& (cur->in_type == FIELD_STATIC)
&& (cur->out_type == JSON_NONE)
) {
cur->out_type = JSON_OBJECT;
}
if(cur->in_type == FIELD_NONE) {
cur->in_type = FIELD_COPY;
}
if(cur->out_type == JSON_NONE) {
cur->out_type = JSON_STRING;
}
if(cur->in_type == FIELD_FIRST_OF) {
cur->list.size = switch_separate_string(cur->value, '|', cur->list.value, MAX_LIST_FIELDS);
}
if(cur->in_type == FIELD_REFERENCE) {
cur->ref = (kazoo_definition_ptr)switch_core_hash_find(definitions->hash, cur->name);
if(cur->ref == NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "referenced field %s not found\n", cur->name);
}
}
*ptr = cur;
return SWITCH_STATUS_SUCCESS;
}
switch_status_t kazoo_config_fields_loop(kazoo_config_ptr definitions, switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_field_ptr *ptr)
{
switch_xml_t field;
kazoo_field_ptr root = NULL, prv = NULL;
for (field = switch_xml_child(cfg, "field"); field; field = field->next) {
kazoo_field_ptr cur = NULL;
kazoo_config_field(definitions, pool, field, &cur);
if(root == NULL) {
root = prv = cur;
} else {
prv->next = cur;
prv = cur;
}
}
*ptr = root;
return SWITCH_STATUS_SUCCESS;
}
switch_status_t kazoo_config_fields(kazoo_config_ptr definitions, switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_fields_ptr *ptr)
{
switch_xml_t fields;
kazoo_fields_ptr root = NULL;
if ((fields = switch_xml_child(cfg, "fields")) != NULL) {
const char *verbose = switch_xml_attr(fields, "verbose");
root = (kazoo_fields_ptr) switch_core_alloc(pool, sizeof(kazoo_fields));
root->verbose = SWITCH_TRUE;
if(verbose) {
root->verbose = switch_true(verbose);
}
kazoo_config_fields_loop(definitions, pool, fields, &root->head);
}
*ptr = root;
return SWITCH_STATUS_SUCCESS;
}
kazoo_config_ptr kazoo_config_event_handlers(kazoo_config_ptr definitions, switch_xml_t cfg)
{
switch_xml_t xml_profiles = NULL, xml_profile = NULL;
kazoo_config_ptr profiles = NULL;
switch_memory_pool_t *pool = NULL;
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "error creating memory pool for producers\n");
return NULL;
}
profiles = switch_core_alloc(pool, sizeof(kazoo_config));
profiles->pool = pool;
switch_core_hash_init(&profiles->hash);
if ((xml_profiles = switch_xml_child(cfg, "event-handlers"))) {
if ((xml_profile = switch_xml_child(xml_profiles, "profile"))) {
for (; xml_profile; xml_profile = xml_profile->next) {
const char *name = switch_xml_attr(xml_profile, "name");
if(name == NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing attr name\n" );
continue;
}
kazoo_config_event_handler(definitions, profiles, xml_profile, NULL);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "unable to locate a event-handler profile for kazoo\n" );
}
} else {
destroy_config(&profiles);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "unable to locate event-handlers section for kazoo, using default\n" );
}
return profiles;
}
kazoo_config_ptr kazoo_config_fetch_handlers(kazoo_config_ptr definitions, switch_xml_t cfg)
{
switch_xml_t xml_profiles = NULL, xml_profile = NULL;
kazoo_config_ptr profiles = NULL;
switch_memory_pool_t *pool = NULL;
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "error creating memory pool for producers\n");
return NULL;
}
profiles = switch_core_alloc(pool, sizeof(kazoo_config));
profiles->pool = pool;
switch_core_hash_init(&profiles->hash);
if ((xml_profiles = switch_xml_child(cfg, "fetch-handlers"))) {
if ((xml_profile = switch_xml_child(xml_profiles, "profile"))) {
for (; xml_profile; xml_profile = xml_profile->next) {
const char *name = switch_xml_attr(xml_profile, "name");
if(name == NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing attr name\n" );
continue;
}
kazoo_config_fetch_handler(definitions, profiles, xml_profile, NULL);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "unable to locate a fetch-handler profile for kazoo\n" );
}
} else {
destroy_config(&profiles);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "unable to locate fetch-handlers section for kazoo, using default\n" );
}
return profiles;
}
switch_status_t kazoo_config_definition(kazoo_config_ptr root, switch_xml_t cfg)
{
kazoo_definition_ptr definition = NULL;
char *name = (char *) switch_xml_attr_soft(cfg, "name");
if (zstr(name)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to load kazoo profile, check definition missing name attr\n");
return SWITCH_STATUS_GENERR;
}
definition = switch_core_alloc(root->pool, sizeof(kazoo_definition));
definition->name = switch_core_strdup(root->pool, name);
kazoo_config_filters(root->pool, cfg, &definition->filter);
kazoo_config_fields_loop(root, root->pool, cfg, &definition->head);
if ( switch_core_hash_insert(root->hash, name, (void *) definition) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to insert new definition [%s] into kazoo definitions hash\n", name);
return SWITCH_STATUS_GENERR;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "definition[%s] successfully configured\n", definition->name);
return SWITCH_STATUS_SUCCESS;
}
kazoo_config_ptr kazoo_config_definitions(switch_xml_t cfg)
{
switch_xml_t xml_definitions = NULL, xml_definition = NULL;
kazoo_config_ptr definitions = NULL;
switch_memory_pool_t *pool = NULL;
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "error creating memory pool for definitions\n");
return NULL;
}
definitions = switch_core_alloc(pool, sizeof(kazoo_config));
definitions->pool = pool;
switch_core_hash_init(&definitions->hash);
if ((xml_definitions = switch_xml_child(cfg, "definitions"))) {
if ((xml_definition = switch_xml_child(xml_definitions, "definition"))) {
for (; xml_definition; xml_definition = xml_definition->next) {
kazoo_config_definition(definitions, xml_definition);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "no definitions for kazoo\n" );
}
} else {
destroy_config(&definitions);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "unable to locate definitions section for kazoo, using default\n" );
}
return definitions;
}
void destroy_config(kazoo_config_ptr *ptr)
{
kazoo_config_ptr config = NULL;
switch_memory_pool_t *pool;
if (!ptr || !*ptr) {
return;
}
config = *ptr;
pool = config->pool;
switch_core_hash_destroy(&(config->hash));
switch_core_destroy_memory_pool(&pool);
*ptr = NULL;
}
/* 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
*/

View File

@ -1,63 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Based on mod_skel by
* Anthony Minessale II <anthm@freeswitch.org>
*
* Contributor(s):
*
* Daniel Bryars <danb@aeriandi.com>
* Tim Brown <tim.brown@aeriandi.com>
* Anthony Minessale II <anthm@freeswitch.org>
* William King <william.king@quentustech.com>
* Mike Jerris <mike@jerris.com>
*
* kazoo.c -- Sends FreeSWITCH events to an AMQP broker
*
*/
#ifndef KAZOO_CONFIG_H
#define KAZOO_CONFIG_H
#include <switch.h>
struct kazoo_config_t {
switch_hash_t *hash;
switch_memory_pool_t *pool;
};
switch_status_t kazoo_config_loglevels(switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_loglevels_ptr *ptr);
switch_status_t kazoo_config_filters(switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_filter_ptr *ptr);
switch_status_t kazoo_config_fields(kazoo_config_ptr definitions, switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_fields_ptr *ptr);
switch_status_t kazoo_config_event_handler(kazoo_config_ptr definitions, kazoo_config_ptr root, switch_xml_t cfg, kazoo_event_profile_ptr *ptr);
switch_status_t kazoo_config_fetch_handler(kazoo_config_ptr definitions, kazoo_config_ptr root, switch_xml_t cfg, kazoo_fetch_profile_ptr *ptr);
kazoo_config_ptr kazoo_config_event_handlers(kazoo_config_ptr definitions, switch_xml_t cfg);
kazoo_config_ptr kazoo_config_fetch_handlers(kazoo_config_ptr definitions, switch_xml_t cfg);
kazoo_config_ptr kazoo_config_definitions(switch_xml_t cfg);
switch_status_t kazoo_config_field(kazoo_config_ptr definitions, switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_field_ptr *ptr);
void destroy_config(kazoo_config_ptr *ptr);
#endif /* KAZOO_CONFIG_H */

View File

@ -1,8 +0,0 @@
.global kz_default_config
.global kz_default_config_size
.section .rodata
kz_default_config:
.incbin "kazoo.conf.xml"
1:
kz_default_config_size:
.int 1b - kz_default_config

View File

@ -1,9 +0,0 @@
#ifndef KAZOO_DEFS_H_
#define KAZOO_DEFS_H_
#define INTERACTION_VARIABLE "Call-Interaction-ID"
#define UNIX_EPOCH_IN_GREGORIAN 62167219200
#define UNIX_EPOCH_IN_GREGORIAN_STR "62167219200"
#endif /* KAZOO_DEFS_H_ */

View File

@ -1,980 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Karl Anderson <karl@2600hz.com>
* Darren Schreiber <darren@2600hz.com>
*
*
* kazoo_dptools.c -- clones of mod_dptools commands slightly modified for kazoo
*
*/
#include "mod_kazoo.h"
#define SET_SHORT_DESC "Set a channel variable"
#define SET_LONG_DESC "Set a channel variable for the channel calling the application."
#define SET_SYNTAX "<varname>=<value>"
#define MULTISET_SHORT_DESC "Set many channel variables"
#define MULTISET_LONG_DESC "Set many channel variables for the channel calling the application"
#define MULTISET_SYNTAX "[^^<delim>]<varname>=<value> <var2>=<val2>"
#define UNSET_SHORT_DESC "Unset a channel variable"
#define UNSET_LONG_DESC "Unset a channel variable for the channel calling the application."
#define UNSET_SYNTAX "<varname>"
#define MULTIUNSET_SHORT_DESC "Unset many channel variables"
#define MULTIUNSET_LONG_DESC "Unset many channel variables for the channel calling the application."
#define MULTIUNSET_SYNTAX "[^^<delim>]<varname> <var2> <var3>"
#define EXPORT_SHORT_DESC "Export many channel variables"
#define EXPORT_LONG_DESC "Export many channel variables for the channel calling the application"
#define EXPORT_SYNTAX "[^^<delim>]<varname>=<value> <var2>=<val2>"
#define PREFIX_UNSET_SHORT_DESC "clear variables by prefix"
#define PREFIX_UNSET_LONG_DESC "clears the channel variables that start with prefix supplied"
#define PREFIX_UNSET_SYNTAX "<prefix>"
#define UUID_MULTISET_SHORT_DESC "Set many channel variables"
#define UUID_MULTISET_LONG_DESC "Set many channel variables for a specific channel"
#define UUID_MULTISET_SYNTAX "<uuid> [^^<delim>]<varname>=<value> <var2>=<val2>"
#define KZ_ENDLESS_PLAYBACK_SHORT_DESC "Playback File Endlessly until break"
#define KZ_ENDLESS_PLAYBACK_LONG_DESC "Endlessly Playback a file to the channel until a break occurs"
#define KZ_ENDLESS_PLAYBACK_SYNTAX "<path>"
#define NOOP_SHORT_DESC "no operation"
#define NOOP_LONG_DESC "no operation. serves as a control point"
#define NOOP_SYNTAX "[<noop-id>]"
static void base_set (switch_core_session_t *session, const char *data, int urldecode, switch_stack_t stack)
{
char *var, *val = NULL;
if (zstr(data)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No variable name specified.\n");
} else {
switch_channel_t *channel = switch_core_session_get_channel(session);
char *expanded = NULL;
var = switch_core_session_strdup(session, data);
if (!(val = strchr(var, '='))) {
val = strchr(var, ',');
}
if (val) {
*val++ = '\0';
if (zstr(val)) {
val = NULL;
}
}
if (val) {
if(urldecode) {
switch_url_decode(val);
}
expanded = switch_channel_expand_variables(channel, val);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SET [%s]=[%s] => [%s]\n", switch_channel_get_name(channel), var, val,
expanded ? expanded : "UNDEF");
switch_channel_add_variable_var_check(channel, var, expanded, SWITCH_FALSE, stack);
kz_check_set_profile_var(channel, var, expanded);
if (expanded && expanded != val) {
switch_safe_free(expanded);
}
}
}
static int kz_is_exported(switch_core_session_t *session, char *varname)
{
char *array[256] = {0};
int i, argc;
switch_channel_t *channel = switch_core_session_get_channel(session);
const char *exports = switch_channel_get_variable(channel, SWITCH_EXPORT_VARS_VARIABLE);
char *arg = switch_core_session_strdup(session, exports);
argc = switch_split(arg, ',', array);
for(i=0; i < argc; i++) {
if(!strcasecmp(array[i], varname))
return 1;
}
return 0;
}
static void base_export (switch_core_session_t *session, const char *data, int urldecode, switch_stack_t stack)
{
char *var, *val = NULL;
if (zstr(data)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No variable name specified.\n");
} else {
switch_channel_t *channel = switch_core_session_get_channel(session);
char *expanded = NULL;
var = switch_core_session_strdup(session, data);
if (!(val = strchr(var, '='))) {
val = strchr(var, ',');
}
if (val) {
*val++ = '\0';
if (zstr(val)) {
val = NULL;
}
}
if (val) {
if(urldecode) {
switch_url_decode(val);
}
expanded = switch_channel_expand_variables(channel, val);
if(!kz_is_exported(session, var)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s EXPORT [%s]=[%s]\n", switch_channel_get_name(channel), var, expanded ? expanded : "UNDEF");
switch_channel_export_variable_var_check(channel, var, expanded, SWITCH_EXPORT_VARS_VARIABLE, SWITCH_FALSE);
} else {
if(strcmp(switch_str_nil(switch_channel_get_variable_dup(channel, var, SWITCH_FALSE, -1)), expanded)) {
switch_channel_set_variable(channel, var, expanded);
}
}
if (expanded && expanded != val) {
switch_safe_free(expanded);
}
}
}
}
SWITCH_STANDARD_APP(prefix_unset_function)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_event_header_t *ei = NULL;
switch_event_t *clear;
char *arg = (char *) data;
if(switch_event_create(&clear, SWITCH_EVENT_CLONE) != SWITCH_STATUS_SUCCESS) {
return;
}
for (ei = switch_channel_variable_first(channel); ei; ei = ei->next) {
const char *name = ei->name;
char *value = ei->value;
if (!strncasecmp(name, arg, strlen(arg))) {
switch_event_add_header_string(clear, SWITCH_STACK_BOTTOM, name, value);
}
}
switch_channel_variable_last(channel);
for (ei = clear->headers; ei; ei = ei->next) {
char *varname = ei->name;
switch_channel_set_variable(channel, varname, NULL);
}
switch_event_destroy(&clear);
}
void kz_multiset(switch_core_session_t *session, const char* data, int urldecode)
{
char delim = ' ';
char *arg = (char *) data;
switch_event_t *event;
if (!zstr(arg) && *arg == '^' && *(arg+1) == '^') {
arg += 2;
delim = *arg++;
}
if(delim != '\0') {
switch_channel_t *channel = switch_core_session_get_channel(session);
if (arg) {
char *array[256] = {0};
int i, argc;
arg = switch_core_session_strdup(session, arg);
argc = switch_split(arg, delim, array);
for(i = 0; i < argc; i++) {
base_set(session, array[i], urldecode, SWITCH_STACK_BOTTOM);
}
}
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
switch_event_fire(&event);
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "multiset with empty args\n");
}
}
SWITCH_STANDARD_APP(multiset_function)
{
kz_multiset(session, data, 0);
}
SWITCH_STANDARD_APP(multiset_encoded_function)
{
kz_multiset(session, data, 1);
}
void kz_uuid_multiset(switch_core_session_t *session, const char* data, int urldecode)
{
char delim = ' ';
char *arg0 = (char *) data;
char *arg = strchr(arg0, ' ');
switch_event_t *event;
if(arg == NULL) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "uuid_multiset with invalid args\n");
return;
}
*arg = '\0';
arg++;
if(zstr(arg0)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "uuid_multiset with invalid uuid\n");
return;
}
if (!zstr(arg) && *arg == '^' && *(arg+1) == '^') {
arg += 2;
delim = *arg++;
}
if(delim != '\0') {
switch_core_session_t *uuid_session = NULL;
if ((uuid_session = switch_core_session_locate(arg0)) != NULL) {
switch_channel_t *uuid_channel = switch_core_session_get_channel(uuid_session);
if (arg) {
char *array[256] = {0};
int i, argc;
arg = switch_core_session_strdup(session, arg);
argc = switch_split(arg, delim, array);
for(i = 0; i < argc; i++) {
base_set(uuid_session, array[i], urldecode, SWITCH_STACK_BOTTOM);
}
}
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(uuid_channel, event);
switch_event_fire(&event);
}
switch_core_session_rwunlock(uuid_session);
} else {
base_set(session, data, urldecode, SWITCH_STACK_BOTTOM);
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "multiset with empty args\n");
}
}
SWITCH_STANDARD_APP(uuid_multiset_function)
{
kz_uuid_multiset(session, data, 0);
}
SWITCH_STANDARD_APP(uuid_multiset_encoded_function)
{
kz_uuid_multiset(session, data, 1);
}
void kz_set(switch_core_session_t *session, const char* data, int urldecode) {
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_event_t *event;
base_set(session, data, urldecode, SWITCH_STACK_BOTTOM);
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
switch_event_fire(&event);
}
}
SWITCH_STANDARD_APP(set_function)
{
kz_set(session, data, 0);
}
SWITCH_STANDARD_APP(set_encoded_function)
{
kz_set(session, data, 1);
}
SWITCH_STANDARD_APP(unset_function) {
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_event_t *event;
if (zstr(data)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No variable name specified.\n");
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "UNSET [%s]\n", (char *) data);
switch_channel_set_variable(switch_core_session_get_channel(session), data, NULL);
}
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
switch_event_fire(&event);
}
}
SWITCH_STANDARD_APP(multiunset_function) {
char delim = ' ';
char *arg = (char *) data;
if (!zstr(arg) && *arg == '^' && *(arg+1) == '^') {
arg += 2;
delim = *arg++;
}
if(delim != '\0') {
if (arg) {
char *array[256] = {0};
int i, argc;
arg = switch_core_session_strdup(session, arg);
argc = switch_split(arg, delim, array);
for(i = 0; i < argc; i++) {
switch_channel_set_variable(switch_core_session_get_channel(session), array[i], NULL);
}
} else {
switch_channel_set_variable(switch_core_session_get_channel(session), arg, NULL);
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "multiunset with empty args\n");
}
}
void kz_export(switch_core_session_t *session, const char* data, int urldecode)
{
char delim = ' ';
char *arg = (char *) data;
if (!zstr(arg) && *arg == '^' && *(arg+1) == '^') {
arg += 2;
delim = *arg++;
}
if(delim != '\0') {
if (arg) {
char *array[256] = {0};
int i, argc;
arg = switch_core_session_strdup(session, arg);
argc = switch_split(arg, delim, array);
for(i = 0; i < argc; i++) {
base_export(session, array[i], urldecode, SWITCH_STACK_BOTTOM);
}
} else {
base_export(session, data, urldecode, SWITCH_STACK_BOTTOM);
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "export with empty args\n");
}
}
SWITCH_STANDARD_APP(export_function)
{
kz_export(session, data, 0);
}
SWITCH_STANDARD_APP(export_encoded_function)
{
kz_export(session, data, 1);
}
// copied from mod_dptools with allow SWITCH_STATUS_BREAK
SWITCH_STANDARD_APP(kz_endless_playback_function)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_status_t status = SWITCH_STATUS_SUCCESS;
const char *file = data;
while (switch_channel_ready(channel)) {
status = switch_ivr_play_file(session, NULL, file, NULL);
if (status != SWITCH_STATUS_SUCCESS) {
break;
}
}
switch (status) {
case SWITCH_STATUS_SUCCESS:
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "FILE PLAYED");
break;
case SWITCH_STATUS_BREAK:
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "PLAYBACK_INTERRUPTED");
break;
case SWITCH_STATUS_NOTFOUND:
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "FILE NOT FOUND");
break;
default:
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "PLAYBACK ERROR");
break;
}
}
SWITCH_STANDARD_APP(kz_moh_function)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_file_handle_t fh = { 0 };
const char *var_samples = switch_channel_get_variable_dup(channel, "moh_playback_samples", SWITCH_FALSE, -1);
unsigned int samples = 0;
char * my_data = NULL;
if (var_samples) {
fh.samples = samples = atoi(var_samples);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "SETTING SAMPLES %d\n", samples);
}
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "");
/*
* hack for proper position
*/
if (!strncmp(data, "http_cache://", 13) && session) {
switch_channel_t *channel = switch_core_session_get_channel(session);
char * resolve = switch_mprintf("${http_get({prefetch=true}%s)}", data+13);
my_data = switch_channel_expand_variables_check(channel, resolve, NULL, NULL, 0);
} else {
my_data = strdup(data);
}
status = switch_ivr_play_file(session, &fh, my_data, NULL);
// status = switch_ivr_play_file(session, &fh, data, NULL);
switch_assert(!(fh.flags & SWITCH_FILE_OPEN));
switch (status) {
case SWITCH_STATUS_SUCCESS:
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "MOH PLAYED SUCCESS\n");
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "MOH FILE PLAYED");
switch_channel_set_variable(channel, "moh_playback_samples", "0");
break;
case SWITCH_STATUS_BREAK:
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "MOH PLAYED BREAK\n");
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "MOH FILE PLAYED");
if ((var_samples = switch_channel_get_variable_dup(channel, "playback_samples", SWITCH_FALSE, -1)) != NULL) {
samples += atoi(var_samples);
if (samples >= fh.samples) {
samples = 0;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "SETTING MOH SAMPLES %d\n", samples);
switch_channel_set_variable_printf(channel, "moh_playback_samples", "%d", samples);
}
break;
case SWITCH_STATUS_NOTFOUND:
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "MOH PLAYED NOT FOUND\n");
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "MOH FILE NOT FOUND");
break;
default:
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "MOH PLAYED DEFAULT\n");
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "MOH PLAYBACK ERROR");
break;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "MOH duration %" SWITCH_INT64_T_FMT "\n", fh.duration);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "MOH offset_pos %d\n", fh.offset_pos);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "MOH pos %" SWITCH_INT64_T_FMT "\n", fh.pos);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "MOH sample_count %" SWITCH_SIZE_T_FMT "\n", fh.sample_count);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "MOH samples %d\n", fh.samples);
switch_safe_free(my_data);
}
SWITCH_STANDARD_APP(noop_function)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
const char *response = uuid_str;
if (zstr(data)) {
switch_uuid_str(uuid_str, sizeof(uuid_str));
} else {
response = data;
}
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, response);
}
SWITCH_STANDARD_APP(kz_restore_caller_id_function)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_caller_profile_t *cp = switch_channel_get_caller_profile(channel);
cp->caller_id_name = cp->orig_caller_id_name;
cp->caller_id_number = cp->orig_caller_id_number;
}
SWITCH_STANDARD_APP(kz_audio_bridge_function)
{
switch_channel_t *caller_channel = switch_core_session_get_channel(session);
switch_core_session_t *peer_session = NULL;
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
switch_status_t status = SWITCH_STATUS_FALSE;
if (zstr(data)) {
return;
}
status = switch_ivr_originate(session, &peer_session, &cause, data, 0, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL);
if (status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Originate Failed. Cause: %s\n", switch_channel_cause2str(cause));
switch_channel_set_variable(caller_channel, "originate_failed_cause", switch_channel_cause2str(cause));
switch_channel_set_variable(caller_channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, switch_channel_cause2str(cause));
switch_channel_handle_cause(caller_channel, cause);
return;
} else {
const char* uuid = switch_core_session_get_uuid(session);
const char* peer_uuid = switch_core_session_get_uuid(peer_session);
switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
if (switch_true(switch_channel_get_variable(caller_channel, SWITCH_BYPASS_MEDIA_AFTER_BRIDGE_VARIABLE)) ||
switch_true(switch_channel_get_variable(peer_channel, SWITCH_BYPASS_MEDIA_AFTER_BRIDGE_VARIABLE))) {
switch_channel_set_flag(caller_channel, CF_BYPASS_MEDIA_AFTER_BRIDGE);
}
while(1) {
const char *xfer_uuid;
switch_channel_state_t a_state , a_running_state;
switch_channel_state_t b_state , b_running_state;
status = switch_ivr_multi_threaded_bridge(session, peer_session, NULL, NULL, NULL);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "BRIDGE RESULT %i\n", status);
if(status != 0) {
break;
}
a_state = switch_channel_get_state(caller_channel);
a_running_state = switch_channel_get_running_state(caller_channel);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "A STATE %s %s => %s , %s\n", switch_channel_state_name(a_running_state), switch_channel_state_name(a_state), uuid, peer_uuid);
if(a_state >= CS_HANGUP) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "A HANGUP = %s , %s\n", uuid, peer_uuid);
break;
}
b_state = switch_channel_get_state(peer_channel);
b_running_state = switch_channel_get_running_state(peer_channel);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "B STATE %s %s => %s , %s\n", switch_channel_state_name(b_running_state), switch_channel_state_name(b_state), uuid, peer_uuid);
if(b_state >= CS_HANGUP) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "B HANGUP = %s , %s\n", uuid, peer_uuid);
switch_channel_set_variable(caller_channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, switch_channel_cause2str(switch_channel_get_cause(peer_channel)));
break;
}
if(!(xfer_uuid=switch_channel_get_variable(caller_channel, "att_xfer_peer_uuid"))) {
if(!(xfer_uuid=switch_channel_get_variable(peer_channel, "att_xfer_peer_uuid"))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "XFER UUID NULL\n");
break;
}
}
switch_channel_set_variable(caller_channel, "att_xfer_peer_uuid", NULL);
switch_channel_set_variable(peer_channel, "att_xfer_peer_uuid", NULL);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "WAIT 1\n");
switch_channel_clear_flag(peer_channel, CF_UUID_BRIDGE_ORIGINATOR);
switch_channel_set_state(peer_channel, CS_RESET);
switch_channel_wait_for_state(peer_channel, NULL, CS_RESET);
switch_channel_clear_state_handler(peer_channel, NULL);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "WAIT 3\n");
switch_channel_set_flag(caller_channel, CF_UUID_BRIDGE_ORIGINATOR);
switch_channel_clear_flag(caller_channel, CF_TRANSFER);
switch_channel_clear_flag(caller_channel, CF_REDIRECT);
switch_channel_set_flag(peer_channel, CF_UUID_BRIDGE_ORIGINATOR);
switch_channel_clear_flag(peer_channel, CF_TRANSFER);
switch_channel_clear_flag(peer_channel, CF_REDIRECT);
if(!switch_channel_media_up(caller_channel)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "A MEDIA DOWN HANGUP = %s, %s , %s\n", xfer_uuid, uuid, peer_uuid);
}
if(!switch_channel_media_up(peer_channel)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "B MEDIA DOWN HANGUP = %s, %s , %s\n", xfer_uuid, uuid, peer_uuid);
}
switch_channel_set_state(caller_channel, CS_EXECUTE);
switch_channel_set_state(peer_channel, CS_EXECUTE);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "XFER LOOP %s %s , %s\n", xfer_uuid, uuid, peer_uuid);
}
if (peer_session) {
switch_core_session_rwunlock(peer_session);
}
}
}
SWITCH_STANDARD_APP(kz_audio_bridge_uuid_function)
{
switch_core_session_t *peer_session = NULL;
const char * peer_uuid = NULL;
if (zstr(data)) {
return;
}
peer_uuid = switch_core_session_strdup(session, data);
if (peer_uuid && (peer_session = switch_core_session_locate(peer_uuid))) {
switch_ivr_multi_threaded_bridge(session, peer_session, NULL, NULL, NULL);
}
if (peer_session) {
switch_core_session_rwunlock(peer_session);
}
}
struct kz_att_keys {
const char *attxfer_cancel_key;
const char *attxfer_hangup_key;
const char *attxfer_conf_key;
};
static switch_status_t kz_att_xfer_on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
{
switch_core_session_t *peer_session = (switch_core_session_t *) buf;
if (!buf || !peer_session) {
return SWITCH_STATUS_SUCCESS;
}
switch (itype) {
case SWITCH_INPUT_TYPE_DTMF:
{
switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
struct kz_att_keys *keys = switch_channel_get_private(channel, "__kz_keys");
if (dtmf->digit == *keys->attxfer_hangup_key) {
switch_channel_hangup(channel, SWITCH_CAUSE_ATTENDED_TRANSFER);
return SWITCH_STATUS_FALSE;
}
if (dtmf->digit == *keys->attxfer_cancel_key) {
switch_channel_hangup(peer_channel, SWITCH_CAUSE_NORMAL_CLEARING);
return SWITCH_STATUS_FALSE;
}
if (dtmf->digit == *keys->attxfer_conf_key) {
switch_caller_extension_t *extension = NULL;
const char *app = "three_way";
const char *app_arg = switch_core_session_get_uuid(session);
const char *holding = switch_channel_get_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE);
switch_core_session_t *b_session;
if (holding && (b_session = switch_core_session_locate(holding))) {
switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
if (!switch_channel_ready(b_channel)) {
app = "intercept";
}
switch_core_session_rwunlock(b_session);
}
if ((extension = switch_caller_extension_new(peer_session, app, app_arg)) == 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n");
abort();
}
switch_caller_extension_add_application(peer_session, extension, app, app_arg);
switch_channel_set_caller_extension(peer_channel, extension);
switch_channel_set_state(peer_channel, CS_RESET);
switch_channel_wait_for_state(peer_channel, channel, CS_RESET);
switch_channel_set_state(peer_channel, CS_EXECUTE);
switch_channel_set_variable(channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, NULL);
return SWITCH_STATUS_FALSE;
}
}
break;
default:
break;
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t kz_att_xfer_tmp_hanguphook(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_channel_state_t state = switch_channel_get_state(channel);
if (state == CS_HANGUP || state == CS_ROUTING) {
const char *bond = switch_channel_get_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE);
if (!zstr(bond)) {
switch_core_session_t *b_session;
if ((b_session = switch_core_session_locate(bond))) {
switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
if (switch_channel_up(b_channel)) {
switch_channel_set_flag(b_channel, CF_REDIRECT);
}
switch_core_session_rwunlock(b_session);
}
}
switch_core_event_hook_remove_state_change(session, kz_att_xfer_tmp_hanguphook);
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t kz_att_xfer_hanguphook(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_channel_state_t state = switch_channel_get_state(channel);
const char *id = NULL;
const char *peer_uuid = NULL;
if (state == CS_HANGUP || state == CS_ROUTING) {
if ((id = switch_channel_get_variable(channel, "xfer_uuids"))) {
switch_stream_handle_t stream = { 0 };
SWITCH_STANDARD_STREAM(stream);
if ((peer_uuid = switch_channel_get_variable(channel, "xfer_peer_uuid"))) {
switch_core_session_t *peer_session = NULL;
if ((peer_session = switch_core_session_locate(peer_uuid)) != NULL ) {
switch_ivr_transfer_recordings(session, peer_session);
switch_core_session_rwunlock(peer_session);
}
}
switch_api_execute("uuid_bridge", id, NULL, &stream);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "\nHangup Command uuid_bridge(%s):\n%s\n", id,
switch_str_nil((char *) stream.data));
switch_safe_free(stream.data);
}
switch_core_event_hook_remove_state_change(session, kz_att_xfer_hanguphook);
}
return SWITCH_STATUS_SUCCESS;
}
static void kz_att_xfer_set_result(switch_channel_t *channel, switch_status_t status)
{
switch_channel_set_variable(channel, SWITCH_ATT_XFER_RESULT_VARIABLE, status == SWITCH_STATUS_SUCCESS ? "success" : "failure");
}
struct kz_att_obj {
switch_core_session_t *session;
const char *data;
int running;
};
void *SWITCH_THREAD_FUNC kz_att_thread_run(switch_thread_t *thread, void *obj)
{
struct kz_att_obj *att = (struct kz_att_obj *) obj;
struct kz_att_keys *keys = NULL;
switch_core_session_t *session = att->session;
switch_core_session_t *peer_session = NULL;
const char *data = att->data;
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
switch_channel_t *channel = switch_core_session_get_channel(session), *peer_channel = NULL;
const char *bond = NULL;
switch_bool_t follow_recording = switch_true(switch_channel_get_variable(channel, "recording_follow_attxfer"));
const char *attxfer_cancel_key = NULL, *attxfer_hangup_key = NULL, *attxfer_conf_key = NULL;
int br = 0;
switch_event_t *event = NULL;
switch_core_session_t *b_session = NULL;
switch_channel_t *b_channel = NULL;
att->running = 1;
if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) {
return NULL;
}
bond = switch_channel_get_partner_uuid(channel);
if ((b_session = switch_core_session_locate(bond)) == NULL) {
switch_core_session_rwunlock(session);
return NULL;
}
switch_channel_set_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE, bond);
switch_core_event_hook_add_state_change(session, kz_att_xfer_tmp_hanguphook);
if (switch_ivr_originate(session, &peer_session, &cause, data, 0, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL)
!= SWITCH_STATUS_SUCCESS || !peer_session) {
switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, bond);
goto end;
}
peer_channel = switch_core_session_get_channel(peer_session);
switch_channel_set_flag(peer_channel, CF_INNER_BRIDGE);
switch_channel_set_flag(channel, CF_INNER_BRIDGE);
if (!(attxfer_cancel_key = switch_channel_get_variable(channel, "attxfer_cancel_key"))) {
if (!(attxfer_cancel_key = switch_channel_get_variable(peer_channel, "attxfer_cancel_key"))) {
attxfer_cancel_key = "#";
}
}
if (!(attxfer_hangup_key = switch_channel_get_variable(channel, "attxfer_hangup_key"))) {
if (!(attxfer_hangup_key = switch_channel_get_variable(peer_channel, "attxfer_hangup_key"))) {
attxfer_hangup_key = "*";
}
}
if (!(attxfer_conf_key = switch_channel_get_variable(channel, "attxfer_conf_key"))) {
if (!(attxfer_conf_key = switch_channel_get_variable(peer_channel, "attxfer_conf_key"))) {
attxfer_conf_key = "0";
}
}
keys = switch_core_session_alloc(session, sizeof(*keys));
keys->attxfer_cancel_key = switch_core_session_strdup(session, attxfer_cancel_key);
keys->attxfer_hangup_key = switch_core_session_strdup(session, attxfer_hangup_key);
keys->attxfer_conf_key = switch_core_session_strdup(session, attxfer_conf_key);
switch_channel_set_private(channel, "__kz_keys", keys);
switch_channel_set_variable(channel, "att_xfer_peer_uuid", switch_core_session_get_uuid(peer_session));
switch_ivr_multi_threaded_bridge(session, peer_session, kz_att_xfer_on_dtmf, peer_session, NULL);
switch_channel_clear_flag(peer_channel, CF_INNER_BRIDGE);
switch_channel_clear_flag(channel, CF_INNER_BRIDGE);
if (switch_channel_down(peer_channel)) {
switch_core_session_rwunlock(peer_session);
switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, bond);
goto end;
}
/*
* we're emiting the transferee event so that callctl can update
*/
b_channel = switch_core_session_get_channel(b_session);
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, "sofia::transferee") == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(b_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_replaced_call_id", switch_core_session_get_uuid(peer_session));
switch_event_fire(&event);
}
if (!switch_channel_ready(channel)) {
switch_status_t status;
if (follow_recording) {
switch_ivr_transfer_recordings(session, peer_session);
}
status = switch_ivr_uuid_bridge(switch_core_session_get_uuid(peer_session), bond);
kz_att_xfer_set_result(peer_channel, status);
br++;
} else {
// switch_channel_set_variable_printf(b_channel, "xfer_uuids", "%s %s", switch_core_session_get_uuid(peer_session), switch_core_session_get_uuid(session));
switch_channel_set_variable_printf(channel, "xfer_uuids", "%s %s", switch_core_session_get_uuid(peer_session), bond);
switch_channel_set_variable(channel, "xfer_peer_uuid", switch_core_session_get_uuid(peer_session));
switch_core_event_hook_add_state_change(session, kz_att_xfer_hanguphook);
// switch_core_event_hook_add_state_change(b_session, kz_att_xfer_hanguphook);
}
/*
* this was commented so that the existing bridge
* doesn't end
*
if (!br) {
switch_status_t status = switch_ivr_uuid_bridge(switch_core_session_get_uuid(session), bond);
att_xfer_set_result(channel, status);
}
*/
switch_core_session_rwunlock(peer_session);
end:
switch_core_event_hook_remove_state_change(session, kz_att_xfer_tmp_hanguphook);
switch_channel_set_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE, NULL);
switch_channel_clear_flag(channel, CF_XFER_ZOMBIE);
switch_core_session_rwunlock(b_session);
switch_core_session_rwunlock(session);
att->running = 0;
return NULL;
}
SWITCH_STANDARD_APP(kz_att_xfer_function)
{
switch_thread_t *thread;
switch_threadattr_t *thd_attr = NULL;
switch_memory_pool_t *pool = switch_core_session_get_pool(session);
struct kz_att_obj *att;
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_threadattr_create(&thd_attr, pool);
switch_threadattr_detach_set(thd_attr, 1);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
switch_threadattr_detach_set(thd_attr, 1);
att = switch_core_session_alloc(session, sizeof(*att));
att->running = -1;
att->session = session;
att->data = switch_core_session_strdup(session, data);
switch_thread_create(&thread, thd_attr, kz_att_thread_run, att, pool);
while(att->running && switch_channel_up(channel)) {
switch_yield(100000);
}
}
void add_kz_dptools(switch_loadable_module_interface_t **module_interface) {
switch_application_interface_t *app_interface = NULL;
SWITCH_ADD_APP(app_interface, "kz_set", SET_SHORT_DESC, SET_LONG_DESC, set_function, SET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
SWITCH_ADD_APP(app_interface, "kz_set_encoded", SET_SHORT_DESC, SET_LONG_DESC, set_encoded_function, SET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
SWITCH_ADD_APP(app_interface, "kz_multiset", MULTISET_SHORT_DESC, MULTISET_LONG_DESC, multiset_function, MULTISET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
SWITCH_ADD_APP(app_interface, "kz_multiset_encoded", MULTISET_SHORT_DESC, MULTISET_LONG_DESC, multiset_encoded_function, MULTISET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
SWITCH_ADD_APP(app_interface, "kz_unset", UNSET_SHORT_DESC, UNSET_LONG_DESC, unset_function, UNSET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
SWITCH_ADD_APP(app_interface, "kz_multiunset", MULTISET_SHORT_DESC, MULTISET_LONG_DESC, multiunset_function, MULTIUNSET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
SWITCH_ADD_APP(app_interface, "kz_export", EXPORT_SHORT_DESC, EXPORT_LONG_DESC, export_function, EXPORT_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
SWITCH_ADD_APP(app_interface, "kz_export_encoded", EXPORT_SHORT_DESC, EXPORT_LONG_DESC, export_encoded_function, EXPORT_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
SWITCH_ADD_APP(app_interface, "kz_prefix_unset", PREFIX_UNSET_SHORT_DESC, PREFIX_UNSET_LONG_DESC, prefix_unset_function, PREFIX_UNSET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
SWITCH_ADD_APP(app_interface, "kz_uuid_multiset", UUID_MULTISET_SHORT_DESC, UUID_MULTISET_LONG_DESC, uuid_multiset_function, UUID_MULTISET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
SWITCH_ADD_APP(app_interface, "kz_uuid_multiset_encoded", UUID_MULTISET_SHORT_DESC, UUID_MULTISET_LONG_DESC, uuid_multiset_encoded_function, UUID_MULTISET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
SWITCH_ADD_APP(app_interface, "kz_endless_playback", KZ_ENDLESS_PLAYBACK_SHORT_DESC, KZ_ENDLESS_PLAYBACK_LONG_DESC, kz_endless_playback_function, KZ_ENDLESS_PLAYBACK_SYNTAX, SAF_NONE);
SWITCH_ADD_APP(app_interface, "kz_restore_caller_id", NOOP_SHORT_DESC, NOOP_LONG_DESC, kz_restore_caller_id_function, NOOP_SYNTAX, SAF_NONE);
SWITCH_ADD_APP(app_interface, "noop", NOOP_SHORT_DESC, NOOP_LONG_DESC, noop_function, NOOP_SYNTAX, SAF_NONE);
SWITCH_ADD_APP(app_interface, "kz_bridge", "Bridge Audio", "Bridge the audio between two sessions", kz_audio_bridge_function, "<channel_url>", SAF_SUPPORT_NOMEDIA|SAF_SUPPORT_TEXT_ONLY);
SWITCH_ADD_APP(app_interface, "kz_bridge_uuid", "Bridge Audio", "Bridge the audio between two sessions", kz_audio_bridge_uuid_function, "<channel_url>", SAF_SUPPORT_NOMEDIA|SAF_SUPPORT_TEXT_ONLY);
SWITCH_ADD_APP(app_interface, "kz_att_xfer", "Attended Transfer", "Attended Transfer", kz_att_xfer_function, "<channel_url>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "kz_moh", "Kazoo MOH Playback", "Kazoo MOH Playback", kz_moh_function, "", SAF_NONE);
}

View File

@ -1,295 +0,0 @@
#ifndef KAZOO_EI_H
#define KAZOO_EI_H
#include <switch.h>
#include <ei.h>
#define MODNAME "mod_kazoo"
#define BUNDLE "community"
#define RELEASE "v1.5.0-1"
#define VERSION "mod_kazoo v1.5.0-1 community"
#define KZ_MAX_SEPARATE_STRINGS 10
#define HOSTNAME_MAX 1024
#define NODENAME_MAX 1024
typedef enum {KAZOO_FETCH_PROFILE, KAZOO_EVENT_PROFILE} kazoo_profile_type;
typedef enum {ERLANG_TUPLE, ERLANG_MAP} kazoo_json_term;
typedef struct ei_xml_agent_s ei_xml_agent_t;
typedef ei_xml_agent_t *ei_xml_agent_ptr;
typedef struct kazoo_event kazoo_event_t;
typedef kazoo_event_t *kazoo_event_ptr;
typedef struct kazoo_event_profile kazoo_event_profile_t;
typedef kazoo_event_profile_t *kazoo_event_profile_ptr;
typedef struct kazoo_fetch_profile kazoo_fetch_profile_t;
typedef kazoo_fetch_profile_t *kazoo_fetch_profile_ptr;
typedef struct kazoo_config_t kazoo_config;
typedef kazoo_config *kazoo_config_ptr;
#include "kazoo_fields.h"
#include "kazoo_config.h"
struct ei_send_msg_s {
ei_x_buff buf;
erlang_pid pid;
};
typedef struct ei_send_msg_s ei_send_msg_t;
struct ei_received_msg_s {
ei_x_buff buf;
erlang_msg msg;
};
typedef struct ei_received_msg_s ei_received_msg_t;
typedef struct ei_event_stream_s ei_event_stream_t;
typedef struct ei_node_s ei_node_t;
struct ei_event_binding_s {
char id[SWITCH_UUID_FORMATTED_LENGTH + 1];
switch_event_node_t *node;
switch_event_types_t type;
const char *subclass_name;
ei_event_stream_t* stream;
kazoo_event_ptr event;
struct ei_event_binding_s *next;
};
typedef struct ei_event_binding_s ei_event_binding_t;
struct ei_event_stream_s {
switch_memory_pool_t *pool;
ei_event_binding_t *bindings;
switch_queue_t *queue;
switch_socket_t *acceptor;
switch_pollset_t *pollset;
switch_pollfd_t *pollfd;
switch_socket_t *socket;
switch_mutex_t *socket_mutex;
switch_bool_t connected;
switch_time_t connected_time;
char remote_ip[48];
uint16_t remote_port;
char local_ip[48];
uint16_t local_port;
erlang_pid pid;
uint32_t flags;
ei_node_t *node;
short event_stream_framing;
short event_stream_keepalive;
switch_interval_time_t queue_timeout;
struct ei_event_stream_s *next;
};
struct ei_node_s {
int nodefd;
switch_atomic_t pending_bgapi;
switch_atomic_t receive_handlers;
switch_memory_pool_t *pool;
ei_event_stream_t *event_streams;
switch_mutex_t *event_streams_mutex;
switch_queue_t *send_msgs;
switch_queue_t *received_msgs;
char *peer_nodename;
switch_time_t created_time;
switch_socket_t *socket;
char remote_ip[48];
uint16_t remote_port;
char local_ip[48];
uint16_t local_port;
uint32_t flags;
int legacy;
short event_stream_framing;
short event_stream_keepalive;
switch_interval_time_t event_stream_queue_timeout;
switch_interval_time_t receiver_queue_timeout;
switch_interval_time_t sender_queue_timeout;
struct ei_node_s *next;
};
struct xml_fetch_reply_s {
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
char *xml_str;
struct xml_fetch_reply_s *next;
};
typedef struct xml_fetch_reply_s xml_fetch_reply_t;
struct fetch_handler_s {
erlang_pid pid;
struct fetch_handler_s *next;
};
typedef struct fetch_handler_s fetch_handler_t;
struct ei_xml_client_s {
ei_node_t *ei_node;
fetch_handler_t *fetch_handlers;
struct ei_xml_client_s *next;
};
typedef struct ei_xml_client_s ei_xml_client_t;
struct ei_xml_agent_s {
switch_memory_pool_t *pool;
switch_xml_section_t section;
switch_thread_rwlock_t *lock;
ei_xml_client_t *clients;
switch_mutex_t *current_client_mutex;
ei_xml_client_t *current_client;
switch_mutex_t *replies_mutex;
switch_thread_cond_t *new_reply;
xml_fetch_reply_t *replies;
kazoo_fetch_profile_ptr profile;
};
struct kz_globals_s {
switch_memory_pool_t *pool;
switch_atomic_t threads;
switch_socket_t *acceptor;
struct ei_cnode_s ei_cnode;
switch_thread_rwlock_t *ei_nodes_lock;
ei_node_t *ei_nodes;
switch_xml_binding_t *config_fetch_binding;
switch_xml_binding_t *directory_fetch_binding;
switch_xml_binding_t *dialplan_fetch_binding;
switch_xml_binding_t *channels_fetch_binding;
switch_xml_binding_t *languages_fetch_binding;
switch_xml_binding_t *chatplan_fetch_binding;
switch_hash_t *event_filter;
int epmdfd;
int node_worker_threads;
switch_bool_t nat_map;
switch_bool_t ei_shortname;
int ei_compat_rel;
char *ip;
char *hostname;
struct hostent* hostname_ent;
char *ei_cookie;
char *ei_nodename;
uint32_t flags;
int send_all_headers;
int send_all_private_headers;
int connection_timeout;
int ei_receive_timeout;
switch_interval_time_t node_sender_queue_timeout;
switch_interval_time_t node_receiver_queue_timeout;
int receive_msg_preallocate;
int event_stream_preallocate;
int send_msg_batch;
short event_stream_framing;
short event_stream_keepalive;
switch_interval_time_t event_stream_queue_timeout;
switch_port_t port;
int config_fetched;
int io_fault_tolerance;
switch_interval_time_t io_fault_tolerance_sleep;
kazoo_event_profile_ptr events;
kazoo_config_ptr definitions;
kazoo_config_ptr event_handlers;
kazoo_config_ptr fetch_handlers;
kazoo_json_term json_encoding;
char **profile_vars_prefixes;
char **kazoo_var_prefixes;
int legacy_events;
uint8_t tweaks[KZ_TWEAK_MAX];
switch_bool_t expand_headers_on_fetch;
switch_interval_time_t delay_before_initial_fetch;
};
typedef struct kz_globals_s kz_globals_t;
extern kz_globals_t kazoo_globals;
/* kazoo_event_stream.c */
ei_event_stream_t *find_event_stream(ei_event_stream_t *event_streams, const erlang_pid *from);
//ei_event_stream_t *new_event_stream(ei_event_stream_t **event_streams, const erlang_pid *from);
ei_event_stream_t *new_event_stream(ei_node_t *ei_node, const erlang_pid *from);
switch_status_t remove_event_stream(ei_event_stream_t **event_streams, const erlang_pid *from);
switch_status_t remove_event_streams(ei_event_stream_t **event_streams);
unsigned long get_stream_port(const ei_event_stream_t *event_stream);
switch_status_t add_event_binding(ei_event_stream_t *event_stream, const char *event_name);
//switch_status_t add_event_binding(ei_event_stream_t *event_stream, const switch_event_types_t event_type, const char *subclass_name);
switch_status_t remove_event_binding(ei_event_stream_t *event_stream, const switch_event_types_t event_type, const char *subclass_name);
switch_status_t remove_event_bindings(ei_event_stream_t *event_stream);
/* kazoo_node.c */
switch_status_t new_kazoo_node(int nodefd, ErlConnect *conn);
/* kazoo_ei_utils.c */
void close_socket(switch_socket_t **sock);
void close_socketfd(int *sockfd);
switch_socket_t *create_socket_with_port(switch_memory_pool_t *pool, switch_port_t port);
switch_socket_t *create_socket(switch_memory_pool_t *pool);
switch_status_t create_ei_cnode(const char *ip_addr, const char *name, struct ei_cnode_s *ei_cnode);
switch_status_t ei_compare_pids(const erlang_pid *pid1, const erlang_pid *pid2);
void ei_encode_switch_event_headers(ei_x_buff *ebuf, switch_event_t *event);
void ei_encode_switch_event_headers_2(ei_x_buff *ebuf, switch_event_t *event, int decode);
void ei_encode_json(ei_x_buff *ebuf, cJSON *JObj);
void ei_link(ei_node_t *ei_node, erlang_pid * from, erlang_pid * to);
void ei_encode_switch_event(ei_x_buff * ebuf, switch_event_t *event);
int ei_helper_send(ei_node_t *ei_node, erlang_pid* to, ei_x_buff *buf);
int ei_decode_atom_safe(char *buf, int *index, char *dst);
int ei_decode_string_or_binary_limited(char *buf, int *index, int maxsize, char *dst);
int ei_decode_string_or_binary(char *buf, int *index, char **dst);
switch_status_t create_acceptor();
switch_hash_t *create_default_filter();
void kz_erl_init();
void kz_erl_shutdown();
SWITCH_DECLARE(switch_status_t) ei_queue_pop(switch_queue_t *queue, void **data, switch_interval_time_t timeout);
void fetch_config();
switch_status_t kazoo_load_config();
void kazoo_destroy_config();
void kz_set_hostname();
#define _ei_x_encode_string(buf, string) { ei_x_encode_binary(buf, string, strlen(string)); }
/* kazoo_fetch_agent.c */
switch_status_t bind_fetch_agents();
switch_status_t unbind_fetch_agents();
switch_status_t remove_xml_clients(ei_node_t *ei_node);
switch_status_t add_fetch_handler(ei_node_t *ei_node, erlang_pid *from, switch_xml_binding_t *binding);
switch_status_t remove_fetch_handlers(ei_node_t *ei_node, erlang_pid *from);
switch_status_t fetch_reply(char *uuid_str, char *xml_str, switch_xml_binding_t *binding);
switch_status_t handle_api_command_streams(ei_node_t *ei_node, switch_stream_handle_t *stream);
void bind_event_profiles(kazoo_event_ptr event);
void rebind_fetch_profiles(kazoo_config_ptr fetch_handlers);
switch_status_t kazoo_config_handlers(switch_xml_t cfg);
/* runtime */
SWITCH_MODULE_RUNTIME_FUNCTION(mod_kazoo_runtime);
#define kz_test_tweak(flag) (kazoo_globals.tweaks[flag] ? 1 : 0)
#define kz_set_tweak(flag) kazoo_globals.tweaks[flag] = 1
#define kz_clear_tweak(flag) kazoo_globals.tweaks[flag] = 0
#endif /* KAZOO_EI_H */
/* 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:
*/

View File

@ -1,708 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Based on mod_skel by
* Anthony Minessale II <anthm@freeswitch.org>
*
* Contributor(s):
*
* Daniel Bryars <danb@aeriandi.com>
* Tim Brown <tim.brown@aeriandi.com>
* Anthony Minessale II <anthm@freeswitch.org>
* William King <william.king@quentustech.com>
* Mike Jerris <mike@jerris.com>
*
* kazoo.c -- Sends FreeSWITCH events to an AMQP broker
*
*/
#include "mod_kazoo.h"
#define KZ_DEFAULT_STREAM_PRE_ALLOCATE 8192
#define KAZOO_DECLARE_GLOBAL_STRING_FUNC(fname, vname) static void __attribute__((__unused__)) fname(const char *string) { if (!string) return;\
if (vname) {free(vname); vname = NULL;}vname = strdup(string);} static void fname(const char *string)
KAZOO_DECLARE_GLOBAL_STRING_FUNC(set_pref_ip, kazoo_globals.ip);
KAZOO_DECLARE_GLOBAL_STRING_FUNC(set_pref_ei_cookie, kazoo_globals.ei_cookie);
KAZOO_DECLARE_GLOBAL_STRING_FUNC(set_pref_ei_nodename, kazoo_globals.ei_nodename);
//KAZOO_DECLARE_GLOBAL_STRING_FUNC(set_pref_kazoo_var_prefix, kazoo_globals.kazoo_var_prefix);
static int read_cookie_from_file(char *filename) {
int fd;
char cookie[MAXATOMLEN + 1];
char *end;
struct stat buf;
if (!stat(filename, &buf)) {
if ((buf.st_mode & S_IRWXG) || (buf.st_mode & S_IRWXO)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s must only be accessible by owner only.\n", filename);
return 2;
}
if (buf.st_size > MAXATOMLEN) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s contains a cookie larger than the maximum atom size of %d.\n", filename, MAXATOMLEN);
return 2;
}
fd = open(filename, O_RDONLY);
if (fd < 1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to open cookie file %s : %d.\n", filename, errno);
return 2;
}
if (read(fd, cookie, MAXATOMLEN) < 1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to read cookie file %s : %d.\n", filename, errno);
}
cookie[MAXATOMLEN] = '\0';
/* replace any end of line characters with a null */
if ((end = strchr(cookie, '\n'))) {
*end = '\0';
}
if ((end = strchr(cookie, '\r'))) {
*end = '\0';
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set cookie from file %s: %s\n", filename, cookie);
set_pref_ei_cookie(cookie);
return 0;
} else {
/* don't error here, because we might be blindly trying to read $HOME/.erlang.cookie, and that can fail silently */
return 1;
}
}
void kz_set_hostname()
{
if (kazoo_globals.hostname == NULL) {
char hostname[NODENAME_MAX];
memcpy(hostname, switch_core_get_hostname(), NODENAME_MAX);
kazoo_globals.hostname_ent = gethostbyname(hostname);
if(kazoo_globals.hostname_ent != NULL) {
kazoo_globals.hostname = switch_core_strdup(kazoo_globals.pool, kazoo_globals.hostname_ent->h_name);
} else {
kazoo_globals.hostname = switch_core_strdup(kazoo_globals.pool, hostname);
}
}
}
switch_status_t kazoo_ei_config(switch_xml_t cfg) {
switch_xml_t child, param;
char* kazoo_var_prefix = NULL;
char* profile_vars_prefix = NULL;
char* sep_array[KZ_MAX_SEPARATE_STRINGS];
int array_len, i;
kazoo_globals.send_all_headers = 0;
kazoo_globals.send_all_private_headers = 1;
kazoo_globals.connection_timeout = 500;
kazoo_globals.ei_receive_timeout = 200;
kazoo_globals.receive_msg_preallocate = 2000;
kazoo_globals.event_stream_preallocate = KZ_DEFAULT_STREAM_PRE_ALLOCATE;
kazoo_globals.send_msg_batch = 10;
kazoo_globals.event_stream_framing = 2;
kazoo_globals.event_stream_keepalive = 1;
kazoo_globals.event_stream_queue_timeout = 200000;
kazoo_globals.node_receiver_queue_timeout = 100000;
kazoo_globals.node_sender_queue_timeout = 0;
kazoo_globals.port = 0;
kazoo_globals.io_fault_tolerance = 3;
kazoo_globals.io_fault_tolerance_sleep = 100000; // 100 ms
kazoo_globals.json_encoding = ERLANG_TUPLE;
kazoo_globals.delay_before_initial_fetch = 10000000;
kazoo_globals.legacy_events = SWITCH_FALSE;
kazoo_globals.expand_headers_on_fetch = SWITCH_TRUE;
kz_set_tweak(KZ_TWEAK_INTERACTION_ID);
kz_set_tweak(KZ_TWEAK_EXPORT_VARS);
kz_set_tweak(KZ_TWEAK_SWITCH_URI);
kz_set_tweak(KZ_TWEAK_REPLACES_CALL_ID);
kz_set_tweak(KZ_TWEAK_LOOPBACK_VARS);
kz_set_tweak(KZ_TWEAK_CALLER_ID);
kz_set_tweak(KZ_TWEAK_TRANSFERS);
kz_set_tweak(KZ_TWEAK_BRIDGE);
kz_set_tweak(KZ_TWEAK_BRIDGE_REPLACES_ALEG);
kz_set_tweak(KZ_TWEAK_BRIDGE_REPLACES_CALL_ID);
kz_set_tweak(KZ_TWEAK_BRIDGE_VARIABLES);
kz_set_tweak(KZ_TWEAK_RESTORE_CALLER_ID_ON_BLIND_XFER);
if ((child = switch_xml_child(cfg, "settings"))) {
for (param = switch_xml_child(child, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
if (!strcmp(var, "listen-ip")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set bind ip address: %s\n", val);
set_pref_ip(val);
} else if (!strcmp(var, "listen-port")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set bind port: %s\n", val);
kazoo_globals.port = atoi(val);
} else if (!strcmp(var, "cookie")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set cookie: %s\n", val);
set_pref_ei_cookie(val);
} else if (!strcmp(var, "cookie-file")) {
if (read_cookie_from_file(val) == 1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to read cookie from %s\n", val);
}
} else if (!strcmp(var, "nodename")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set node name: %s\n", val);
set_pref_ei_nodename(val);
} else if (!strcmp(var, "shortname")) {
kazoo_globals.ei_shortname = switch_true(val);
} else if (!strcmp(var, "kazoo-var-prefix")) {
kazoo_var_prefix = switch_core_strdup(kazoo_globals.pool, val);
} else if (!strcmp(var, "set-profile-vars-prefix")) {
profile_vars_prefix = switch_core_strdup(kazoo_globals.pool, val);
} else if (!strcmp(var, "compat-rel")) {
if (atoi(val) >= 7)
kazoo_globals.ei_compat_rel = atoi(val);
else
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid compatibility release '%s' specified\n", val);
} else if (!strcmp(var, "nat-map")) {
kazoo_globals.nat_map = switch_true(val);
} else if (!strcmp(var, "send-all-headers")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set send-all-headers: %s\n", val);
kazoo_globals.send_all_headers = switch_true(val);
} else if (!strcmp(var, "send-all-private-headers")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set send-all-private-headers: %s\n", val);
kazoo_globals.send_all_private_headers = switch_true(val);
} else if (!strcmp(var, "connection-timeout")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set connection-timeout: %s\n", val);
kazoo_globals.connection_timeout = atoi(val);
} else if (!strcmp(var, "receive-timeout")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set receive-timeout: %s\n", val);
kazoo_globals.ei_receive_timeout = atoi(val);
} else if (!strcmp(var, "receive-msg-preallocate")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set receive-msg-preallocate: %s\n", val);
kazoo_globals.receive_msg_preallocate = atoi(val);
} else if (!strcmp(var, "event-stream-preallocate")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set event-stream-preallocate: %s\n", val);
kazoo_globals.event_stream_preallocate = atoi(val);
} else if (!strcmp(var, "send-msg-batch-size")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set send-msg-batch-size: %s\n", val);
kazoo_globals.send_msg_batch = atoi(val);
} else if (!strcmp(var, "event-stream-framing")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set event-stream-framing: %s\n", val);
kazoo_globals.event_stream_framing = atoi(val);
} else if (!strcmp(var, "event-stream-keep-alive")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set event-stream-keep-alive: %s\n", val);
kazoo_globals.event_stream_keepalive = switch_true(val);
} else if (!strcmp(var, "io-fault-tolerance")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set io-fault-tolerance: %s\n", val);
kazoo_globals.io_fault_tolerance = atoi(val);
} else if (!strcmp(var, "io-fault-tolerance-sleep-micro")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val);
kazoo_globals.io_fault_tolerance_sleep = atoi(val);
} else if (!strcmp(var, "io-fault-tolerance-sleep-ms")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val);
kazoo_globals.io_fault_tolerance_sleep = atoi(val) * 1000;
} else if (!strcmp(var, "io-fault-tolerance-sleep-sec")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val);
kazoo_globals.io_fault_tolerance_sleep = atoi(val) * 1000000;
} else if (!strcmp(var, "node-worker-threads")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set node-worker-threads: %s\n", val);
kazoo_globals.node_worker_threads = atoi(val);
} else if (!strcmp(var, "json-term-encoding")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set json-term-encoding: %s\n", val);
if(!strcmp(val, "map")) {
kazoo_globals.json_encoding = ERLANG_MAP;
}
} else if (!strcmp(var, "legacy-events")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set legacy-events: %s\n", val);
kazoo_globals.legacy_events = switch_true(val);
} else if (!strcmp(var, "expand-headers-on-fetch")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set expand-headers-on-fetch: %s\n", val);
kazoo_globals.expand_headers_on_fetch = switch_true(val);
} else if (!strcmp(var, "node-receiver-queue-timeout")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val);
kazoo_globals.node_receiver_queue_timeout = atoi(val);
} else if (!strcmp(var, "node-sender-queue-timeout")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val);
kazoo_globals.node_sender_queue_timeout = atoi(val);
} else if (!strcmp(var, "event-stream-queue-timeout")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val);
kazoo_globals.event_stream_queue_timeout = atoi(val);
} else if (!strcmp(var, "delay-before-initial-fetch-micro")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val);
kazoo_globals.delay_before_initial_fetch = atoi(val);
} else if (!strcmp(var, "delay-before-initial-fetch-ms")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val);
kazoo_globals.delay_before_initial_fetch = atoi(val) * 1000;
} else if (!strcmp(var, "delay-before-initial-fetch-sec")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val);
kazoo_globals.delay_before_initial_fetch = atoi(val) * 1000000;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "unknown config option %s : %s\n", var, val);
}
}
}
if ((child = switch_xml_child(cfg, "tweaks"))) {
char *default_tweaks = (char *) switch_xml_attr_soft(child, "default");
if (default_tweaks && !zstr(default_tweaks)) {
int i, v = switch_true(default_tweaks) ? 1 : 0;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set tweak default : %s\n", default_tweaks);
for (i = 0; i < KZ_TWEAK_MAX; i++) kazoo_globals.tweaks[i] = v;
}
for (param = switch_xml_child(child, "tweak"); param; param = param->next) {
kz_tweak_t tweak = KZ_TWEAK_MAX;
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
if(var && val && kz_name_tweak(var, &tweak) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set tweak %s : %s\n", var, val);
if(switch_true(val)) {
kz_set_tweak(tweak);
} else {
kz_clear_tweak(tweak);
}
}
}
}
if ((child = switch_xml_child(cfg, "variables"))) {
for (param = switch_xml_child(child, "variable"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
if(var && val) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set core variable %s : %s\n", var, val);
switch_core_set_variable(var, val);
}
}
}
if ((child = switch_xml_child(cfg, "event-filter"))) {
switch_hash_t *filter;
switch_core_hash_init(&filter);
for (param = switch_xml_child(child, "header"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
switch_core_hash_insert(filter, var, "1");
}
kazoo_globals.event_filter = filter;
}
if (kazoo_globals.receive_msg_preallocate < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid receive message preallocate value, disabled\n");
kazoo_globals.receive_msg_preallocate = 0;
}
if (kazoo_globals.event_stream_preallocate < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid event stream preallocate value, disabled\n");
kazoo_globals.event_stream_preallocate = 0;
}
if (kazoo_globals.send_msg_batch < 1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid send message batch size, reverting to default\n");
kazoo_globals.send_msg_batch = 10;
}
if (kazoo_globals.io_fault_tolerance < 1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid I/O fault tolerance, reverting to default\n");
kazoo_globals.io_fault_tolerance = 10;
}
if (!kazoo_globals.event_filter) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Event filter not found in configuration, using default\n");
kazoo_globals.event_filter = create_default_filter();
}
if (kazoo_globals.event_stream_framing < 1 || kazoo_globals.event_stream_framing > 4) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid event stream framing value, using default\n");
kazoo_globals.event_stream_framing = 2;
}
if (zstr(kazoo_var_prefix)) {
kazoo_var_prefix = switch_core_strdup(kazoo_globals.pool, "ecallmgr_;cav_");
}
if (zstr(profile_vars_prefix)) {
profile_vars_prefix = switch_core_strdup(kazoo_globals.pool, "effective_;origination_");
}
kazoo_globals.kazoo_var_prefixes = switch_core_alloc(kazoo_globals.pool, sizeof(char*) * KZ_MAX_SEPARATE_STRINGS);
array_len = switch_separate_string(kazoo_var_prefix, ';', sep_array, KZ_MAX_SEPARATE_STRINGS - 1);
for(i=0; i < array_len; i++) {
char var[100];
sprintf(var, "variable_%s", sep_array[i]);
kazoo_globals.kazoo_var_prefixes[i] = switch_core_strdup(kazoo_globals.pool, var);
}
kazoo_globals.profile_vars_prefixes = switch_core_alloc(kazoo_globals.pool, sizeof(char*) * KZ_MAX_SEPARATE_STRINGS);
array_len = switch_separate_string(profile_vars_prefix, ';', sep_array, KZ_MAX_SEPARATE_STRINGS - 1);
for(i=0; i < array_len; i++) {
kazoo_globals.profile_vars_prefixes[i] = switch_core_strdup(kazoo_globals.pool, sep_array[i]);
}
if (!kazoo_globals.node_worker_threads) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Number of node worker threads not found in configuration, using default\n");
kazoo_globals.node_worker_threads = 10;
}
if (zstr(kazoo_globals.ip)) {
set_pref_ip("0.0.0.0");
}
if (zstr(kazoo_globals.ei_cookie)) {
int res;
char *home_dir = getenv("HOME");
char path_buf[1024];
if (!zstr(home_dir)) {
/* $HOME/.erlang.cookie */
switch_snprintf(path_buf, sizeof (path_buf), "%s%s%s", home_dir, SWITCH_PATH_SEPARATOR, ".erlang.cookie");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Checking for cookie at path: %s\n", path_buf);
res = read_cookie_from_file(path_buf);
if (res) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No cookie or valid cookie file specified, using default cookie\n");
set_pref_ei_cookie("ClueCon");
}
}
}
if (!kazoo_globals.ei_nodename) {
set_pref_ei_nodename("freeswitch");
}
if (!kazoo_globals.nat_map) {
kazoo_globals.nat_map = 0;
}
return SWITCH_STATUS_SUCCESS;
}
switch_status_t kazoo_config_handlers(switch_xml_t cfg)
{
switch_xml_t def = NULL;
switch_xml_t child, param;
char* xml = NULL;
kazoo_config_ptr definitions = NULL, fetch_handlers = NULL, event_handlers = NULL;
kazoo_event_profile_ptr events = NULL;
xml = strndup(kz_default_config, kz_default_config_size);
def = switch_xml_parse_str_dup(xml);
kz_xml_process(def);
kz_xml_process(cfg);
if ((child = switch_xml_child(cfg, "variables"))) {
for (param = switch_xml_child(child, "variable"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
if(var && val) {
switch_core_set_variable(var, val);
}
}
} else if ((child = switch_xml_child(def, "variables"))) {
for (param = switch_xml_child(child, "variable"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
if(var && val) {
switch_core_set_variable(var, val);
}
}
}
definitions = kazoo_config_definitions(cfg);
if(definitions == NULL) {
if(kazoo_globals.definitions == NULL) {
definitions = kazoo_config_definitions(def);
} else {
definitions = kazoo_globals.definitions;
}
}
fetch_handlers = kazoo_config_fetch_handlers(definitions, cfg);
if(fetch_handlers == NULL) {
if(kazoo_globals.fetch_handlers == NULL) {
fetch_handlers = kazoo_config_fetch_handlers(definitions, def);
} else {
fetch_handlers = kazoo_globals.fetch_handlers;
}
}
event_handlers = kazoo_config_event_handlers(definitions, cfg);
if(event_handlers == NULL) {
if(kazoo_globals.event_handlers == NULL) {
event_handlers = kazoo_config_event_handlers(definitions, def);
} else {
event_handlers = kazoo_globals.event_handlers;
}
}
if(event_handlers != NULL) {
events = (kazoo_event_profile_ptr) switch_core_hash_find(event_handlers->hash, "default");
}
if(events == NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to get default handler for events\n");
destroy_config(&event_handlers);
event_handlers = kazoo_config_event_handlers(definitions, def);
events = (kazoo_event_profile_ptr) switch_core_hash_find(event_handlers->hash, "default");
}
if(kazoo_globals.events != events) {
bind_event_profiles(events->events);
kazoo_globals.events = events;
}
if(kazoo_globals.event_handlers != event_handlers) {
kazoo_config_ptr tmp = kazoo_globals.event_handlers;
kazoo_globals.event_handlers = event_handlers;
destroy_config(&tmp);
}
if(kazoo_globals.fetch_handlers != fetch_handlers) {
kazoo_config_ptr tmp = kazoo_globals.fetch_handlers;
kazoo_globals.fetch_handlers = fetch_handlers;
rebind_fetch_profiles(fetch_handlers);
destroy_config(&tmp);
}
if(kazoo_globals.definitions != definitions) {
kazoo_config_ptr tmp = kazoo_globals.definitions;
kazoo_globals.definitions = definitions;
destroy_config(&tmp);
}
switch_xml_free(def);
switch_safe_free(xml);
return SWITCH_STATUS_SUCCESS;
}
switch_status_t kazoo_load_config()
{
char *cf = "kazoo.conf";
switch_xml_t cfg, xml;
if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open configuration file %s\n", cf);
return SWITCH_STATUS_FALSE;
} else {
kazoo_ei_config(cfg);
kazoo_config_handlers(cfg);
switch_xml_free(xml);
}
return SWITCH_STATUS_SUCCESS;
}
void kazoo_destroy_config()
{
destroy_config(&kazoo_globals.event_handlers);
destroy_config(&kazoo_globals.fetch_handlers);
destroy_config(&kazoo_globals.definitions);
}
switch_status_t kazoo_config_events(kazoo_config_ptr definitions, switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_event_profile_ptr profile)
{
switch_xml_t events, event;
kazoo_event_ptr prv = NULL, cur = NULL;
if ((events = switch_xml_child(cfg, "events")) != NULL) {
for (event = switch_xml_child(events, "event"); event; event = event->next) {
const char *var = switch_xml_attr(event, "name");
cur = (kazoo_event_ptr) switch_core_alloc(pool, sizeof(kazoo_event_t));
memset(cur, 0, sizeof(kazoo_event_t));
if(prv == NULL) {
profile->events = prv = cur;
} else {
prv->next = cur;
prv = cur;
}
cur->profile = profile;
cur->name = switch_core_strdup(pool, var);
kazoo_config_filters(pool, event, &cur->filter);
kazoo_config_fields(definitions, pool, event, &cur->fields);
if (switch_xml_child(event, "logging") != NULL) {
kazoo_config_loglevels(pool, event, &cur->logging);
}
}
}
return SWITCH_STATUS_SUCCESS;
}
switch_status_t kazoo_config_fetch_handler(kazoo_config_ptr definitions, kazoo_config_ptr root, switch_xml_t cfg, kazoo_fetch_profile_ptr *ptr)
{
kazoo_fetch_profile_ptr profile = NULL;
switch_xml_t params, param;
switch_xml_section_t fetch_section;
int fetch_timeout = 2000000;
switch_memory_pool_t *pool = NULL;
char *name = (char *) switch_xml_attr_soft(cfg, "name");
if (zstr(name)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing name in profile\n");
return SWITCH_STATUS_GENERR;
}
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error allocation pool for new profile : %s\n", name);
return SWITCH_STATUS_GENERR;
}
profile = switch_core_alloc(pool, sizeof(kazoo_fetch_profile_t));
profile->pool = pool;
profile->root = root;
profile->name = switch_core_strdup(profile->pool, name);
fetch_section = switch_xml_parse_section_string(name);
if ((params = switch_xml_child(cfg, "params")) != NULL) {
for (param = switch_xml_child(params, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
if (!var) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile[%s] param missing 'name' attribute\n", name);
continue;
}
if (!val) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile[%s] param[%s] missing 'value' attribute\n", name, var);
continue;
}
if (!strncmp(var, "fetch-timeout", 13)) {
fetch_timeout = atoi(val);
} else if (!strncmp(var, "fetch-section", 13)) {
fetch_section = switch_xml_parse_section_string(val);
}
}
}
if (fetch_section == SWITCH_XML_SECTION_RESULT) {
char *tmp = switch_xml_toxml(cfg, SWITCH_FALSE);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Fetch Profile[%s] invalid fetch-section: %s\n", name, tmp);
free(tmp);
goto err;
}
profile->fetch_timeout = fetch_timeout;
profile->section = fetch_section;
kazoo_config_fields(definitions, pool, cfg, &profile->fields);
kazoo_config_loglevels(pool, cfg, &profile->logging);
if(root) {
if ( switch_core_hash_insert(root->hash, name, (void *) profile) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to insert new fetch profile [%s] into kazoo profile hash\n", name);
goto err;
}
}
if (ptr) {
*ptr = profile;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "fetch handler profile %s successfully configured\n", name);
return SWITCH_STATUS_SUCCESS;
err:
/* Cleanup */
if(pool) {
switch_core_destroy_memory_pool(&pool);
}
return SWITCH_STATUS_GENERR;
}
switch_status_t kazoo_config_event_handler(kazoo_config_ptr definitions, kazoo_config_ptr root, switch_xml_t cfg, kazoo_event_profile_ptr *ptr)
{
kazoo_event_profile_ptr profile = NULL;
switch_memory_pool_t *pool = NULL;
char *name = (char *) switch_xml_attr_soft(cfg, "name");
if (zstr(name)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing name in profile\n");
return SWITCH_STATUS_GENERR;
}
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error allocation pool for new profile : %s\n", name);
return SWITCH_STATUS_GENERR;
}
profile = switch_core_alloc(pool, sizeof(kazoo_event_profile_t));
profile->pool = pool;
profile->root = root;
profile->name = switch_core_strdup(profile->pool, name);
kazoo_config_filters(pool, cfg, &profile->filter);
kazoo_config_fields(definitions, pool, cfg, &profile->fields);
kazoo_config_events(definitions, pool, cfg, profile);
kazoo_config_loglevels(pool, cfg, &profile->logging);
if(root) {
if ( switch_core_hash_insert(root->hash, name, (void *) profile) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to insert new profile [%s] into kazoo profile hash\n", name);
goto err;
}
}
if(ptr)
*ptr = profile;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "event handler profile %s successfully configured\n", name);
return SWITCH_STATUS_SUCCESS;
err:
/* Cleanup */
if(pool) {
switch_core_destroy_memory_pool(&pool);
}
return SWITCH_STATUS_GENERR;
}
/* 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
*/

File diff suppressed because it is too large Load Diff

View File

@ -1,500 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Karl Anderson <karl@2600hz.com>
* Darren Schreiber <darren@2600hz.com>
*
*
* kazoo_dptools.c -- clones of mod_dptools commands slightly modified for kazoo
*
*/
#include "mod_kazoo.h"
#define INTERACTION_VARIABLE "Call-Interaction-ID"
static const char *x_bridge_variables[] = {
"Call-Control-Queue",
"Call-Control-PID",
"Call-Control-Node",
INTERACTION_VARIABLE,
"ecallmgr_Ecallmgr-Node",
"sip_h_k-cid",
"Switch-URI",
"Switch-URL",
NULL
};
static void kz_tweaks_variables_to_event(switch_core_session_t *session, switch_event_t *event)
{
int i;
switch_channel_t *channel = switch_core_session_get_channel(session);
for(i = 0; x_bridge_variables[i] != NULL; i++) {
const char *val = switch_channel_get_variable_dup(channel, x_bridge_variables[i], SWITCH_FALSE, -1);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, x_bridge_variables[i], val);
}
}
static switch_call_cause_t kz_endpoint_outgoing_channel(switch_core_session_t *session,
switch_event_t *var_event,
switch_caller_profile_t *outbound_profile_in,
switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
switch_call_cause_t *cancel_cause)
{
switch_xml_t x_user = NULL, x_param, x_params, x_callfwd;
char *user = NULL, *domain = NULL, *dup_domain = NULL, *dialed_user = NULL;
char *dest = NULL;
switch_call_cause_t cause = SWITCH_CAUSE_NONE;
unsigned int timelimit = SWITCH_DEFAULT_TIMEOUT;
switch_channel_t *new_channel = NULL;
switch_event_t *params = NULL, *var_event_orig = var_event;
char stupid[128] = "";
const char *skip = NULL, *var = NULL;
switch_core_session_t *a_session = NULL, *e_session = NULL;
cJSON * ctx = NULL;
const char *endpoint_dial = NULL;
const char *callforward_dial = NULL;
const char *failover_dial = NULL;
char *b_failover_dial = NULL;
const char *endpoint_separator = NULL;
const char *varval = NULL;
char *d_dest = NULL;
switch_channel_t *channel = NULL;
switch_originate_flag_t myflags = SOF_NONE;
char *cid_name_override = NULL;
char *cid_num_override = NULL;
switch_event_t *event = NULL;
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_caller_profile_t *outbound_profile = NULL;
if (zstr(outbound_profile_in->destination_number)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "NO DESTINATION NUMBER\n");
goto done;
}
user = strdup(outbound_profile_in->destination_number);
if (!user)
goto done;
if ((domain = strchr(user, '@'))) {
*domain++ = '\0';
} else {
domain = switch_core_get_domain(SWITCH_TRUE);
dup_domain = domain;
}
if (!domain) {
goto done;
}
switch_event_create(&params, SWITCH_EVENT_REQUEST_PARAMS);
switch_assert(params);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "as_channel", "true");
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "action", "user_call");
if (session) {
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(session));
}
if (var_event) {
switch_event_merge(params, var_event);
}
if (var_event && (skip = switch_event_get_header(var_event, "user_recurse_variables")) && switch_false(skip)) {
if ((var = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) || (var = switch_event_get_header(var_event, "leg_timeout"))) {
timelimit = atoi(var);
}
var_event = NULL;
}
if (switch_xml_locate_user_merged("id", user, domain, NULL, &x_user, params) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Can't find user [%s@%s]\n", user, domain);
cause = SWITCH_CAUSE_SUBSCRIBER_ABSENT;
goto done;
}
if (var_event) {
const char * str_ctx = switch_event_get_header(var_event, "kz-endpoint-runtime-context");
if ( str_ctx ) {
ctx = cJSON_Parse(str_ctx);
if (ctx) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "call context parsed => %s\n", str_ctx);
}
}
}
if ((x_params = switch_xml_child(x_user, "variables"))) {
for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
const char *pvar = switch_xml_attr_soft(x_param, "name");
const char *val = switch_xml_attr(x_param, "value");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "adding variable to var_event => %s = %s\n", pvar, val);
if (!var_event) {
switch_event_create(&var_event, SWITCH_EVENT_GENERAL);
} else {
switch_event_del_header(var_event, pvar);
}
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, pvar, val);
}
}
if ((x_params = switch_xml_child(x_user, "params"))) {
for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
const char *pvar = switch_xml_attr_soft(x_param, "name");
const char *val = switch_xml_attr(x_param, "value");
if (!strcasecmp(pvar, "endpoint-dial-string")) {
endpoint_dial = val;
} else if (!strcasecmp(pvar, "callforward-dial-string")) {
callforward_dial = val;
} else if (!strcasecmp(pvar, "endpoint-separator")) {
endpoint_separator = val;
} else if (!strncasecmp(pvar, "dial-var-", 9)) {
if (!var_event) {
switch_event_create(&var_event, SWITCH_EVENT_GENERAL);
} else {
switch_event_del_header(var_event, pvar + 9);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "adding dialog var to var_event => %s = %s\n", pvar + 9, val);
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, pvar + 9, val);
}
}
}
x_callfwd = switch_xml_child(x_user, "call-forward");
if (x_callfwd) {
switch_bool_t call_fwd_is_substitute = SWITCH_FALSE,
call_fwd_is_failover = SWITCH_FALSE,
call_fwd_direct_calls_only = SWITCH_FALSE,
call_fwd_is_valid = SWITCH_TRUE;
for (x_param = switch_xml_child(x_callfwd, "variable"); x_param; x_param = x_param->next) {
const char *var = switch_xml_attr_soft(x_param, "name");
const char *val = switch_xml_attr(x_param, "value");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "cfw %s => %s\n", var, val);
if (!strcasecmp(var, "Is-Substitute")) {
call_fwd_is_substitute = switch_true(val);
} else if (!strcasecmp(var, "Is-Failover")) {
call_fwd_is_failover = switch_true(val);
} else if (!strcasecmp(var, "Direct-Calls-Only")) {
call_fwd_direct_calls_only = switch_true(val);
}
}
if (call_fwd_direct_calls_only) {
call_fwd_is_valid = SWITCH_FALSE;
if (ctx ) {
cJSON *json_flags = cJSON_GetObjectItem(ctx, "Flags");
if (json_flags && json_flags->type == cJSON_Array) {
cJSON *item;
cJSON_ArrayForEach(item, json_flags) {
if (!strcmp(item->valuestring, "direct_call")) {
call_fwd_is_valid = SWITCH_TRUE;
break;
}
}
if (!call_fwd_is_valid) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "call fwd requires direct_call and it was not found\n");
}
}
}
}
if (!call_fwd_is_valid) {
dest = endpoint_dial ? strdup(endpoint_dial) : strdup("");
} else if (call_fwd_is_failover) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "setting failover => %s\n", callforward_dial);
dest = endpoint_dial ? strdup(endpoint_dial) : strdup("");
failover_dial = callforward_dial;
} else if (call_fwd_is_substitute) {
dest = callforward_dial ? strdup(callforward_dial) : strdup("");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "setting call fwd substitute => %s\n", dest);
} else {
dest = switch_mprintf("%s%s%s", endpoint_dial ? endpoint_dial : "", (endpoint_dial ? endpoint_separator ? endpoint_separator : "," : ""), callforward_dial);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "setting call fwd append => %s => %s\n", callforward_dial, dest);
}
} else {
dest = endpoint_dial ? strdup(endpoint_dial) : strdup("");
}
dialed_user = (char *)switch_xml_attr(x_user, "id");
if (var_event) {
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_user", dialed_user);
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_domain", domain);
}
if (!dest) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No dial-string available, please check your user directory.\n");
cause = SWITCH_CAUSE_MANDATORY_IE_MISSING;
goto done;
}
if (var_event) {
cid_name_override = switch_event_get_header(var_event, "origination_caller_id_name");
cid_num_override = switch_event_get_header(var_event, "origination_caller_id_number");
}
if(session) {
a_session = session;
} else if(var_event) {
const char* uuid_e_session = switch_event_get_header(var_event, "ent_originate_aleg_uuid");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHECKING ORIGINATE-UUID : %s\n", uuid_e_session);
if (uuid_e_session && (e_session = switch_core_session_locate(uuid_e_session)) != NULL) {
a_session = e_session;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FOUND ORIGINATE-UUID : %s\n", uuid_e_session);
}
}
if (a_session) {
switch_event_create(&event, SWITCH_EVENT_GENERAL);
channel = switch_core_session_get_channel(a_session);
if ((varval = switch_channel_get_variable(channel, SWITCH_CALL_TIMEOUT_VARIABLE))
|| (var_event && (varval = switch_event_get_header(var_event, "leg_timeout")))) {
timelimit = atoi(varval);
}
switch_channel_event_set_data(channel, event);
switch_channel_set_variable(channel, "dialed_user", dialed_user);
switch_channel_set_variable(channel, "dialed_domain", domain);
} else {
if (var_event) {
switch_event_dup(&event, var_event);
switch_event_del_header(event, "dialed_user");
switch_event_del_header(event, "dialed_domain");
if ((varval = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) ||
(varval = switch_event_get_header(var_event, "leg_timeout"))) {
timelimit = atoi(varval);
}
} else {
switch_event_create(&event, SWITCH_EVENT_REQUEST_PARAMS);
switch_assert(event);
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "dialed_user", dialed_user);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "dialed_domain", domain);
}
if ((x_params = switch_xml_child(x_user, "profile-variables"))) {
for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
const char *pvar = switch_xml_attr_soft(x_param, "name");
const char *val = switch_xml_attr(x_param, "value");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "adding profile variable to event => %s = %s\n", pvar, val);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, pvar, val);
}
}
if ((x_params = switch_xml_child(x_user, "variables"))) {
for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
const char *pvar = switch_xml_attr_soft(x_param, "name");
const char *val = switch_xml_attr(x_param, "value");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "adding variable to event => %s = %s\n", pvar, val);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, pvar, val);
}
}
if ((x_params = switch_xml_child(x_user, "params"))) {
for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
const char *pvar = switch_xml_attr_soft(x_param, "name");
const char *val = switch_xml_attr(x_param, "value");
if (!strncasecmp(pvar, "dial-var-", 9)) {
switch_event_del_header(event, pvar + 9);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "adding dialog var to event => %s = %s\n", pvar + 9, val);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, pvar + 9, val);
}
}
}
// add runtime vars to event for expand
if (ctx) {
kz_expand_json_to_event(ctx, event, "kz_ctx");
}
d_dest = kz_event_expand_headers(event, dest);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "dialing %s => %s\n", dest, d_dest);
if(failover_dial) {
b_failover_dial = kz_event_expand_headers(event, failover_dial);
}
if (var_event) {
kz_expand_headers(event, var_event);
}
switch_event_destroy(&event);
if ((flags & SOF_NO_LIMITS)) {
myflags |= SOF_NO_LIMITS;
}
if ((flags & SOF_FORKED_DIAL)) {
myflags |= SOF_NOBLOCK;
}
if ( a_session ) {
if(var_event) {
kz_tweaks_variables_to_event(a_session, var_event);
}
}
if(e_session) {
switch_core_session_rwunlock(e_session);
}
switch_snprintf(stupid, sizeof(stupid), "kz/%s", dialed_user);
if (switch_stristr(stupid, d_dest)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Waddya Daft? You almost called '%s' in an infinate loop!\n", stupid);
cause = SWITCH_CAUSE_INVALID_IE_CONTENTS;
goto done;
}
//
outbound_profile = outbound_profile_in;
/*
outbound_profile = switch_caller_profile_dup(outbound_profile_in->pool, outbound_profile_in);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG1, "CHECKING CALLER-ID\n");
if ((x_params = switch_xml_child(x_user, "profile-variables"))) {
const char* val = NULL;
outbound_profile->soft = NULL;
for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
const char *pvar = switch_xml_attr(x_param, "name");
const char *val = switch_xml_attr(x_param, "value");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG1, "setting profile var %s = %s\n", pvar, val);
switch_caller_profile_set_var(outbound_profile, pvar, val);
}
// * TODO * verify onnet/offnet
if((val=switch_caller_get_field_by_name(outbound_profile, "Endpoint-Caller-ID-Name"))) {
outbound_profile->callee_id_name = val;
outbound_profile->orig_caller_id_name = val;
}
if((val=switch_caller_get_field_by_name(outbound_profile, "Endpoint-Caller-ID-Number"))) {
outbound_profile->callee_id_number = val;
outbound_profile->orig_caller_id_number = val;
}
}
*/
status = switch_ivr_originate(session, new_session, &cause, d_dest, timelimit, NULL,
cid_name_override, cid_num_override, outbound_profile, var_event, myflags,
cancel_cause, NULL);
if (status != SWITCH_STATUS_SUCCESS && b_failover_dial) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "trying failover => %s\n", failover_dial);
status = switch_ivr_originate(session, new_session, &cause, b_failover_dial, timelimit, NULL,
cid_name_override, cid_num_override, outbound_profile, var_event, myflags,
cancel_cause, NULL);
}
if (status == SWITCH_STATUS_SUCCESS) {
const char *context;
switch_caller_profile_t *cp;
if (var_event) {
switch_event_del_header(var_event, "origination_uuid");
}
new_channel = switch_core_session_get_channel(*new_session);
if ((context = switch_channel_get_variable(new_channel, "user_context"))) {
if ((cp = switch_channel_get_caller_profile(new_channel))) {
cp->context = switch_core_strdup(cp->pool, context);
}
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG1, "CHECKING CALLER-ID\n");
if ((x_params = switch_xml_child(x_user, "profile-variables"))) {
switch_caller_profile_t *cp = switch_channel_get_caller_profile(new_channel);
const char* val = NULL;
cp->soft = NULL;
for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
const char *pvar = switch_xml_attr(x_param, "name");
const char *val = switch_xml_attr(x_param, "value");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG1, "setting profile var %s = %s\n", pvar, val);
switch_channel_set_profile_var(new_channel, pvar, val);
//switch_caller_profile_set_var(cp, pvar, val);
}
// * TODO * verify onnet/offnet
if((val=switch_caller_get_field_by_name(cp, "Endpoint-Caller-ID-Name"))) {
cp->callee_id_name = val;
cp->orig_caller_id_name = val;
}
if((val=switch_caller_get_field_by_name(cp, "Endpoint-Caller-ID-Number"))) {
cp->callee_id_number = val;
cp->orig_caller_id_number = val;
}
}
switch_core_session_rwunlock(*new_session);
}
done:
if (d_dest && d_dest != dest) {
switch_safe_free(d_dest);
}
if(b_failover_dial && b_failover_dial != failover_dial) {
switch_safe_free(b_failover_dial);
}
switch_safe_free(dest);
if (ctx) {
cJSON_Delete(ctx);
}
if (x_user) {
switch_xml_free(x_user);
}
if (params) {
switch_event_destroy(&params);
}
if (var_event && var_event_orig != var_event) {
switch_event_destroy(&var_event);
}
switch_safe_free(user);
switch_safe_free(dup_domain);
return cause;
}
/* kazoo endpoint */
switch_io_routines_t kz_endpoint_io_routines = {
/*.outgoing_channel */ kz_endpoint_outgoing_channel
};
void add_kz_endpoints(switch_loadable_module_interface_t **module_interface) {
switch_endpoint_interface_t *kz_endpoint_interface;
kz_endpoint_interface = (switch_endpoint_interface_t *) switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
kz_endpoint_interface->interface_name = "kz";
kz_endpoint_interface->io_routines = &kz_endpoint_io_routines;
}

View File

@ -1,750 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Karl Anderson <karl@2600hz.com>
* Darren Schreiber <darren@2600hz.com>
*
*
* kazoo_event_streams.c -- Event Publisher
*
*/
#include "mod_kazoo.h"
#define MAX_FRAMING 4
/* Blatantly repurposed from switch_eventc */
static char *my_dup(const char *s) {
size_t len = strlen(s) + 1;
void *new = malloc(len);
switch_assert(new);
return (char *) memcpy(new, s, len);
}
#ifndef DUP
#define DUP(str) my_dup(str)
#endif
static const char* private_headers[] = {"variable_sip_h_", "sip_h_", "P-", "X-"};
static int is_private_header(const char *name) {
int i;
for(i=0; i < 4; i++) {
if(!strncmp(name, private_headers[i], strlen(private_headers[i]))) {
return 1;
}
}
return 0;
}
static int is_kazoo_var(char* header)
{
int idx = 0;
while(kazoo_globals.kazoo_var_prefixes[idx] != NULL) {
char *prefix = kazoo_globals.kazoo_var_prefixes[idx];
if(!strncasecmp(header, prefix, strlen(prefix))) {
return 1;
}
idx++;
}
return 0;
}
static switch_status_t kazoo_event_dup(switch_event_t **clone, switch_event_t *event, switch_hash_t *filter) {
switch_event_header_t *header;
if (switch_event_create_subclass(clone, SWITCH_EVENT_CLONE, event->subclass_name) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_GENERR;
}
(*clone)->event_id = event->event_id;
(*clone)->event_user_data = event->event_user_data;
(*clone)->bind_user_data = event->bind_user_data;
(*clone)->flags = event->flags;
for (header = event->headers; header; header = header->next) {
if (event->subclass_name && !strcmp(header->name, "Event-Subclass")) {
continue;
}
if (!is_kazoo_var(header->name)
&& filter
&& !switch_core_hash_find(filter, header->name)
&& (!kazoo_globals.send_all_headers)
&& (!(kazoo_globals.send_all_private_headers && is_private_header(header->name)))
)
{
continue;
}
if (header->idx) {
int i;
for (i = 0; i < header->idx; i++) {
switch_event_add_header_string(*clone, SWITCH_STACK_PUSH, header->name, header->array[i]);
}
} else {
switch_event_add_header_string(*clone, SWITCH_STACK_BOTTOM, header->name, header->value);
}
}
if (event->body) {
(*clone)->body = DUP(event->body);
}
(*clone)->key = event->key;
return SWITCH_STATUS_SUCCESS;
}
static int encode_event_old(switch_event_t *event, ei_x_buff *ebuf) {
switch_event_t *clone = NULL;
if (kazoo_event_dup(&clone, event, kazoo_globals.event_filter) != SWITCH_STATUS_SUCCESS) {
return 0;
}
ei_encode_switch_event(ebuf, clone);
switch_event_destroy(&clone);
return 1;
}
static int encode_event_new(switch_event_t *event, ei_x_buff *ebuf) {
kazoo_message_ptr msg = NULL;
ei_event_binding_t *event_binding = (ei_event_binding_t *) event->bind_user_data;
msg = kazoo_message_create_event(event, event_binding->event, kazoo_globals.events);
if(msg == NULL) {
return 0;
}
ei_x_encode_tuple_header(ebuf, 3);
ei_x_encode_atom(ebuf, "event");
if(kazoo_globals.json_encoding == ERLANG_TUPLE) {
ei_x_encode_atom(ebuf, "json");
} else {
ei_x_encode_atom(ebuf, "map");
}
ei_encode_json(ebuf, msg->JObj);
kazoo_message_destroy(&msg);
return 1;
}
/*
* event_handler is duplicated when there are 2+ nodes connected
* with the same bindings
* we should maintain a list of event_streams in event_binding struct
* and build a ref count in the message
*
*/
static void event_handler(switch_event_t *event) {
ei_event_binding_t *event_binding = (ei_event_binding_t *) event->bind_user_data;
ei_event_stream_t *event_stream = event_binding->stream;
ei_x_buff *ebuf = NULL;
int res = 0;
/* if mod_kazoo or the event stream isn't running dont push a new event */
if (!switch_test_flag(event_stream, LFLAG_RUNNING) || !switch_test_flag(&kazoo_globals, LFLAG_RUNNING)) {
return;
}
kz_event_decode(event);
switch_malloc(ebuf, sizeof(*ebuf));
if(ebuf == NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate erlang buffer for mod_kazoo message\n");
return;
}
memset(ebuf, 0, sizeof(*ebuf));
if(kazoo_globals.event_stream_preallocate > 0) {
ebuf->buff = malloc(kazoo_globals.event_stream_preallocate);
ebuf->buffsz = kazoo_globals.event_stream_preallocate;
ebuf->index = 0;
if(ebuf->buff == NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not pre-allocate memory for mod_kazoo message\n");
switch_safe_free(ebuf);
return;
}
} else {
ei_x_new(ebuf);
}
ebuf->index = MAX_FRAMING;
ei_x_encode_version(ebuf);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Target-Node", event_binding->stream->node->peer_nodename);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Switch-Nodename", kazoo_globals.ei_cnode.thisnodename);
if(event_stream->node->legacy) {
res = encode_event_old(event, ebuf);
} else {
res = encode_event_new(event, ebuf);
}
switch_event_del_header(event, "Switch-Nodename");
switch_event_del_header(event, "Target-Node");
if(!res) {
ei_x_free(ebuf);
switch_safe_free(ebuf);
return;
}
if (kazoo_globals.event_stream_preallocate > 0 && ebuf->buffsz > kazoo_globals.event_stream_preallocate) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "increased event stream buffer size to %d\n", ebuf->buffsz);
}
if (switch_queue_trypush(event_stream->queue, ebuf) != SWITCH_STATUS_SUCCESS) {
/* if we couldn't place the cloned event into the listeners */
/* event queue make sure we destroy it, real good like */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error placing the event in the listeners queue\n");
ei_x_free(ebuf);
switch_safe_free(ebuf);
}
}
static void *SWITCH_THREAD_FUNC event_stream_loop(switch_thread_t *thread, void *obj) {
ei_event_stream_t *event_stream = (ei_event_stream_t *) obj;
ei_event_binding_t *event_binding;
switch_sockaddr_t *sa;
uint16_t port;
char ipbuf[48];
const char *ip_addr;
void *pop;
short event_stream_framing;
short event_stream_keepalive;
short ok = 1;
switch_atomic_inc(&kazoo_globals.threads);
switch_assert(event_stream != NULL);
event_stream_framing = event_stream->event_stream_framing;
event_stream_keepalive = event_stream->event_stream_keepalive;
/* figure out what socket we just opened */
switch_socket_addr_get(&sa, SWITCH_FALSE, event_stream->acceptor);
port = switch_sockaddr_get_port(sa);
ip_addr = switch_get_addr(ipbuf, sizeof(ipbuf), sa);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Starting erlang event stream %p on %s:%u for %s <%d.%d.%d>\n"
,(void *)event_stream, ip_addr, port, event_stream->pid.node, event_stream->pid.creation
,event_stream->pid.num, event_stream->pid.serial);
while (switch_test_flag(event_stream, LFLAG_RUNNING) && switch_test_flag(&kazoo_globals, LFLAG_RUNNING) && ok) {
const switch_pollfd_t *fds;
int32_t numfds;
/* check if a new connection is pending */
if (switch_pollset_poll(event_stream->pollset, 0, &numfds, &fds) == SWITCH_STATUS_SUCCESS) {
int32_t i;
for (i = 0; i < numfds; i++) {
switch_socket_t *newsocket;
/* accept the new client connection */
if (switch_socket_accept(&newsocket, event_stream->acceptor, event_stream->pool) == SWITCH_STATUS_SUCCESS) {
switch_sockaddr_t *sa;
if (switch_socket_opt_set(newsocket, SWITCH_SO_NONBLOCK, TRUE)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't set socket as non-blocking\n");
}
if (event_stream_keepalive) {
if (switch_socket_opt_set(newsocket, SWITCH_SO_KEEPALIVE, TRUE)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't set socket keep-alive\n");
}
}
if (switch_socket_opt_set(newsocket, SWITCH_SO_TCP_NODELAY, 1)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't disable Nagle.\n");
}
/* close the current client, if there is one */
close_socket(&event_stream->socket);
switch_mutex_lock(event_stream->socket_mutex);
/* start sending to the new client */
event_stream->socket = newsocket;
switch_socket_addr_get(&sa, SWITCH_TRUE, newsocket);
event_stream->remote_port = switch_sockaddr_get_port(sa);
switch_get_addr(event_stream->remote_ip, sizeof (event_stream->remote_ip), sa);
switch_socket_addr_get(&sa, SWITCH_FALSE, newsocket);
event_stream->local_port = switch_sockaddr_get_port(sa);
switch_get_addr(event_stream->local_ip, sizeof (event_stream->local_ip), sa);
event_stream->connected = SWITCH_TRUE;
event_stream->connected_time = switch_micro_time_now();
switch_mutex_unlock(event_stream->socket_mutex);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Erlang event stream %p client %s:%u\n", (void *)event_stream, event_stream->remote_ip, event_stream->remote_port);
}
}
}
/* if there was an event waiting in our queue send it to the client */
if (ei_queue_pop(event_stream->queue, &pop, event_stream->queue_timeout) == SWITCH_STATUS_SUCCESS) {
ei_x_buff *ebuf = (ei_x_buff *) pop;
if (event_stream->socket) {
switch_size_t size = 1, expected = 0;
switch_status_t status = SWITCH_STATUS_SUCCESS;
if(ebuf->index >= pow(2, 8 * event_stream_framing)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sending frame size %d with insufficient frame capacity, change event_stream_framing here and tcp_packet_type in ecallmgr\n", ebuf->index);
} else {
if(event_stream_framing) {
int index = ebuf->index - MAX_FRAMING;
char byte;
short i = event_stream_framing;
while (i) {
byte = index >> (8 * --i);
ebuf->buff[MAX_FRAMING - i - 1] = byte;
}
}
expected = size = (switch_size_t)ebuf->index - MAX_FRAMING + event_stream_framing;
if((status = switch_socket_send(event_stream->socket, ebuf->buff + (MAX_FRAMING - event_stream_framing), &size)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error %d sending event stream\n", status);
ok = 0;
} else if(expected != size) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error sending event stream, sent bytes is different of expected\n");
ok = 0;
}
}
}
ei_x_free(ebuf);
switch_safe_free(ebuf);
}
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Shutting down erlang event stream %p\n", (void *)event_stream);
/* unbind from the system events */
event_binding = event_stream->bindings;
while(event_binding != NULL) {
switch_event_unbind(&event_binding->node);
event_binding = event_binding->next;
}
event_stream->bindings = NULL;
/* clear and destroy any remaining queued events */
while (switch_queue_trypop(event_stream->queue, &pop) == SWITCH_STATUS_SUCCESS) {
ei_x_buff *ebuf = (ei_x_buff *) pop;
ei_x_free(ebuf);
switch_safe_free(ebuf);
}
/* remove the acceptor pollset */
switch_pollset_remove(event_stream->pollset, event_stream->pollfd);
/* close any open sockets */
close_socket(&event_stream->acceptor);
switch_mutex_lock(event_stream->socket_mutex);
event_stream->connected = SWITCH_FALSE;
close_socket(&event_stream->socket);
switch_mutex_unlock(event_stream->socket_mutex);
switch_mutex_destroy(event_stream->socket_mutex);
/* clean up the memory */
switch_core_destroy_memory_pool(&event_stream->pool);
switch_atomic_dec(&kazoo_globals.threads);
return NULL;
}
ei_event_stream_t *new_event_stream(ei_node_t *ei_node, const erlang_pid *from) {
switch_thread_t *thread;
switch_threadattr_t *thd_attr = NULL;
switch_memory_pool_t *pool = NULL;
ei_event_stream_t *event_stream;
ei_event_stream_t **event_streams = &ei_node->event_streams;
/* create memory pool for this event stream */
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Out of memory: How many Alzheimer's patients does it take to screw in a light bulb? To get to the other side.\n");
return NULL;
}
/* from the memory pool, allocate the event stream structure */
if (!(event_stream = switch_core_alloc(pool, sizeof (*event_stream)))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Out of memory: I may have Alzheimers but at least I dont have Alzheimers.\n");
goto cleanup;
}
/* prepare the event stream */
memset(event_stream, 0, sizeof(*event_stream));
event_stream->bindings = NULL;
event_stream->pool = pool;
event_stream->connected = SWITCH_FALSE;
event_stream->node = ei_node;
event_stream->event_stream_framing = ei_node->event_stream_framing;
event_stream->event_stream_keepalive = ei_node->event_stream_keepalive;
event_stream->queue_timeout = ei_node->event_stream_queue_timeout;
memcpy(&event_stream->pid, from, sizeof(erlang_pid));
switch_queue_create(&event_stream->queue, MAX_QUEUE_LEN, pool);
/* create a socket for accepting the event stream client */
if (!(event_stream->acceptor = create_socket(pool))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Like car accidents, most hardware problems are due to driver error.\n");
goto cleanup;
}
if (switch_socket_opt_set(event_stream->acceptor, SWITCH_SO_NONBLOCK, TRUE)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Hey, it compiles!\n");
goto cleanup;
}
/* create a pollset so we can efficiently check for new client connections */
if (switch_pollset_create(&event_stream->pollset, 1000, pool, 0) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "My software never has bugs. It just develops random features.\n");
goto cleanup;
}
switch_socket_create_pollfd(&event_stream->pollfd, event_stream->acceptor, SWITCH_POLLIN | SWITCH_POLLERR, NULL, pool);
if (switch_pollset_add(event_stream->pollset, event_stream->pollfd) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "If you saw a heat wave, would you wave back?\n");
goto cleanup;
}
switch_mutex_init(&event_stream->socket_mutex, SWITCH_MUTEX_DEFAULT, pool);
/* add the new event stream to the link list
* since the event streams link list is only
* accessed from the same thread no locks
* are required */
if (!*event_streams) {
*event_streams = event_stream;
} else {
event_stream->next = *event_streams;
*event_streams = event_stream;
}
/* when we start we are running */
switch_set_flag(event_stream, LFLAG_RUNNING);
switch_threadattr_create(&thd_attr, event_stream->pool);
switch_threadattr_detach_set(thd_attr, 1);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
switch_thread_create(&thread, thd_attr, event_stream_loop, event_stream, event_stream->pool);
return event_stream;
cleanup:
if (event_stream) {
/* remove the acceptor pollset */
if (event_stream->pollset) {
switch_pollset_remove(event_stream->pollset, event_stream->pollfd);
}
/* close any open sockets */
if (event_stream->acceptor) {
close_socket(&event_stream->acceptor);
}
}
/* clean up the memory */
switch_core_destroy_memory_pool(&pool);
return NULL;
}
unsigned long get_stream_port(const ei_event_stream_t *event_stream) {
switch_sockaddr_t *sa;
switch_socket_addr_get(&sa, SWITCH_FALSE, event_stream->acceptor);
return (unsigned long) switch_sockaddr_get_port(sa);
}
ei_event_stream_t *find_event_stream(ei_event_stream_t *event_stream, const erlang_pid *from) {
while (event_stream != NULL) {
if (ei_compare_pids(&event_stream->pid, from) == SWITCH_STATUS_SUCCESS) {
return event_stream;
}
event_stream = event_stream->next;
}
return NULL;
}
switch_status_t remove_event_stream(ei_event_stream_t **event_streams, const erlang_pid *from) {
ei_event_stream_t *event_stream, *prev = NULL;
int found = 0;
/* if there are no event bindings there is nothing to do */
if (!*event_streams) {
return SWITCH_STATUS_SUCCESS;
}
/* try to find the event stream for the client process */
event_stream = *event_streams;
while(event_stream != NULL) {
if (ei_compare_pids(&event_stream->pid, from) == SWITCH_STATUS_SUCCESS) {
found = 1;
break;
}
prev = event_stream;
event_stream = event_stream->next;
}
if (found) {
/* if we found an event stream remove it from
* from the link list */
if (!prev) {
*event_streams = event_stream->next;
} else {
prev->next = event_stream->next;
}
/* stop the event stream thread */
switch_clear_flag(event_stream, LFLAG_RUNNING);
}
return SWITCH_STATUS_SUCCESS;
}
switch_status_t remove_event_streams(ei_event_stream_t **event_streams) {
ei_event_stream_t *event_stream = *event_streams;
while(event_stream != NULL) {
/* stop the event bindings publisher thread */
switch_clear_flag(event_stream, LFLAG_RUNNING);
event_stream = event_stream->next;
}
*event_streams = NULL;
return SWITCH_STATUS_SUCCESS;
}
void bind_event_profile(ei_event_binding_t *event_binding, kazoo_event_ptr event)
{
switch_event_types_t event_type;
while(event != NULL) {
if (switch_name_event(event->name, &event_type) != SWITCH_STATUS_SUCCESS) {
event_type = SWITCH_EVENT_CUSTOM;
}
if(event_binding->type != SWITCH_EVENT_CUSTOM
&& event_binding->type == event_type) {
break;
}
if (event_binding->type == SWITCH_EVENT_CUSTOM
&& event_binding->type == event_type
&& !strcasecmp(event_binding->subclass_name, event->name)) {
break;
}
event = event->next;
}
event_binding->event = event;
if(event == NULL && (!event_binding->stream->node->legacy)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "event binding to an event without profile in non legacy mode => %s - %s\n",switch_event_name(event_binding->type), event_binding->subclass_name);
}
}
void bind_event_profiles(kazoo_event_ptr event)
{
ei_node_t *ei_node = kazoo_globals.ei_nodes;
while(ei_node) {
ei_event_stream_t *event_streams = ei_node->event_streams;
while(event_streams) {
ei_event_binding_t *bindings = event_streams->bindings;
while(bindings) {
bind_event_profile(bindings, event);
bindings = bindings->next;
}
event_streams = event_streams->next;
}
ei_node = ei_node->next;
}
}
switch_status_t add_event_binding(ei_event_stream_t *event_stream, const char *event_name) {
ei_event_binding_t *event_binding = event_stream->bindings;
switch_event_types_t event_type;
if(!strcasecmp(event_name, "CUSTOM")) {
return SWITCH_STATUS_SUCCESS;
}
if (switch_name_event(event_name, &event_type) != SWITCH_STATUS_SUCCESS) {
event_type = SWITCH_EVENT_CUSTOM;
}
/* check if the event binding already exists, ignore if so */
while(event_binding != NULL) {
if (event_binding->type == SWITCH_EVENT_CUSTOM) {
if(event_type == SWITCH_EVENT_CUSTOM
&& event_name
&& event_binding->subclass_name
&& !strcasecmp(event_name, event_binding->subclass_name)) {
return SWITCH_STATUS_SUCCESS;
}
} else if (event_binding->type == event_type) {
return SWITCH_STATUS_SUCCESS;
}
event_binding = event_binding->next;
}
/* from the event stream memory pool, allocate the event binding structure */
if (!(event_binding = switch_core_alloc(event_stream->pool, sizeof (*event_binding)))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Out of random-access memory, attempting write-only memory\n");
return SWITCH_STATUS_FALSE;
}
/* prepare the event binding struct */
event_binding->stream = event_stream;
event_binding->type = event_type;
if(event_binding->type == SWITCH_EVENT_CUSTOM) {
event_binding->subclass_name = switch_core_strdup(event_stream->pool, event_name);
} else {
event_binding->subclass_name = SWITCH_EVENT_SUBCLASS_ANY;
}
event_binding->next = NULL;
bind_event_profile(event_binding, kazoo_globals.events->events);
/* bind to the event with a unique ID and capture the event_node pointer */
switch_uuid_str(event_binding->id, sizeof(event_binding->id));
if (switch_event_bind_removable(event_binding->id, event_type, event_binding->subclass_name, event_handler, event_binding, &event_binding->node) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to bind to event %s %s!\n"
,switch_event_name(event_binding->type), event_binding->subclass_name ? event_binding->subclass_name : "");
return SWITCH_STATUS_GENERR;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding event binding %s to stream %p for %s <%d.%d.%d>: %s %s\n"
,event_binding->id, (void *)event_stream, event_stream->pid.node, event_stream->pid.creation
,event_stream->pid.num, event_stream->pid.serial, switch_event_name(event_binding->type)
,event_binding->subclass_name ? event_binding->subclass_name : "");
/* add the new binding to the list */
if (!event_stream->bindings) {
event_stream->bindings = event_binding;
} else {
event_binding->next = event_stream->bindings;
event_stream->bindings = event_binding;
}
return SWITCH_STATUS_SUCCESS;
}
switch_status_t remove_event_binding(ei_event_stream_t *event_stream, const switch_event_types_t event_type, const char *subclass_name) {
ei_event_binding_t *event_binding = event_stream->bindings, *prev = NULL;
int found = 0;
/* if there are no bindings then there is nothing to do */
if (!event_binding) {
return SWITCH_STATUS_SUCCESS;
}
/* try to find the event binding specified */
while(event_binding != NULL) {
if (event_binding->type == SWITCH_EVENT_CUSTOM
&& subclass_name
&& event_binding->subclass_name
&& !strcmp(subclass_name, event_binding->subclass_name)) {
found = 1;
break;
} else if (event_binding->type == event_type) {
found = 1;
break;
}
prev = event_binding;
event_binding = event_binding->next;
}
if (found) {
/* if the event binding exists, unbind from the system */
switch_event_unbind(&event_binding->node);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removing event binding %s from %p for %s <%d.%d.%d>: %s %s\n"
,event_binding->id, (void *)event_stream, event_stream->pid.node, event_stream->pid.creation
,event_stream->pid.num, event_stream->pid.serial, switch_event_name(event_binding->type)
,event_binding->subclass_name ? event_binding->subclass_name : "");
/* remove the event binding from the list */
if (!prev) {
event_stream->bindings = event_binding->next;
} else {
prev->next = event_binding->next;
}
}
return SWITCH_STATUS_SUCCESS;
}
switch_status_t remove_event_bindings(ei_event_stream_t *event_stream) {
ei_event_binding_t *event_binding = event_stream->bindings;
/* if there are no bindings then there is nothing to do */
if (!event_binding) {
return SWITCH_STATUS_SUCCESS;
}
/* try to find the event binding specified */
while(event_binding != NULL) {
/* if the event binding exists, unbind from the system */
switch_event_unbind(&event_binding->node);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removing event binding %s from %p for %s <%d.%d.%d>: %s %s\n"
,event_binding->id, (void *)event_stream, event_stream->pid.node, event_stream->pid.creation
,event_stream->pid.num, event_stream->pid.serial, switch_event_name(event_binding->type)
,event_binding->subclass_name ? event_binding->subclass_name : "");
event_binding = event_binding->next;
}
event_stream->bindings = NULL;
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:
*/

View File

@ -1,803 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Karl Anderson <karl@2600hz.com>
* Darren Schreiber <darren@2600hz.com>
*
*
* kazoo_fetch.c -- XML fetch request handler
*
*/
#include "mod_kazoo.h"
static const char *fetch_uuid_sources[] = {
"Fetch-Call-UUID",
"refer-from-channel-id",
"sip_call_id",
NULL
};
static char *xml_section_to_string(switch_xml_section_t section) {
switch(section) {
case SWITCH_XML_SECTION_CONFIG:
return "configuration";
case SWITCH_XML_SECTION_DIRECTORY:
return "directory";
case SWITCH_XML_SECTION_DIALPLAN:
return "dialplan";
case SWITCH_XML_SECTION_CHATPLAN:
return "chatplan";
case SWITCH_XML_SECTION_CHANNELS:
return "channels";
case SWITCH_XML_SECTION_LANGUAGES:
return "languages";
default:
return "unknown";
}
}
static char *expand_vars(char *xml_str) {
char *var, *val;
char *rp = xml_str; /* read pointer */
char *ep, *wp, *buff; /* end pointer, write pointer, write buffer */
if (!(strstr(xml_str, "$${"))) {
return xml_str;
}
switch_zmalloc(buff, strlen(xml_str) * 2);
wp = buff;
ep = buff + (strlen(xml_str) * 2) - 1;
while (*rp && wp < ep) {
if (*rp == '$' && *(rp + 1) == '$' && *(rp + 2) == '{') {
char *e = switch_find_end_paren(rp + 2, '{', '}');
if (e) {
rp += 3;
var = rp;
*e++ = '\0';
rp = e;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "trying to expand %s \n", var);
if ((val = switch_core_get_variable_dup(var))) {
char *p;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "expanded %s to %s\n", var, val);
for (p = val; p && *p && wp <= ep; p++) {
*wp++ = *p;
}
switch_safe_free(val);
}
continue;
}
}
*wp++ = *rp++;
}
*wp++ = '\0';
switch_safe_free(xml_str);
return buff;
}
static switch_xml_t fetch_handler(const char *section, const char *tag_name, const char *key_name, const char *key_value, switch_event_t *params, void *user_data) {
switch_xml_t xml = NULL;
switch_uuid_t uuid;
switch_time_t now = 0;
ei_xml_agent_t *agent = (ei_xml_agent_t *) user_data;
ei_xml_client_t *client;
fetch_handler_t *fetch_handler;
xml_fetch_reply_t reply, *pending, *prev = NULL;
switch_event_t *event = params;
kazoo_fetch_profile_ptr profile = agent->profile;
const char *fetch_call_id;
ei_send_msg_t *send_msg = NULL;
int sent = 0;
now = switch_micro_time_now();
if (!switch_test_flag(&kazoo_globals, LFLAG_RUNNING)) {
return xml;
}
/* read-lock the agent */
switch_thread_rwlock_rdlock(agent->lock);
/* serialize access to current, used to round-robin requests */
/* TODO: check kazoo_globals for round-robin boolean or loop all clients */
switch_mutex_lock(agent->current_client_mutex);
if (!agent->current_client) {
client = agent->clients;
} else {
client = agent->current_client;
}
if (client) {
agent->current_client = client->next;
}
switch_mutex_unlock(agent->current_client_mutex);
/* no client, no work required */
if (!client || !client->fetch_handlers) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "No %s XML erlang handler currently available\n"
,section);
switch_thread_rwlock_unlock(agent->lock);
return xml;
}
/* no profile, no work required */
if (!profile) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "weird case where client is available but there's no profile for %s. try reloading mod_kazoo.\n"
,section);
switch_thread_rwlock_unlock(agent->lock);
return xml;
}
if(event == NULL) {
if (switch_event_create(&event, SWITCH_EVENT_GENERAL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error creating event for fetch handler\n");
return xml;
}
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Switch-Nodename", kazoo_globals.ei_cnode.thisnodename);
/* prepare the reply collector */
switch_uuid_get(&uuid);
switch_uuid_format(reply.uuid_str, &uuid);
reply.next = NULL;
reply.xml_str = NULL;
if(switch_event_get_header(event, "Unique-ID") == NULL) {
int i;
for(i = 0; fetch_uuid_sources[i] != NULL; i++) {
if((fetch_call_id = switch_event_get_header(event, fetch_uuid_sources[i])) != NULL) {
switch_core_session_t *session = NULL;
if((session = switch_core_session_locate(fetch_call_id)) != NULL) {
switch_channel_t *channel = switch_core_session_get_channel(session);
uint32_t verbose = switch_channel_test_flag(channel, CF_VERBOSE_EVENTS);
switch_channel_set_flag(channel, CF_VERBOSE_EVENTS);
switch_channel_event_set_data(channel, event);
switch_channel_set_flag_value(channel, CF_VERBOSE_EVENTS, verbose);
switch_core_session_rwunlock(session);
break;
}
}
}
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Fetch-UUID", reply.uuid_str);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Fetch-Section", section);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Fetch-Tag", tag_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Fetch-Key-Name", key_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Fetch-Key-Value", key_value);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Fetch-Timeout", "%u", profile->fetch_timeout);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Fetch-Timestamp-Micro", "%" SWITCH_UINT64_T_FMT, (uint64_t)now);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Kazoo-Version", VERSION);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Kazoo-Bundle", BUNDLE);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Kazoo-Release", RELEASE);
kz_event_decode(event);
switch_malloc(send_msg, sizeof(*send_msg));
if(client->ei_node->legacy) {
ei_x_new_with_version(&send_msg->buf);
ei_x_encode_tuple_header(&send_msg->buf, 7);
ei_x_encode_atom(&send_msg->buf, "fetch");
ei_x_encode_atom(&send_msg->buf, section);
_ei_x_encode_string(&send_msg->buf, tag_name ? tag_name : "undefined");
_ei_x_encode_string(&send_msg->buf, key_name ? key_name : "undefined");
_ei_x_encode_string(&send_msg->buf, key_value ? key_value : "undefined");
_ei_x_encode_string(&send_msg->buf, reply.uuid_str);
ei_encode_switch_event_headers(&send_msg->buf, event);
} else {
kazoo_message_ptr msg = kazoo_message_create_fetch(event, profile);
ei_x_new_with_version(&send_msg->buf);
ei_x_encode_tuple_header(&send_msg->buf, 2);
ei_x_encode_atom(&send_msg->buf, "fetch");
ei_encode_json(&send_msg->buf, msg->JObj);
kazoo_message_destroy(&msg);
}
/* add our reply placeholder to the replies list */
switch_mutex_lock(agent->replies_mutex);
if (!agent->replies) {
agent->replies = &reply;
} else {
reply.next = agent->replies;
agent->replies = &reply;
}
switch_mutex_unlock(agent->replies_mutex);
fetch_handler = client->fetch_handlers;
while (fetch_handler != NULL && sent == 0) {
memcpy(&send_msg->pid, &fetch_handler->pid, sizeof(erlang_pid));
if (switch_queue_trypush(client->ei_node->send_msgs, send_msg) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to send %s XML request to %s <%d.%d.%d>\n"
,section
,fetch_handler->pid.node
,fetch_handler->pid.creation
,fetch_handler->pid.num
,fetch_handler->pid.serial);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sending %s XML request (%s) to %s <%d.%d.%d>\n"
,section
,reply.uuid_str
,fetch_handler->pid.node
,fetch_handler->pid.creation
,fetch_handler->pid.num
,fetch_handler->pid.serial);
sent = 1;
}
fetch_handler = fetch_handler->next;
}
if(!sent) {
ei_x_free(&send_msg->buf);
switch_safe_free(send_msg);
}
if(params == NULL)
switch_event_destroy(&event);
/* wait for a reply (if there isnt already one...amazingly improbable but lets not take shortcuts */
switch_mutex_lock(agent->replies_mutex);
switch_thread_rwlock_unlock(agent->lock);
if (!reply.xml_str) {
switch_time_t timeout;
timeout = switch_micro_time_now() + 3000000;
while (switch_micro_time_now() < timeout) {
/* unlock the replies list and go to sleep, calculate a three second timeout before we started the loop
* plus 100ms to add a little hysteresis between the timeout and the while loop */
switch_thread_cond_timedwait(agent->new_reply, agent->replies_mutex, (timeout - switch_micro_time_now() + 100000));
/* if we woke up (and therefore have locked replies again) check if we got our reply
* otherwise we either timed-out (the while condition will fail) or one of
* our sibling processes got a reply and we should go back to sleep */
if (reply.xml_str) {
break;
}
}
}
/* find our reply placeholder in the linked list and remove it */
pending = agent->replies;
while (pending != NULL) {
if (pending->uuid_str == reply.uuid_str) {
break;
}
prev = pending;
pending = pending->next;
}
if (pending) {
if (!prev) {
agent->replies = reply.next;
} else {
prev->next = reply.next;
}
}
/* we are done with the replies link-list */
switch_mutex_unlock(agent->replies_mutex);
/* after all that did we get what we were after?! */
if (reply.xml_str) {
/* HELL YA WE DID */
if (kazoo_globals.expand_headers_on_fetch) {
reply.xml_str = expand_vars(reply.xml_str);
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Received %s XML (%s) after %dms: %s\n"
,section
,reply.uuid_str
,(unsigned int) (switch_micro_time_now() - now) / 1000
,reply.xml_str);
if ((xml = switch_xml_parse_str_dynamic(reply.xml_str, SWITCH_FALSE)) == NULL) {
switch_safe_free(reply.xml_str);
}
} else {
/* facepalm */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Request for %s XML (%s) timed-out after %dms\n"
,section
,reply.uuid_str
,(unsigned int) (switch_micro_time_now() - now) / 1000);
}
return xml;
}
void bind_fetch_profile(ei_xml_agent_t *agent, kazoo_config_ptr fetch_handlers)
{
switch_hash_index_t *hi;
kazoo_fetch_profile_ptr val = NULL, ptr = NULL;
if (!fetch_handlers) return;
for (hi = switch_core_hash_first(fetch_handlers->hash); hi; hi = switch_core_hash_next(&hi)) {
switch_core_hash_this(hi, NULL, NULL, (void**) &val);
if (val && val->section == agent->section) {
ptr = val;
break;
}
}
agent->profile = ptr;
switch_safe_free(hi);
}
void rebind_fetch_profiles(kazoo_config_ptr fetch_handlers)
{
if(kazoo_globals.config_fetch_binding != NULL)
bind_fetch_profile((ei_xml_agent_t *) switch_xml_get_binding_user_data(kazoo_globals.config_fetch_binding), fetch_handlers);
if(kazoo_globals.directory_fetch_binding != NULL)
bind_fetch_profile((ei_xml_agent_t *) switch_xml_get_binding_user_data(kazoo_globals.directory_fetch_binding), fetch_handlers);
if(kazoo_globals.dialplan_fetch_binding != NULL)
bind_fetch_profile((ei_xml_agent_t *) switch_xml_get_binding_user_data(kazoo_globals.dialplan_fetch_binding), fetch_handlers);
if(kazoo_globals.channels_fetch_binding != NULL)
bind_fetch_profile((ei_xml_agent_t *) switch_xml_get_binding_user_data(kazoo_globals.channels_fetch_binding), fetch_handlers);
if(kazoo_globals.languages_fetch_binding != NULL)
bind_fetch_profile((ei_xml_agent_t *) switch_xml_get_binding_user_data(kazoo_globals.languages_fetch_binding), fetch_handlers);
if(kazoo_globals.chatplan_fetch_binding != NULL)
bind_fetch_profile((ei_xml_agent_t *) switch_xml_get_binding_user_data(kazoo_globals.chatplan_fetch_binding), fetch_handlers);
}
static switch_status_t bind_fetch_agent(switch_xml_section_t section, switch_xml_binding_t **binding) {
switch_memory_pool_t *pool = NULL;
ei_xml_agent_t *agent;
/* create memory pool for this xml search binging (lives for duration of mod_kazoo runtime) */
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Out of memory: They're not people; they're hippies!\n");
return SWITCH_STATUS_MEMERR;
}
/* allocate some memory to store the fetch bindings for this section */
if (!(agent = switch_core_alloc(pool, sizeof (*agent)))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Out of memory: Oh, Jesus tap-dancing Christ!\n");
return SWITCH_STATUS_MEMERR;
}
/* try to bind to the switch */
if (switch_xml_bind_search_function_ret(fetch_handler, section, agent, binding) != SWITCH_STATUS_SUCCESS) {
switch_core_destroy_memory_pool(&pool);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not bind to FreeSWITCH %s XML requests\n"
,xml_section_to_string(section));
return SWITCH_STATUS_GENERR;
}
agent->pool = pool;
agent->section = section;
switch_thread_rwlock_create(&agent->lock, pool);
agent->clients = NULL;
switch_mutex_init(&agent->current_client_mutex, SWITCH_MUTEX_DEFAULT, pool);
agent->current_client = NULL;
switch_mutex_init(&agent->replies_mutex, SWITCH_MUTEX_DEFAULT, pool);
switch_thread_cond_create(&agent->new_reply, pool);
agent->replies = NULL;
bind_fetch_profile(agent, kazoo_globals.fetch_handlers);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Bound to %s XML requests\n"
,xml_section_to_string(section));
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t unbind_fetch_agent(switch_xml_binding_t **binding) {
ei_xml_agent_t *agent;
ei_xml_client_t *client;
if(*binding == NULL)
return SWITCH_STATUS_GENERR;
/* get a pointer to our user_data */
agent = (ei_xml_agent_t *)switch_xml_get_binding_user_data(*binding);
/* unbind from the switch */
switch_xml_unbind_search_function(binding);
/* LOCK ALL THE THINGS */
switch_thread_rwlock_wrlock(agent->lock);
switch_mutex_lock(agent->current_client_mutex);
switch_mutex_lock(agent->replies_mutex);
/* cleanly destroy each client */
client = agent->clients;
while(client != NULL) {
ei_xml_client_t *tmp_client = client;
fetch_handler_t *fetch_handler;
fetch_handler = client->fetch_handlers;
while(fetch_handler != NULL) {
fetch_handler_t *tmp_fetch_handler = fetch_handler;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removed %s XML handler %s <%d.%d.%d>\n"
,xml_section_to_string(agent->section)
,fetch_handler->pid.node
,fetch_handler->pid.creation
,fetch_handler->pid.num
,fetch_handler->pid.serial);
fetch_handler = fetch_handler->next;
switch_safe_free(tmp_fetch_handler);
}
client = client->next;
switch_safe_free(tmp_client);
}
/* keep the pointers clean, even if its just for a moment */
agent->clients = NULL;
agent->current_client = NULL;
/* release the locks! */
switch_thread_rwlock_unlock(agent->lock);
switch_mutex_unlock(agent->current_client_mutex);
switch_mutex_unlock(agent->replies_mutex);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Unbound from %s XML requests\n"
,xml_section_to_string(agent->section));
/* cleanly destroy the bindings */
switch_thread_rwlock_destroy(agent->lock);
switch_mutex_destroy(agent->current_client_mutex);
switch_mutex_destroy(agent->replies_mutex);
switch_thread_cond_destroy(agent->new_reply);
switch_core_destroy_memory_pool(&agent->pool);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t remove_xml_client(ei_node_t *ei_node, switch_xml_binding_t *binding) {
ei_xml_agent_t *agent;
ei_xml_client_t *client, *prev = NULL;
int found = 0;
if(binding == NULL)
return SWITCH_STATUS_GENERR;
agent = (ei_xml_agent_t *)switch_xml_get_binding_user_data(binding);
/* write-lock the agent */
switch_thread_rwlock_wrlock(agent->lock);
client = agent->clients;
while (client != NULL) {
if (client->ei_node == ei_node) {
found = 1;
break;
}
prev = client;
client = client->next;
}
if (found) {
fetch_handler_t *fetch_handler;
if (!prev) {
agent->clients = client->next;
} else {
prev->next = client->next;
}
/* the mutex lock is not required since we have the write lock
* but hey its fun and safe so do it anyway */
switch_mutex_lock(agent->current_client_mutex);
if (agent->current_client == client) {
agent->current_client = agent->clients;
}
switch_mutex_unlock(agent->current_client_mutex);
fetch_handler = client->fetch_handlers;
while(fetch_handler != NULL) {
fetch_handler_t *tmp_fetch_handler = fetch_handler;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removed %s XML handler %s <%d.%d.%d>\n"
,xml_section_to_string(agent->section)
,fetch_handler->pid.node
,fetch_handler->pid.creation
,fetch_handler->pid.num
,fetch_handler->pid.serial);
fetch_handler = fetch_handler->next;
switch_safe_free(tmp_fetch_handler);
}
switch_safe_free(client);
}
switch_thread_rwlock_unlock(agent->lock);
return SWITCH_STATUS_SUCCESS;
}
static ei_xml_client_t *add_xml_client(ei_node_t *ei_node, ei_xml_agent_t *agent) {
ei_xml_client_t *client;
switch_malloc(client, sizeof(*client));
client->ei_node = ei_node;
client->fetch_handlers = NULL;
client->next = NULL;
if (agent->clients) {
client->next = agent->clients;
}
agent->clients = client;
return client;
}
static ei_xml_client_t *find_xml_client(ei_node_t *ei_node, ei_xml_agent_t *agent) {
ei_xml_client_t *client;
client = agent->clients;
while (client != NULL) {
if (client->ei_node == ei_node) {
return client;
}
client = client->next;
}
return NULL;
}
static switch_status_t remove_fetch_handler(ei_node_t *ei_node, erlang_pid *from, switch_xml_binding_t *binding) {
ei_xml_agent_t *agent;
ei_xml_client_t *client;
fetch_handler_t *fetch_handler, *prev = NULL;
int found = 0;
agent = (ei_xml_agent_t *)switch_xml_get_binding_user_data(binding);
/* write-lock the agent */
switch_thread_rwlock_wrlock(agent->lock);
if (!(client = find_xml_client(ei_node, agent))) {
switch_thread_rwlock_unlock(agent->lock);
return SWITCH_STATUS_SUCCESS;
}
fetch_handler = client->fetch_handlers;
while (fetch_handler != NULL) {
if (ei_compare_pids(&fetch_handler->pid, from) == SWITCH_STATUS_SUCCESS) {
found = 1;
break;
}
prev = fetch_handler;
fetch_handler = fetch_handler->next;
}
if (found) {
if (!prev) {
client->fetch_handlers = fetch_handler->next;
} else {
prev->next = fetch_handler->next;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removed %s XML handler %s <%d.%d.%d>\n"
,xml_section_to_string(agent->section)
,fetch_handler->pid.node
,fetch_handler->pid.creation
,fetch_handler->pid.num
,fetch_handler->pid.serial);
switch_safe_free(fetch_handler);
}
switch_thread_rwlock_unlock(agent->lock);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t handle_api_command_stream(ei_node_t *ei_node, switch_stream_handle_t *stream, switch_xml_binding_t *binding) {
ei_xml_agent_t *agent;
ei_xml_client_t *client;
if (!binding) {
return SWITCH_STATUS_GENERR;
}
agent = (ei_xml_agent_t *)switch_xml_get_binding_user_data(binding);
/* read-lock the agent */
switch_thread_rwlock_rdlock(agent->lock);
client = agent->clients;
while (client != NULL) {
if (client->ei_node == ei_node) {
fetch_handler_t *fetch_handler;
fetch_handler = client->fetch_handlers;
while (fetch_handler != NULL) {
stream->write_function(stream, "XML %s handler <%d.%d.%d>\n"
,xml_section_to_string(agent->section)
,fetch_handler->pid.creation
,fetch_handler->pid.num
,fetch_handler->pid.serial);
fetch_handler = fetch_handler->next;
}
break;
}
client = client->next;
}
switch_thread_rwlock_unlock(agent->lock);
return SWITCH_STATUS_SUCCESS;
}
switch_status_t bind_fetch_agents() {
bind_fetch_agent(SWITCH_XML_SECTION_CONFIG, &kazoo_globals.config_fetch_binding);
bind_fetch_agent(SWITCH_XML_SECTION_DIRECTORY, &kazoo_globals.directory_fetch_binding);
bind_fetch_agent(SWITCH_XML_SECTION_DIALPLAN, &kazoo_globals.dialplan_fetch_binding);
bind_fetch_agent(SWITCH_XML_SECTION_CHANNELS, &kazoo_globals.channels_fetch_binding);
bind_fetch_agent(SWITCH_XML_SECTION_LANGUAGES, &kazoo_globals.languages_fetch_binding);
bind_fetch_agent(SWITCH_XML_SECTION_CHATPLAN, &kazoo_globals.chatplan_fetch_binding);
return SWITCH_STATUS_SUCCESS;
}
switch_status_t unbind_fetch_agents() {
unbind_fetch_agent(&kazoo_globals.config_fetch_binding);
unbind_fetch_agent(&kazoo_globals.directory_fetch_binding);
unbind_fetch_agent(&kazoo_globals.dialplan_fetch_binding);
unbind_fetch_agent(&kazoo_globals.channels_fetch_binding);
unbind_fetch_agent(&kazoo_globals.languages_fetch_binding);
unbind_fetch_agent(&kazoo_globals.chatplan_fetch_binding);
return SWITCH_STATUS_SUCCESS;
}
switch_status_t remove_xml_clients(ei_node_t *ei_node) {
remove_xml_client(ei_node, kazoo_globals.config_fetch_binding);
remove_xml_client(ei_node, kazoo_globals.directory_fetch_binding);
remove_xml_client(ei_node, kazoo_globals.dialplan_fetch_binding);
remove_xml_client(ei_node, kazoo_globals.channels_fetch_binding);
remove_xml_client(ei_node, kazoo_globals.languages_fetch_binding);
remove_xml_client(ei_node, kazoo_globals.chatplan_fetch_binding);
return SWITCH_STATUS_SUCCESS;
}
switch_status_t add_fetch_handler(ei_node_t *ei_node, erlang_pid *from, switch_xml_binding_t *binding) {
ei_xml_agent_t *agent;
ei_xml_client_t *client;
fetch_handler_t *fetch_handler;
if(binding == NULL)
return SWITCH_STATUS_GENERR;
agent = (ei_xml_agent_t *)switch_xml_get_binding_user_data(binding);
/* write-lock the agent */
switch_thread_rwlock_wrlock(agent->lock);
if (!(client = find_xml_client(ei_node, agent))) {
client = add_xml_client(ei_node, agent);
}
fetch_handler = client->fetch_handlers;
while (fetch_handler != NULL) {
if (ei_compare_pids(&fetch_handler->pid, from) == SWITCH_STATUS_SUCCESS) {
switch_thread_rwlock_unlock(agent->lock);
return SWITCH_STATUS_SUCCESS;
}
fetch_handler = fetch_handler->next;
}
switch_malloc(fetch_handler, sizeof(*fetch_handler));
memcpy(&fetch_handler->pid, from, sizeof(erlang_pid));;
fetch_handler->next = NULL;
if (client->fetch_handlers) {
fetch_handler->next = client->fetch_handlers;
}
client->fetch_handlers = fetch_handler;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Added %s XML handler %s <%d.%d.%d>\n"
,xml_section_to_string(agent->section)
,fetch_handler->pid.node
,fetch_handler->pid.creation
,fetch_handler->pid.num
,fetch_handler->pid.serial);
switch_thread_rwlock_unlock(agent->lock);
ei_link(ei_node, ei_self(&kazoo_globals.ei_cnode), from);
return SWITCH_STATUS_SUCCESS;
}
switch_status_t remove_fetch_handlers(ei_node_t *ei_node, erlang_pid *from) {
remove_fetch_handler(ei_node, from, kazoo_globals.config_fetch_binding);
remove_fetch_handler(ei_node, from, kazoo_globals.directory_fetch_binding);
remove_fetch_handler(ei_node, from, kazoo_globals.dialplan_fetch_binding);
remove_fetch_handler(ei_node, from, kazoo_globals.channels_fetch_binding);
remove_fetch_handler(ei_node, from, kazoo_globals.languages_fetch_binding);
remove_fetch_handler(ei_node, from, kazoo_globals.chatplan_fetch_binding);
return SWITCH_STATUS_SUCCESS;
}
switch_status_t fetch_reply(char *uuid_str, char *xml_str, switch_xml_binding_t *binding) {
ei_xml_agent_t *agent;
xml_fetch_reply_t *reply;
switch_status_t status = SWITCH_STATUS_NOTFOUND;
agent = (ei_xml_agent_t *)switch_xml_get_binding_user_data(binding);
switch_mutex_lock(agent->replies_mutex);
reply = agent->replies;
while (reply != NULL) {
if (!strncmp(reply->uuid_str, uuid_str, SWITCH_UUID_FORMATTED_LENGTH)) {
if (!reply->xml_str) {
reply->xml_str = xml_str;
switch_thread_cond_broadcast(agent->new_reply);
status = SWITCH_STATUS_SUCCESS;
}
break;
}
reply = reply->next;
}
switch_mutex_unlock(agent->replies_mutex);
return status;
}
switch_status_t handle_api_command_streams(ei_node_t *ei_node, switch_stream_handle_t *stream) {
handle_api_command_stream(ei_node, stream, kazoo_globals.config_fetch_binding);
handle_api_command_stream(ei_node, stream, kazoo_globals.directory_fetch_binding);
handle_api_command_stream(ei_node, stream, kazoo_globals.dialplan_fetch_binding);
handle_api_command_stream(ei_node, stream, kazoo_globals.channels_fetch_binding);
handle_api_command_stream(ei_node, stream, kazoo_globals.languages_fetch_binding);
handle_api_command_stream(ei_node, stream, kazoo_globals.chatplan_fetch_binding);
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:
*/

View File

@ -1,203 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Based on mod_skel by
* Anthony Minessale II <anthm@freeswitch.org>
*
* Contributor(s):
*
* Daniel Bryars <danb@aeriandi.com>
* Tim Brown <tim.brown@aeriandi.com>
* Anthony Minessale II <anthm@freeswitch.org>
* William King <william.king@quentustech.com>
* Mike Jerris <mike@jerris.com>
*
* kazoo.c -- Sends FreeSWITCH events to an AMQP broker
*
*/
#ifndef KAZOO_FIELDS_H
#define KAZOO_FIELDS_H
#include <switch.h>
#define MAX_LIST_FIELDS 25
typedef struct kazoo_log_levels kazoo_loglevels_t;
typedef kazoo_loglevels_t *kazoo_loglevels_ptr;
struct kazoo_log_levels
{
switch_log_level_t success_log_level;
switch_log_level_t failed_log_level;
switch_log_level_t warn_log_level;
switch_log_level_t info_log_level;
switch_log_level_t time_log_level;
switch_log_level_t filtered_event_log_level;
switch_log_level_t filtered_field_log_level;
switch_log_level_t trace_log_level;
switch_log_level_t debug_log_level;
switch_log_level_t error_log_level;
switch_log_level_t hashing_log_level;
};
typedef struct kazoo_logging kazoo_logging_t;
typedef kazoo_logging_t *kazoo_logging_ptr;
struct kazoo_logging
{
kazoo_loglevels_ptr levels;
const char *profile_name;
const char *event_name;
};
typedef struct kazoo_list_s {
char *value[MAX_LIST_FIELDS];
int size;
} kazoo_list_t;
typedef enum {
FILTER_COMPARE_REGEX,
FILTER_COMPARE_LIST,
FILTER_COMPARE_VALUE,
FILTER_COMPARE_PREFIX,
FILTER_COMPARE_EXISTS,
FILTER_COMPARE_FIELD
} kazoo_filter_compare_type;
typedef enum {
FILTER_EXCLUDE,
FILTER_INCLUDE,
FILTER_ENSURE
} kazoo_filter_type;
typedef struct kazoo_filter_t {
kazoo_filter_type type;
kazoo_filter_compare_type compare;
char* name;
char* value;
kazoo_list_t list;
struct kazoo_filter_t* next;
} kazoo_filter, *kazoo_filter_ptr;
typedef enum {
JSON_NONE,
JSON_STRING,
JSON_NUMBER,
JSON_BOOLEAN,
JSON_OBJECT,
JSON_RAW
} kazoo_json_field_type;
typedef enum {
FIELD_NONE,
FIELD_COPY,
FIELD_STATIC,
FIELD_FIRST_OF,
FIELD_EXPAND,
FIELD_PREFIX,
FIELD_OBJECT,
FIELD_GROUP,
FIELD_REFERENCE
} kazoo_field_type;
typedef struct kazoo_field_t kazoo_field;
typedef kazoo_field *kazoo_field_ptr;
typedef struct kazoo_fields_t kazoo_fields;
typedef kazoo_fields *kazoo_fields_ptr;
typedef struct kazoo_definition_t kazoo_definition;
typedef kazoo_definition *kazoo_definition_ptr;
struct kazoo_field_t {
char* name;
char* value;
char* as;
kazoo_list_t list;
switch_bool_t exclude_prefix;
kazoo_field_type in_type;
kazoo_json_field_type out_type;
int out_type_as_array;
kazoo_filter_ptr filter;
kazoo_definition_ptr ref;
kazoo_field_ptr next;
kazoo_fields_ptr children;
};
struct kazoo_fields_t {
kazoo_field_ptr head;
int verbose;
};
struct kazoo_definition_t {
char* name;
kazoo_field_ptr head;
kazoo_filter_ptr filter;
};
struct kazoo_event {
kazoo_event_profile_ptr profile;
char *name;
kazoo_fields_ptr fields;
kazoo_filter_ptr filter;
kazoo_loglevels_ptr logging;
kazoo_event_t* next;
};
struct kazoo_event_profile {
char *name;
kazoo_config_ptr root;
switch_bool_t running;
switch_memory_pool_t *pool;
kazoo_filter_ptr filter;
kazoo_fields_ptr fields;
kazoo_event_ptr events;
kazoo_loglevels_ptr logging;
};
struct kazoo_fetch_profile {
char *name;
kazoo_config_ptr root;
switch_bool_t running;
switch_memory_pool_t *pool;
kazoo_fields_ptr fields;
int fetch_timeout;
switch_mutex_t *fetch_reply_mutex;
switch_hash_t *fetch_reply_hash;
switch_xml_binding_t *fetch_binding;
switch_xml_section_t section;
kazoo_loglevels_ptr logging;
};
#endif /* KAZOO_FIELDS_H */

View File

@ -1,488 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Based on mod_skel by
* Anthony Minessale II <anthm@freeswitch.org>
*
* Contributor(s):
*
* Daniel Bryars <danb@aeriandi.com>
* Tim Brown <tim.brown@aeriandi.com>
* Anthony Minessale II <anthm@freeswitch.org>
* William King <william.king@quentustech.com>
* Mike Jerris <mike@jerris.com>
*
* kazoo.c -- Sends FreeSWITCH events to an AMQP broker
*
*/
#include "mod_kazoo.h"
/* deletes then add */
void kazoo_cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
{
cJSON_DeleteItemFromObject(object, string);
cJSON_AddItemToObject(object, string, item);
}
static int inline filter_compare(switch_event_t* evt, kazoo_filter_ptr filter, kazoo_logging_ptr logging)
{
switch_event_header_t *header;
int hasValue = 0, n;
char *value = NULL, *expr = NULL;
switch(filter->compare) {
case FILTER_COMPARE_EXISTS:
hasValue = switch_event_get_header(evt, filter->name) != NULL ? 1 : 0;
switch_log_printf(SWITCH_CHANNEL_LOG, logging->levels->trace_log_level, "profile[%s] event %s checking if %s exists => %s\n", logging->profile_name, logging->event_name, filter->name, hasValue ? "true" : "false");
break;
case FILTER_COMPARE_VALUE:
if (*filter->name == '$') {
value = expr = kz_event_expand_headers(evt, filter->name);
} else {
value = switch_event_get_header(evt, filter->name);
}
hasValue = value ? !strcmp(value, filter->value) : 0;
switch_log_printf(SWITCH_CHANNEL_LOG, logging->levels->trace_log_level, "profile[%s] event %s compare value %s to %s => %s == %s => %s\n", logging->profile_name, logging->event_name, filter->name, filter->value, value, filter->value, hasValue ? "true" : "false");
break;
case FILTER_COMPARE_FIELD:
if (*filter->name == '$') {
value = expr = kz_event_expand_headers(evt, filter->name);
} else {
value = switch_event_get_header(evt, filter->name);
}
hasValue = value ? !strcmp(value, switch_event_get_header_nil(evt, filter->value)) : 0;
switch_log_printf(SWITCH_CHANNEL_LOG, logging->levels->trace_log_level, "profile[%s] event %s compare field %s to %s => %s == %s => %s\n", logging->profile_name, logging->event_name, filter->name, filter->value, value, switch_event_get_header_nil(evt, filter->value), hasValue ? "true" : "false");
break;
case FILTER_COMPARE_PREFIX:
for (header = evt->headers; header; header = header->next) {
if(!strncmp(header->name, filter->value, strlen(filter->value))) {
hasValue = 1;
break;
}
}
break;
case FILTER_COMPARE_LIST:
if (*filter->name == '$') {
value = expr = kz_event_expand_headers(evt, filter->name);
} else {
value = switch_event_get_header(evt, filter->name);
}
if(value) {
for(n = 0; n < filter->list.size; n++) {
if(!strncmp(value, filter->list.value[n], strlen(filter->list.value[n]))) {
hasValue = 1;
break;
}
}
}
break;
case FILTER_COMPARE_REGEX:
break;
default:
break;
}
switch_safe_free(expr);
return hasValue;
}
static kazoo_filter_ptr inline filter_event(switch_event_t* evt, kazoo_filter_ptr filter, kazoo_logging_ptr logging)
{
while(filter) {
int hasValue = filter_compare(evt, filter, logging);
if(filter->type == FILTER_EXCLUDE) {
if(hasValue)
break;
} else if(filter->type == FILTER_INCLUDE) {
if(!hasValue)
break;
}
filter = filter->next;
}
return filter;
}
static void kazoo_event_init_json_fields(switch_event_t *event, cJSON *json)
{
switch_event_header_t *hp;
for (hp = event->headers; hp; hp = hp->next) {
if (strncmp(hp->name, "_json_", 6)) {
if (hp->idx) {
cJSON *a = cJSON_CreateArray();
int i;
for(i = 0; i < hp->idx; i++) {
cJSON_AddItemToArray(a, cJSON_CreateString(hp->array[i]));
}
cJSON_AddItemToObject(json, hp->name, a);
} else {
cJSON_AddItemToObject(json, hp->name, cJSON_CreateString(hp->value));
}
}
}
}
static switch_status_t kazoo_event_init_json(kazoo_fields_ptr fields1, kazoo_fields_ptr fields2, switch_event_t* evt, cJSON** clone)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
if( (fields2 && fields2->verbose)
|| (fields1 && fields1->verbose)
|| ( (!fields2) && (!fields1)) ) {
*clone = cJSON_CreateObject();
if((*clone) == NULL) {
status = SWITCH_STATUS_GENERR;
} else {
kazoo_event_init_json_fields(evt, *clone);
}
} else {
*clone = cJSON_CreateObject();
if((*clone) == NULL) {
status = SWITCH_STATUS_GENERR;
}
}
return status;
}
static cJSON * kazoo_event_json_value(kazoo_json_field_type type, const char *value) {
cJSON *item = NULL;
switch(type) {
case JSON_STRING:
item = cJSON_CreateString(value);
break;
case JSON_NUMBER:
item = cJSON_CreateNumber(strtod(value, NULL));
break;
case JSON_BOOLEAN:
item = cJSON_CreateBool(switch_true(value));
break;
case JSON_OBJECT:
item = cJSON_CreateObject();
break;
case JSON_RAW:
item = cJSON_Parse(value);
if (!item) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "parse from raw error!\n");
item = cJSON_CreateRaw(value);
}
break;
default:
break;
};
return item;
}
static cJSON * kazoo_event_add_json_value(cJSON *dst, kazoo_field_ptr field, const char *as, const char *value) {
cJSON *item = NULL;
if(value || field->out_type == JSON_OBJECT) {
if((item = kazoo_event_json_value(field->out_type, value)) != NULL) {
kazoo_cJSON_AddItemToObject(dst, as, item);
}
}
return item;
}
cJSON * kazoo_event_add_field_to_json(cJSON *dst, switch_event_t *src, kazoo_field_ptr field)
{
switch_event_header_t *header;
char *expanded;
int i, n;
cJSON *item = NULL;
switch(field->in_type) {
case FIELD_COPY:
if (!strcmp(field->name, "_body")) {
item = kazoo_event_add_json_value(dst, field, field->as ? field->as : field->name, src->body);
} else if((header = switch_event_get_header_ptr(src, field->name)) != NULL) {
if (header->idx) {
item = cJSON_CreateArray();
for(i = 0; i < header->idx; i++) {
cJSON_AddItemToArray(item, kazoo_event_json_value(field->out_type, header->array[i]));
}
kazoo_cJSON_AddItemToObject(dst, field->as ? field->as : field->name, item);
} else if (field->out_type_as_array) {
item = cJSON_CreateArray();
cJSON_AddItemToArray(item, kazoo_event_json_value(field->out_type, header->value));
kazoo_cJSON_AddItemToObject(dst, field->as ? field->as : field->name, item);
} else {
item = kazoo_event_add_json_value(dst, field, field->as ? field->as : field->name, header->value);
}
}
break;
case FIELD_EXPAND:
expanded = kz_event_expand_headers(src, field->value);
if(expanded != NULL && !zstr(expanded)) {
item = kazoo_event_add_json_value(dst, field, field->as ? field->as : field->name, expanded);
}
if (expanded != field->value) {
switch_safe_free(expanded);
}
break;
case FIELD_FIRST_OF:
for(n = 0; n < field->list.size; n++) {
if(*field->list.value[n] == '#') {
item = kazoo_event_add_json_value(dst, field, field->as ? field->as : field->name, ++field->list.value[n]);
break;
} else {
header = switch_event_get_header_ptr(src, field->list.value[n]);
if(header) {
if (header->idx) {
item = cJSON_CreateArray();
for(i = 0; i < header->idx; i++) {
cJSON_AddItemToArray(item, kazoo_event_json_value(field->out_type, header->array[i]));
}
kazoo_cJSON_AddItemToObject(dst, field->as ? field->as : field->name, item);
} else {
item = kazoo_event_add_json_value(dst, field, field->as ? field->as : field->name, header->value);
}
break;
}
}
}
break;
case FIELD_PREFIX:
for (header = src->headers; header; header = header->next) {
if(!strncmp(header->name, field->name, strlen(field->name))) {
if (header->idx) {
cJSON *array = cJSON_CreateArray();
for(i = 0; i < header->idx; i++) {
cJSON_AddItemToArray(array, kazoo_event_json_value(field->out_type, header->array[i]));
}
kazoo_cJSON_AddItemToObject(dst, field->exclude_prefix ? header->name+strlen(field->name) : header->name, array);
} else {
kazoo_event_add_json_value(dst, field, field->exclude_prefix ? header->name+strlen(field->name) : header->name, header->value);
}
}
}
break;
case FIELD_STATIC:
item = kazoo_event_add_json_value(dst, field, field->name, field->value);
break;
case FIELD_GROUP:
item = dst;
break;
default:
break;
}
return item;
}
static switch_status_t kazoo_event_add_fields_to_json(kazoo_logging_ptr logging, cJSON *dst, switch_event_t *src, kazoo_field_ptr field) {
kazoo_filter_ptr filter;
cJSON *item = NULL;
while(field) {
if(field->in_type == FIELD_REFERENCE) {
if(field->ref) {
if((filter = filter_event(src, field->ref->filter, logging)) != NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, logging->levels->filtered_field_log_level, "profile[%s] event %s, referenced field %s filtered by settings %s : %s\n", logging->profile_name, logging->event_name, field->ref->name, filter->name, filter->value);
} else {
kazoo_event_add_fields_to_json(logging, dst, src, field->ref->head);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "profile[%s] event %s, referenced field %s not found\n", logging->profile_name, logging->event_name, field->name);
}
} else {
if((filter = filter_event(src, field->filter, logging)) != NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, logging->levels->filtered_field_log_level, "profile[%s] event %s, field %s filtered by settings %s : %s\n", logging->profile_name, logging->event_name, field->name, filter->name, filter->value);
} else {
item = kazoo_event_add_field_to_json(dst, src, field);
if(field->children && item != NULL) {
if(field->children->verbose && field->out_type == JSON_OBJECT) {
kazoo_event_init_json_fields(src, item);
}
kazoo_event_add_fields_to_json(logging, field->out_type == JSON_OBJECT ? item : dst, src, field->children->head);
}
}
}
field = field->next;
}
return SWITCH_STATUS_SUCCESS;
}
#define EVENT_TIMESTAMP_FIELD "Event-Date-Timestamp"
#define JSON_TIMESTAMP_FIELD "Event-Timestamp"
static switch_status_t kazoo_event_add_timestamp(switch_event_t* evt, cJSON* JObj)
{
switch_event_header_t *header;
cJSON *item = NULL;
if((header = switch_event_get_header_ptr(evt, EVENT_TIMESTAMP_FIELD)) != NULL) {
if ((item = kazoo_event_json_value(JSON_NUMBER, header->value)) != NULL) {
kazoo_cJSON_AddItemToObject(JObj, JSON_TIMESTAMP_FIELD, item);
return SWITCH_STATUS_SUCCESS;
}
}
return SWITCH_STATUS_NOTFOUND;
}
kazoo_message_ptr kazoo_message_create_event(switch_event_t* evt, kazoo_event_ptr event, kazoo_event_profile_ptr profile)
{
kazoo_message_ptr message;
cJSON *JObj = NULL;
kazoo_filter_ptr filtered;
kazoo_logging_t logging;
logging.levels = profile->logging;
logging.event_name = evt->subclass_name ? evt->subclass_name : switch_event_get_header_nil(evt, "Event-Name");
logging.profile_name = profile->name;
message = malloc(sizeof(kazoo_message_t));
if(message == NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error allocating memory for serializing event to json\n");
return NULL;
}
memset(message, 0, sizeof(kazoo_message_t));
if(profile->filter) {
// filtering
if((filtered = filter_event(evt, profile->filter, &logging)) != NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, logging.levels->filtered_event_log_level, "profile[%s] event %s filtered by profile settings %s : %s\n", logging.profile_name, logging.event_name, filtered->name, filtered->value);
kazoo_message_destroy(&message);
return NULL;
}
}
if (event->logging) {
logging.levels = event->logging;
}
if (event && event->filter) {
if((filtered = filter_event(evt, event->filter, &logging)) != NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, logging.levels->filtered_event_log_level, "profile[%s] event %s filtered by event settings %s : %s\n", logging.profile_name, logging.event_name, filtered->name, filtered->value);
kazoo_message_destroy(&message);
return NULL;
}
}
kazoo_event_init_json(profile->fields, event ? event->fields : NULL, evt, &JObj);
kazoo_event_add_timestamp(evt, JObj);
if(profile->fields)
kazoo_event_add_fields_to_json(&logging, JObj, evt, profile->fields->head);
if(event && event->fields)
kazoo_event_add_fields_to_json(&logging, JObj, evt, event->fields->head);
message->JObj = JObj;
return message;
}
kazoo_message_ptr kazoo_message_create_fetch(switch_event_t* evt, kazoo_fetch_profile_ptr profile)
{
kazoo_message_ptr message;
cJSON *JObj = NULL;
kazoo_logging_t logging;
logging.levels = profile->logging;
logging.event_name = switch_event_get_header_nil(evt, "Event-Name");
logging.profile_name = profile->name;
message = malloc(sizeof(kazoo_message_t));
if(message == NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error allocating memory for serializing event to json\n");
return NULL;
}
memset(message, 0, sizeof(kazoo_message_t));
kazoo_event_init_json(profile->fields, NULL, evt, &JObj);
kazoo_event_add_timestamp(evt, JObj);
if(profile->fields)
kazoo_event_add_fields_to_json(&logging, JObj, evt, profile->fields->head);
message->JObj = JObj;
return message;
}
void kazoo_message_destroy(kazoo_message_ptr *msg)
{
if (!msg || !*msg) return;
if((*msg)->JObj != NULL)
cJSON_Delete((*msg)->JObj);
switch_safe_free(*msg);
}
/* 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
*/

View File

@ -1,66 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Based on mod_skel by
* Anthony Minessale II <anthm@freeswitch.org>
*
* Contributor(s):
*
* Daniel Bryars <danb@aeriandi.com>
* Tim Brown <tim.brown@aeriandi.com>
* Anthony Minessale II <anthm@freeswitch.org>
* William King <william.king@quentustech.com>
* Mike Jerris <mike@jerris.com>
*
* kazoo.c -- Sends FreeSWITCH events to an AMQP broker
*
*/
#ifndef KAZOO_MESSAGE_H
#define KAZOO_MESSAGE_H
#include <switch.h>
typedef struct {
uint64_t timestamp;
uint64_t start;
uint64_t filter;
uint64_t serialize;
uint64_t print;
uint64_t rk;
} kazoo_message_times_t, *kazoo_message_times_ptr;
typedef struct {
cJSON *JObj;
} kazoo_message_t, *kazoo_message_ptr;
void kazoo_cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
cJSON * kazoo_event_add_field_to_json(cJSON *dst, switch_event_t *src, kazoo_field_ptr field);
kazoo_message_ptr kazoo_message_create_event(switch_event_t* evt, kazoo_event_ptr event, kazoo_event_profile_ptr profile);
kazoo_message_ptr kazoo_message_create_fetch(switch_event_t* evt, kazoo_fetch_profile_ptr profile);
void kazoo_message_destroy(kazoo_message_ptr *msg);
#endif /* KAZOO_MESSAGE_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,666 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Luis Azedo <luis@2600hz.com>
*
* mod_hacks.c -- hacks with state handlers
*
*/
#include "mod_kazoo.h"
static char *TWEAK_NAMES[] = {
"interaction-id",
"export-vars",
"switch-uri",
"replaces-call-id",
"loopback-vars",
"caller-id",
"transfers",
"bridge",
"bridge-replaces-aleg",
"bridge-replaces-call-id",
"bridge-variables",
"restore-caller-id-on-blind-xfer"
};
static const char *bridge_variables[] = {
"Call-Control-Queue",
"Call-Control-PID",
"Call-Control-Node",
INTERACTION_VARIABLE,
"ecallmgr_Ecallmgr-Node",
"sip_h_k-cid",
"Switch-URI",
"Switch-URL",
NULL
};
static switch_status_t kz_tweaks_signal_bridge_on_hangup(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_event_t *my_event;
const char *peer_uuid = switch_channel_get_variable(channel, "Bridge-B-Unique-ID");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "tweak signal bridge on hangup: %s , %s\n", switch_core_session_get_uuid(session), peer_uuid);
if (switch_event_create(&my_event, SWITCH_EVENT_CHANNEL_UNBRIDGE) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(my_event, SWITCH_STACK_BOTTOM, "Bridge-A-Unique-ID", switch_core_session_get_uuid(session));
switch_event_add_header_string(my_event, SWITCH_STACK_BOTTOM, "Bridge-B-Unique-ID", peer_uuid);
switch_channel_event_set_data(channel, my_event);
switch_event_fire(&my_event);
}
return SWITCH_STATUS_SUCCESS;
}
static const switch_state_handler_table_t kz_tweaks_signal_bridge_state_handlers = {
/*.on_init */ NULL,
/*.on_routing */ NULL,
/*.on_execute */ NULL,
/*.on_hangup */ kz_tweaks_signal_bridge_on_hangup,
/*.on_exchange_media */ NULL,
/*.on_soft_execute */ NULL,
/*.on_consume_media */ NULL,
/*.on_hibernate */ NULL,
/*.on_reset */ NULL,
/*.on_park */ NULL,
/*.on_reporting */ NULL,
/*.on_destroy */ NULL
};
static void kz_tweaks_handle_bridge_variables(switch_event_t *event)
{
switch_core_session_t *a_session = NULL, *b_session = NULL;
const char *a_leg = switch_event_get_header(event, "Bridge-A-Unique-ID");
const char *b_leg = switch_event_get_header(event, "Bridge-B-Unique-ID");
const char *reentry = switch_event_get_header(event, "Bridge-Event-Processed");
int i;
if (!kz_test_tweak(KZ_TWEAK_BRIDGE_VARIABLES)) return;
if(reentry) return;
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(a_leg), SWITCH_LOG_DEBUG, "tweak bridge event handler: variables : %s , %s\n", a_leg, b_leg);
if (a_leg && (a_session = switch_core_session_locate(a_leg)) != NULL) {
switch_channel_t *a_channel = switch_core_session_get_channel(a_session);
switch_channel_timetable_t *a_times = switch_channel_get_timetable(a_channel);
if(b_leg && (b_session = switch_core_session_locate(b_leg)) != NULL) {
switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
switch_channel_timetable_t *b_times = switch_channel_get_timetable(b_channel);
if (a_times->created <= b_times->created) {
for(i = 0; bridge_variables[i] != NULL; i++) {
const char *val = switch_channel_get_variable_dup(a_channel, bridge_variables[i], SWITCH_FALSE, -1);
switch_channel_set_variable(b_channel, bridge_variables[i], val);
}
} else {
for(i = 0; bridge_variables[i] != NULL; i++) {
const char *val = switch_channel_get_variable_dup(b_channel, bridge_variables[i], SWITCH_FALSE, -1);
switch_channel_set_variable(a_channel, bridge_variables[i], val);
}
}
switch_core_session_rwunlock(b_session);
}
switch_core_session_rwunlock(a_session);
} else {
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(a_leg), SWITCH_LOG_DEBUG1, "NOT FOUND : %s\n", a_leg);
}
}
static void kz_tweaks_handle_bridge_replaces_call_id(switch_event_t *event)
{
switch_event_t *my_event;
const char *replaced_call_id = switch_event_get_header(event, "variable_sip_replaces_call_id");
const char *peer_uuid = switch_event_get_header(event, "Unique-ID");
const char *reentry = switch_event_get_header(event, "Bridge-Event-Processed");
if (!kz_test_tweak(KZ_TWEAK_BRIDGE_REPLACES_CALL_ID)) return;
if(reentry) return;
if(replaced_call_id) {
switch_core_session_t *call_session = NULL;
const char *call_id = switch_event_get_header(event, "Bridge-B-Unique-ID");
if (call_id && (call_session = switch_core_session_locate(call_id)) != NULL) {
switch_channel_t *call_channel = switch_core_session_get_channel(call_session);
if (switch_event_create(&my_event, SWITCH_EVENT_CHANNEL_BRIDGE) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(my_event, SWITCH_STACK_BOTTOM, "Bridge-A-Unique-ID", switch_core_session_get_uuid(call_session));
switch_event_add_header_string(my_event, SWITCH_STACK_BOTTOM, "Bridge-B-Unique-ID", peer_uuid);
switch_event_add_header_string(my_event, SWITCH_STACK_BOTTOM, "Bridge-Event-Processed", "true");
switch_channel_event_set_data(call_channel, my_event);
switch_event_fire(&my_event);
}
switch_channel_set_variable(call_channel, "Bridge-B-Unique-ID", peer_uuid);
switch_channel_add_state_handler(call_channel, &kz_tweaks_signal_bridge_state_handlers);
switch_core_session_rwunlock(call_session);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "NOT FOUND : %s\n", call_id);
}
}
}
static void kz_tweaks_channel_bridge_event_handler(switch_event_t *event)
{
if (!kz_test_tweak(KZ_TWEAK_BRIDGE)) return;
kz_tweaks_handle_bridge_replaces_call_id(event);
kz_tweaks_handle_bridge_variables(event);
}
// TRANSFERS
static void kz_tweaks_channel_replaced_event_handler(switch_event_t *event)
{
const char *uuid = switch_event_get_header(event, "Unique-ID");
const char *replaced_by = switch_event_get_header(event, "att_xfer_replaced_by");
if (!kz_test_tweak(KZ_TWEAK_TRANSFERS)) return;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "REPLACED : %s , %s\n", uuid, replaced_by);
}
static void kz_tweaks_channel_intercepted_event_handler(switch_event_t *event)
{
const char *uuid = switch_event_get_header(event, "Unique-ID");
const char *peer_uuid = switch_event_get_header(event, "intercepted_by");
if (!kz_test_tweak(KZ_TWEAK_TRANSFERS)) return;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "INTERCEPTED : %s => %s\n", uuid, peer_uuid);
}
static void kz_tweaks_channel_transferor_event_handler(switch_event_t *event)
{
switch_core_session_t *uuid_session = NULL;
switch_event_t *evt = NULL;
const char *uuid = switch_event_get_header(event, "Unique-ID");
const char *orig_call_id = switch_event_get_header(event, "att_xfer_original_call_id");
const char *dest_peer_uuid = switch_event_get_header(event, "att_xfer_destination_peer_uuid");
const char *dest_call_id = switch_event_get_header(event, "att_xfer_destination_call_id");
const char *file = switch_event_get_header(event, "Event-Calling-File");
const char *func = switch_event_get_header(event, "Event-Calling-Function");
const char *line = switch_event_get_header(event, "Event-Calling-Line-Number");
if (!kz_test_tweak(KZ_TWEAK_TRANSFERS)) return;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR : %s , %s , %s, %s, %s , %s , %s \n", uuid, orig_call_id, dest_peer_uuid, dest_call_id, file, func, line);
if ((uuid_session = switch_core_session_locate(uuid)) != NULL) {
switch_channel_t *uuid_channel = switch_core_session_get_channel(uuid_session);
const char* interaction_id = switch_channel_get_variable_dup(uuid_channel, INTERACTION_VARIABLE, SWITCH_TRUE, -1);
// set to uuid & peer_uuid
if(interaction_id != NULL) {
switch_core_session_t *session = NULL;
if(dest_call_id && (session = switch_core_session_locate(dest_call_id)) != NULL) {
switch_channel_t *channel = switch_core_session_get_channel(session);
const char* prv_interaction_id = switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_TRUE, -1);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "LOCATING UUID PRV : %s : %s\n", prv_interaction_id, interaction_id);
switch_channel_set_variable(channel, INTERACTION_VARIABLE, interaction_id);
if (switch_event_create(&evt, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, evt);
switch_event_fire(&evt);
}
switch_core_session_rwunlock(session);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR NO UUID SESSION: %s , %s , %s \n", uuid, dest_call_id, dest_peer_uuid);
}
if(dest_peer_uuid && (session = switch_core_session_locate(dest_peer_uuid)) != NULL) {
switch_channel_t *channel = switch_core_session_get_channel(session);
const char* prv_interaction_id = switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_TRUE, -1);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "LOCATING PEER UUID PRV : %s : %s\n", prv_interaction_id, interaction_id);
switch_channel_set_variable(channel, INTERACTION_VARIABLE, interaction_id);
if (switch_event_create(&evt, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, evt);
switch_event_fire(&evt);
}
switch_core_session_rwunlock(session);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR NO PEER SESSION: %s , %s , %s \n", uuid, dest_call_id, dest_peer_uuid);
}
if(orig_call_id && (session = switch_core_session_locate(orig_call_id)) != NULL) {
switch_channel_t *channel = switch_core_session_get_channel(session);
const char* prv_interaction_id = switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_TRUE, -1);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "LOCATING PEER UUID PRV : %s : %s\n", prv_interaction_id, interaction_id);
switch_channel_set_variable(channel, INTERACTION_VARIABLE, interaction_id);
if (switch_event_create(&evt, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, evt);
switch_event_fire(&evt);
}
switch_core_session_rwunlock(session);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR NO PEER SESSION: %s , %s , %s \n", uuid, dest_call_id, dest_peer_uuid);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR ID = NULL : %s , %s , %s \n", uuid, dest_call_id, dest_peer_uuid);
}
switch_core_session_rwunlock(uuid_session);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SESSION NOT FOUND : %s\n", uuid);
}
}
static void kz_tweaks_channel_transferee_event_handler(switch_event_t *event)
{
const char *uuid = switch_event_get_header(event, "Unique-ID");
const char *replaced_by_uuid = switch_event_get_header(event, "att_xfer_replaced_call_id");
if (!kz_test_tweak(KZ_TWEAK_TRANSFERS)) return;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEREE : %s replaced by %s\n", uuid, replaced_by_uuid);
}
// END TRANSFERS
static switch_status_t kz_tweaks_handle_loopback(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_channel_t *a_channel = NULL;
const char * loopback_leg = NULL;
const char * loopback_aleg = NULL;
switch_core_session_t *a_session = NULL;
switch_event_t *event = NULL;
switch_event_header_t *header = NULL;
switch_event_t *to_add = NULL;
switch_event_t *to_remove = NULL;
switch_caller_profile_t *caller;
int n = 0;
if (!kz_test_tweak(KZ_TWEAK_LOOPBACK_VARS)) {
return SWITCH_STATUS_SUCCESS;
}
caller = switch_channel_get_caller_profile(channel);
if(strncmp(caller->source, "mod_loopback", 12))
return SWITCH_STATUS_SUCCESS;
if((loopback_leg = switch_channel_get_variable(channel, "loopback_leg")) == NULL)
return SWITCH_STATUS_SUCCESS;
if(strncmp(loopback_leg, "B", 1))
return SWITCH_STATUS_SUCCESS;
switch_channel_get_variables(channel, &event);
switch_event_create_plain(&to_add, SWITCH_EVENT_CHANNEL_DATA);
switch_event_create_plain(&to_remove, SWITCH_EVENT_CHANNEL_DATA);
for(header = event->headers; header; header = header->next) {
if(!strncmp(header->name, "Export-Loopback-", 16)) {
kz_switch_event_add_variable_name_printf(to_add, SWITCH_STACK_BOTTOM, header->value, "%s", header->name+16);
switch_channel_set_variable(channel, header->name, NULL);
n++;
} else if(!strncmp(header->name, "sip_loopback_", 13)) {
kz_switch_event_add_variable_name_printf(to_add, SWITCH_STACK_BOTTOM, header->value, "sip_%s", header->name+13);
} else if(!strncmp(header->name, "ecallmgr_", 9)) {
switch_event_add_header_string(to_remove, SWITCH_STACK_BOTTOM, header->name, header->value);
}
}
if(n) {
for(header = to_remove->headers; header; header = header->next) {
switch_channel_set_variable(channel, header->name, NULL);
}
}
for(header = to_add->headers; header; header = header->next) {
switch_channel_set_variable(channel, header->name, header->value);
}
// cleanup leg A
loopback_aleg = switch_channel_get_variable(channel, "other_loopback_leg_uuid");
if(loopback_aleg != NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "found loopback a-leg uuid - %s\n", loopback_aleg);
if ((a_session = switch_core_session_locate(loopback_aleg))) {
a_channel = switch_core_session_get_channel(a_session);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "found loopback session a - %s\n", loopback_aleg);
switch_channel_del_variable_prefix(a_channel, "Export-Loopback-");
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Couldn't locate loopback session a - %s\n", loopback_aleg);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Couldn't find loopback a-leg uuid!\n");
}
/*
* set Interaction-ID
* if we're not crossing account boundaries
*/
if (kz_test_tweak(KZ_TWEAK_INTERACTION_ID)) {
if (a_channel) {
const char *interaction_id = switch_channel_get_variable_dup(a_channel, INTERACTION_VARIABLE, SWITCH_FALSE, -1);
const char *a_account_id = switch_channel_get_variable_dup(a_channel, "ecallmgr_Account-ID", SWITCH_FALSE, -1);
const char *b_account_id = switch_channel_get_variable_dup(channel, "ecallmgr_Account-ID", SWITCH_FALSE, -1);
if ((!a_account_id) || (!b_account_id) || (!strcmp(a_account_id, b_account_id))) {
switch_channel_set_variable(channel, INTERACTION_VARIABLE, interaction_id);
}
}
}
if (a_session){
switch_core_session_rwunlock(a_session);
}
switch_event_destroy(&event);
switch_event_destroy(&to_add);
switch_event_destroy(&to_remove);
return SWITCH_STATUS_SUCCESS;
}
static void kz_tweaks_handle_caller_id(switch_core_session_t *session)
{
if (kz_test_tweak(KZ_TWEAK_CALLER_ID)) {
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_caller_profile_t* caller = switch_channel_get_caller_profile(channel);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "CHECKING CALLER-ID\n");
if (caller && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
const char* val = NULL;
if((val=switch_caller_get_field_by_name(caller, "Endpoint-Caller-ID-Name"))) {
caller->caller_id_name = val;
caller->orig_caller_id_name = val;
}
if((val=switch_caller_get_field_by_name(caller, "Endpoint-Caller-ID-Number"))) {
caller->caller_id_number = val;
caller->orig_caller_id_number = val;
}
}
}
}
static switch_status_t kz_tweaks_handle_nightmare_xfer_interaction_id(switch_core_session_t *session)
{
if (kz_test_tweak(KZ_TWEAK_INTERACTION_ID)) {
switch_core_session_t *replace_session = NULL;
switch_channel_t *channel = switch_core_session_get_channel(session);
const char *replaced_call_id = switch_channel_get_variable(channel, "sip_replaces_call_id");
const char *core_uuid = switch_channel_get_variable(channel, "sip_h_X-FS-From-Core-UUID");
const char *partner_uuid = switch_channel_get_variable(channel, "sip_h_X-FS-Refer-Partner-UUID");
const char *interaction_id = switch_channel_get_variable(channel, "sip_h_X-FS-Call-Interaction-ID");
if(core_uuid && partner_uuid && replaced_call_id && interaction_id) {
switch_channel_set_variable(channel, INTERACTION_VARIABLE, interaction_id);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "checking nightmare xfer tweak for %s\n", switch_channel_get_uuid(channel));
if ((replace_session = switch_core_session_locate(replaced_call_id))) {
switch_channel_t *replaced_call_channel = switch_core_session_get_channel(replace_session);
switch_channel_set_variable(replaced_call_channel, INTERACTION_VARIABLE, interaction_id);
switch_core_session_rwunlock(replace_session);
}
if ((replace_session = switch_core_session_locate(partner_uuid))) {
switch_channel_t *replaced_call_channel = switch_core_session_get_channel(replace_session);
switch_channel_set_variable(replaced_call_channel, INTERACTION_VARIABLE, interaction_id);
switch_core_session_rwunlock(replace_session);
}
}
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t kz_tweaks_handle_replaces_call_id(switch_core_session_t *session)
{
if (kz_test_tweak(KZ_TWEAK_REPLACES_CALL_ID)) {
switch_core_session_t *replace_call_session = NULL;
switch_event_t *event;
switch_channel_t *channel = switch_core_session_get_channel(session);
const char *replaced_call_id = switch_channel_get_variable(channel, "sip_replaces_call_id");
const char *core_uuid = switch_channel_get_variable(channel, "sip_h_X-FS-From-Core-UUID");
if((!core_uuid) && replaced_call_id) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "checking replaces header tweak for %s\n", replaced_call_id);
if ((replace_call_session = switch_core_session_locate(replaced_call_id))) {
switch_channel_t *replaced_call_channel = switch_core_session_get_channel(replace_call_session);
int i;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "setting bridge variables from %s to %s\n", replaced_call_id, switch_channel_get_uuid(channel));
for(i = 0; bridge_variables[i] != NULL; i++) {
const char *val = switch_channel_get_variable_dup(replaced_call_channel, bridge_variables[i], SWITCH_TRUE, -1);
switch_channel_set_variable(channel, bridge_variables[i], val);
}
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
switch_event_fire(&event);
}
switch_core_session_rwunlock(replace_call_session);
}
}
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t kz_tweaks_handle_switch_uri(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
if (kz_test_tweak(KZ_TWEAK_SWITCH_URI)) {
const char *profile_url = switch_channel_get_variable(channel, "sofia_profile_url");
if(profile_url) {
int n = strcspn(profile_url, "@");
switch_channel_set_variable(channel, "Switch-URL", profile_url);
switch_channel_set_variable_printf(channel, "Switch-URI", "sip:%s", n > 0 ? profile_url + n + 1 : profile_url);
}
}
return SWITCH_STATUS_SUCCESS;
}
static char * kz_tweaks_new_interaction_id()
{
long int first = (switch_micro_time_now() / 1000000) + UNIX_EPOCH_IN_GREGORIAN;
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
switch_uuid_t uuid;
switch_uuid_get(&uuid);
switch_uuid_format(uuid_str, &uuid);
uuid_str[8] = '\0';
return switch_mprintf("%ld-%s", first, uuid_str);
}
static void kz_tweaks_handle_interaction_id(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
char * val = NULL;
switch_core_session_t *peer_session = NULL;
const char* peer_interaction_id = NULL;
if (kz_test_tweak(KZ_TWEAK_INTERACTION_ID)) {
val = kz_tweaks_new_interaction_id();
if (val) {
switch_channel_set_variable(channel, "Original-"INTERACTION_VARIABLE, val);
if(switch_core_session_get_partner(session, &peer_session) == SWITCH_STATUS_SUCCESS) {
switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
peer_interaction_id = switch_channel_get_variable_dup(peer_channel, INTERACTION_VARIABLE, SWITCH_FALSE, -1);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "PEER_SESSION => %s\n", peer_interaction_id);
if(peer_interaction_id) {
switch_channel_set_variable(channel, INTERACTION_VARIABLE, peer_interaction_id);
}
switch_core_session_rwunlock(peer_session);
} else if (!switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_FALSE, -1)) {
switch_channel_set_variable(channel, INTERACTION_VARIABLE, val);
}
}
switch_safe_free(val);
}
}
static switch_status_t kz_outgoing_channel(switch_core_session_t * session, switch_event_t * event, switch_caller_profile_t * cp, switch_core_session_t * peer_session, switch_originate_flag_t flag)
{
if (kz_test_tweak(KZ_TWEAK_INTERACTION_ID)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "GOT OUTGOING\n");
if (peer_session) {
switch_channel_t *channel = switch_core_session_get_channel(session);
const char* interaction_id = switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_FALSE, -1);
switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "SESSION && PEER_SESSION => %s\n", interaction_id );
if (interaction_id) {
switch_channel_set_variable(peer_channel, INTERACTION_VARIABLE, interaction_id);
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "NO SESSION && PEER_SESSION\n");
}
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t kz_tweaks_register_handle_blind_xfer(switch_core_session_t *session)
{
if (kz_test_tweak(KZ_TWEAK_RESTORE_CALLER_ID_ON_BLIND_XFER)) {
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_channel_set_variable(channel, "execute_on_blind_transfer", "kz_restore_caller_id");
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t kz_tweaks_on_init(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "checking tweaks for %s\n", switch_channel_get_uuid(channel));
switch_channel_set_flag(channel, CF_VERBOSE_EVENTS);
switch_core_event_hook_add_outgoing_channel(session, kz_outgoing_channel);
kz_tweaks_handle_interaction_id(session);
kz_tweaks_handle_switch_uri(session);
kz_tweaks_handle_caller_id(session);
kz_tweaks_handle_nightmare_xfer_interaction_id(session);
kz_tweaks_handle_replaces_call_id(session);
kz_tweaks_handle_loopback(session);
kz_tweaks_register_handle_blind_xfer(session);
return SWITCH_STATUS_SUCCESS;
}
static switch_state_handler_table_t kz_tweaks_state_handlers = {
/*.on_init */ kz_tweaks_on_init,
/*.on_routing */ NULL,
/*.on_execute */ NULL,
/*.on_hangup */ NULL,
/*.on_exchange_media */ NULL,
/*.on_soft_execute */ NULL,
/*.on_consume_media */ NULL,
/*.on_hibernate */ NULL,
/*.on_reset */ NULL,
/*.on_park */ NULL,
/*.on_reporting */ NULL,
/*.on_destroy */ NULL
};
static void kz_tweaks_register_state_handlers()
{
/*
* we may need two handlers
* one with SSH_FLAG_PRE_EXEC
* and another without it
* mod_loopback tweaks needs post-init (SSH_FLAG_PRE_EXEC off)
*
* kz_tweaks_state_handlers.flags = SSH_FLAG_PRE_EXEC;
*
*/
switch_core_add_state_handler(&kz_tweaks_state_handlers);
}
static void kz_tweaks_unregister_state_handlers()
{
switch_core_remove_state_handler(&kz_tweaks_state_handlers);
}
static void kz_tweaks_bind_events()
{
if (switch_event_bind("kz_tweaks", SWITCH_EVENT_CHANNEL_BRIDGE, SWITCH_EVENT_SUBCLASS_ANY, kz_tweaks_channel_bridge_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind to channel_bridge event!\n");
}
if (switch_event_bind("kz_tweaks", SWITCH_EVENT_CUSTOM, "sofia::replaced", kz_tweaks_channel_replaced_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind to channel_bridge event!\n");
}
if (switch_event_bind("kz_tweaks", SWITCH_EVENT_CUSTOM, "sofia::intercepted", kz_tweaks_channel_intercepted_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind to channel_bridge event!\n");
}
if (switch_event_bind("kz_tweaks", SWITCH_EVENT_CUSTOM, "sofia::transferor", kz_tweaks_channel_transferor_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind to channel_bridge event!\n");
}
if (switch_event_bind("kz_tweaks", SWITCH_EVENT_CUSTOM, "sofia::transferee", kz_tweaks_channel_transferee_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind to channel_bridge event!\n");
}
}
static void kz_tweaks_unbind_events()
{
switch_event_unbind_callback(kz_tweaks_channel_bridge_event_handler);
switch_event_unbind_callback(kz_tweaks_channel_replaced_event_handler);
switch_event_unbind_callback(kz_tweaks_channel_intercepted_event_handler);
switch_event_unbind_callback(kz_tweaks_channel_transferor_event_handler);
switch_event_unbind_callback(kz_tweaks_channel_transferee_event_handler);
}
void kz_tweaks_add_core_variables()
{
switch_core_set_variable("UNIX_EPOCH_IN_GREGORIAN", UNIX_EPOCH_IN_GREGORIAN_STR);
}
void kz_tweaks_start()
{
kz_tweaks_add_core_variables();
kz_tweaks_register_state_handlers();
kz_tweaks_bind_events();
}
void kz_tweaks_stop()
{
kz_tweaks_unbind_events();
kz_tweaks_unregister_state_handlers();
}
SWITCH_DECLARE(const char *) kz_tweak_name(kz_tweak_t tweak)
{
return TWEAK_NAMES[tweak];
}
SWITCH_DECLARE(switch_status_t) kz_name_tweak(const char *name, kz_tweak_t *type)
{
kz_tweak_t x;
for (x = 0; x < KZ_TWEAK_MAX; x++) {
if (!strcasecmp(name, TWEAK_NAMES[x])) {
*type = x;
return SWITCH_STATUS_SUCCESS;
}
}
return SWITCH_STATUS_FALSE;
}
/* 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:
*/

View File

@ -1,32 +0,0 @@
#pragma once
#include <switch.h>
typedef enum {
KZ_TWEAK_INTERACTION_ID,
KZ_TWEAK_EXPORT_VARS,
KZ_TWEAK_SWITCH_URI,
KZ_TWEAK_REPLACES_CALL_ID,
KZ_TWEAK_LOOPBACK_VARS,
KZ_TWEAK_CALLER_ID,
KZ_TWEAK_TRANSFERS,
KZ_TWEAK_BRIDGE,
KZ_TWEAK_BRIDGE_REPLACES_ALEG,
KZ_TWEAK_BRIDGE_REPLACES_CALL_ID,
KZ_TWEAK_BRIDGE_VARIABLES,
KZ_TWEAK_RESTORE_CALLER_ID_ON_BLIND_XFER,
/* No new flags below this line */
KZ_TWEAK_MAX
} kz_tweak_t;
void kz_tweaks_start();
void kz_tweaks_stop();
SWITCH_DECLARE(const char *) kz_tweak_name(kz_tweak_t tweak);
SWITCH_DECLARE(switch_status_t) kz_name_tweak(const char *name, kz_tweak_t *type);
#define kz_test_tweak(flag) (kazoo_globals.tweaks[flag] ? 1 : 0)
#define kz_set_tweak(flag) kazoo_globals.tweaks[flag] = 1
#define kz_clear_tweak(flag) kazoo_globals.tweaks[flag] = 0

View File

@ -1,700 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthm@freeswitch.org>
* Andrew Thompson <andrew@hijacked.us>
* Rob Charlton <rob.charlton@savageminds.com>
* Karl Anderson <karl@2600hz.com>
*
* Original from mod_erlang_event.
* ei_helpers.c -- helper functions for ei
*
*/
#include "mod_kazoo.h"
#define kz_resize(l) {\
char *dp;\
olen += (len + l + block);\
cpos = c - data;\
if ((dp = realloc(data, olen))) {\
data = dp;\
c = data + cpos;\
memset(c, 0, olen - cpos);\
}} \
void kz_check_set_profile_var(switch_channel_t *channel, char* var, char *val)
{
int idx = 0;
while(kazoo_globals.profile_vars_prefixes[idx] != NULL) {
char *prefix = kazoo_globals.profile_vars_prefixes[idx];
if (!strncasecmp(var, prefix, strlen(prefix))) {
switch_channel_set_profile_var(channel, var + strlen(prefix), val);
}
idx++;
}
}
SWITCH_DECLARE(switch_status_t) kz_switch_core_merge_variables(switch_event_t *event)
{
switch_event_t *global_vars;
switch_status_t status = switch_core_get_variables(&global_vars);
if(status == SWITCH_STATUS_SUCCESS) {
switch_event_merge(event, global_vars);
switch_event_destroy(&global_vars);
}
return status;
}
SWITCH_DECLARE(switch_status_t) kz_switch_core_base_headers_for_expand(switch_event_t **event)
{
switch_status_t status = SWITCH_STATUS_GENERR;
*event = NULL;
if(switch_event_create(event, SWITCH_EVENT_GENERAL) == SWITCH_STATUS_SUCCESS) {
status = kz_switch_core_merge_variables(*event);
}
return status;
}
SWITCH_DECLARE(switch_status_t) kz_expand_api_execute(const char *cmd, const char *arg, switch_core_session_t *session, switch_stream_handle_t *stream)
{
switch_api_interface_t *api;
switch_status_t status;
char *arg_used;
char *cmd_used;
switch_assert(stream != NULL);
switch_assert(stream->data != NULL);
switch_assert(stream->write_function != NULL);
cmd_used = switch_strip_whitespace(cmd);
arg_used = switch_strip_whitespace(arg);
if (cmd_used && (api = switch_loadable_module_get_api_interface(cmd_used)) != 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "executing [%s] => [%s]\n", cmd_used, arg_used);
if ((status = api->function(arg_used, session, stream)) != SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "COMMAND RETURNED ERROR!\n");
}
UNPROTECT_INTERFACE(api);
} else {
status = SWITCH_STATUS_FALSE;
stream->write_function(stream, "INVALID COMMAND!\n");
}
if (cmd_used != cmd) {
switch_safe_free(cmd_used);
}
if (arg_used != arg) {
switch_safe_free(arg_used);
}
return status;
}
SWITCH_DECLARE(char *) kz_event_expand_headers_check(switch_event_t *event, const char *in, switch_event_t *var_list, switch_event_t *api_list, uint32_t recur)
{
char *p, *c = NULL;
char *data, *indup, *endof_indup;
size_t sp = 0, len = 0, olen = 0, vtype = 0, br = 0, cpos, block = 128;
const char *sub_val = NULL;
char *cloned_sub_val = NULL, *expanded_sub_val = NULL;
char *func_val = NULL;
int nv = 0;
char *gvar = NULL, *sb = NULL;
if (recur > 100) {
return (char *) in;
}
if (zstr(in)) {
return (char *) in;
}
nv = switch_string_var_check_const(in) || switch_string_has_escaped_data(in);
if (!nv) {
return (char *) in;
}
nv = 0;
olen = strlen(in) + 1;
indup = strdup(in);
switch_assert(indup);
endof_indup = end_of_p(indup) + 1;
if ((data = malloc(olen))) {
memset(data, 0, olen);
c = data;
for (p = indup; p && p < endof_indup && *p; p++) {
int global = 0;
vtype = 0;
if (*p == '\\') {
if (*(p + 1) == '$') {
nv = 1;
p++;
if (*(p + 1) == '$') {
p++;
}
} else if (*(p + 1) == '\'') {
p++;
continue;
} else if (*(p + 1) == '\\') {
if (len + 1 >= olen) {
kz_resize(1);
}
*c++ = *p++;
len++;
continue;
}
}
if (*p == '$' && !nv) {
if (*(p + 1) == '$') {
p++;
global++;
}
if (*(p + 1)) {
if (*(p + 1) == '{') {
vtype = global ? 3 : 1;
} else {
nv = 1;
}
} else {
nv = 1;
}
}
if (nv) {
if (len + 1 >= olen) {
kz_resize(1);
}
*c++ = *p;
len++;
nv = 0;
continue;
}
if (vtype) {
char *s = p, *e, *vname, *vval = NULL;
size_t nlen;
s++;
if ((vtype == 1 || vtype == 3) && *s == '{') {
br = 1;
s++;
}
e = s;
vname = s;
while (*e) {
if (br == 1 && *e == '}') {
br = 0;
*e++ = '\0';
break;
}
if (br > 0) {
if (e != s && *e == '{') {
br++;
} else if (br > 1 && *e == '}') {
br--;
}
}
e++;
}
p = e > endof_indup ? endof_indup : e;
vval = NULL;
for(sb = vname; sb && *sb; sb++) {
if (*sb == ' ') {
vval = sb;
break;
} else if (*sb == '(') {
vval = sb;
br = 1;
break;
}
}
if (vval) {
e = vval - 1;
*vval++ = '\0';
while (*e == ' ') {
*e-- = '\0';
}
e = vval;
while (e && *e) {
if (*e == '(') {
br++;
} else if (br > 1 && *e == ')') {
br--;
} else if (br == 1 && *e == ')') {
*e = '\0';
break;
}
e++;
}
vtype = 2;
}
if (vtype == 1 || vtype == 3) {
char *expanded = NULL;
int offset = 0;
int ooffset = 0;
char *ptr;
int idx = -1;
if ((expanded = kz_event_expand_headers_check(event, (char *) vname, var_list, api_list, recur+1)) == vname) {
expanded = NULL;
} else {
vname = expanded;
}
if ((ptr = strchr(vname, ':'))) {
*ptr++ = '\0';
offset = atoi(ptr);
if ((ptr = strchr(ptr, ':'))) {
ptr++;
ooffset = atoi(ptr);
}
}
if ((ptr = strchr(vname, '[')) && strchr(ptr, ']')) {
*ptr++ = '\0';
idx = atoi(ptr);
}
if (vtype == 3 || !(sub_val = switch_event_get_header_idx(event, vname, idx))) {
switch_safe_free(gvar);
if ((gvar = switch_core_get_variable_dup(vname))) {
sub_val = gvar;
}
if (var_list && !switch_event_check_permission_list(var_list, vname)) {
sub_val = "<Variable Expansion Permission Denied>";
}
if ((expanded_sub_val = kz_event_expand_headers_check(event, sub_val, var_list, api_list, recur+1)) == sub_val) {
expanded_sub_val = NULL;
} else {
sub_val = expanded_sub_val;
}
}
if (sub_val) {
if (offset || ooffset) {
cloned_sub_val = strdup(sub_val);
switch_assert(cloned_sub_val);
sub_val = cloned_sub_val;
}
if (offset >= 0) {
sub_val += offset;
} else if ((size_t) abs(offset) <= strlen(sub_val)) {
sub_val = cloned_sub_val + (strlen(cloned_sub_val) + offset);
}
if (ooffset > 0 && (size_t) ooffset < strlen(sub_val)) {
if ((ptr = (char *) sub_val + ooffset)) {
*ptr = '\0';
}
}
}
switch_safe_free(expanded);
} else {
char *expanded = NULL;
char *expanded_vname = NULL;
if ((expanded_vname = kz_event_expand_headers_check(event, (char *) vname, var_list, api_list, recur+1)) == vname) {
expanded_vname = NULL;
} else {
vname = expanded_vname;
}
if ((expanded = kz_event_expand_headers_check(event, vval, var_list, api_list, recur+1)) == vval) {
expanded = NULL;
} else {
vval = expanded;
}
if (!switch_core_test_flag(SCF_API_EXPANSION) || (api_list && !switch_event_check_permission_list(api_list, vname))) {
func_val = NULL;
sub_val = "<API execute Permission Denied>";
} else {
switch_stream_handle_t stream = { 0 };
SWITCH_STANDARD_STREAM(stream);
stream.param_event = event;
if (kz_expand_api_execute(vname, vval, NULL, &stream) == SWITCH_STATUS_SUCCESS) {
func_val = stream.data;
sub_val = func_val;
} else {
free(stream.data);
}
}
switch_safe_free(expanded);
switch_safe_free(expanded_vname);
}
if ((nlen = sub_val ? strlen(sub_val) : 0)) {
if (len + nlen >= olen) {
kz_resize(nlen);
}
len += nlen;
strcat(c, sub_val);
c += nlen;
}
switch_safe_free(func_val);
switch_safe_free(cloned_sub_val);
switch_safe_free(expanded_sub_val);
sub_val = NULL;
vname = NULL;
br = 0;
}
if (sp) {
if (len + 1 >= olen) {
kz_resize(1);
}
*c++ = ' ';
sp = 0;
len++;
}
if (*p == '$') {
p--;
} else {
if (len + 1 >= olen) {
kz_resize(1);
}
*c++ = *p;
len++;
}
}
}
free(indup);
switch_safe_free(gvar);
return data;
}
SWITCH_DECLARE(char *) kz_event_expand_headers(switch_event_t *event, const char *in)
{
return kz_event_expand_headers_check(event, in, NULL, NULL, 0);
}
SWITCH_DECLARE(char *) kz_event_expand_headers_pool(switch_memory_pool_t *pool, switch_event_t *event, char *val)
{
char *expanded;
char *dup = NULL;
expanded = kz_event_expand_headers(event, val);
dup = switch_core_strdup(pool, expanded);
if (expanded != val) {
free(expanded);
}
return dup;
}
SWITCH_DECLARE(char *) kz_expand(const char *in, const char *uuid)
{
switch_event_t *event = NULL;
char *ret = NULL;
kz_switch_core_base_headers_for_expand(&event);
if (uuid != NULL) {
switch_core_session_t *nsession = NULL;
if ((nsession = switch_core_session_locate(uuid))) {
switch_channel_event_set_data(switch_core_session_get_channel(nsession), event);
switch_core_session_rwunlock(nsession);
}
}
ret = kz_event_expand_headers_check(event, in, NULL, NULL, 0);
switch_event_destroy(&event);
return ret;
}
SWITCH_DECLARE(char *) kz_expand_pool(switch_memory_pool_t *pool, const char *in)
{
char *expanded;
char *dup = NULL;
if(!(expanded = kz_expand(in, NULL))) {
return NULL;
}
dup = switch_core_strdup(pool, expanded);
if (expanded != in) {
switch_safe_free(expanded);
}
return dup;
}
char* kz_switch_event_get_first_of(switch_event_t *event, const char *list[])
{
switch_event_header_t *header = NULL;
int i = 0;
while(list[i] != NULL) {
if((header = switch_event_get_header_ptr(event, list[i])) != NULL)
break;
i++;
}
if(header != NULL) {
return header->value;
} else {
return "nodomain";
}
}
SWITCH_DECLARE(switch_status_t) kz_switch_event_add_variable_name_printf(switch_event_t *event, switch_stack_t stack, const char *val, const char *fmt, ...)
{
int ret = 0;
char *varname;
va_list ap;
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_assert(event != NULL);
va_start(ap, fmt);
ret = switch_vasprintf(&varname, fmt, ap);
va_end(ap);
if (ret == -1) {
return SWITCH_STATUS_MEMERR;
}
status = switch_event_add_header_string(event, stack, varname, val);
free(varname);
return status;
}
SWITCH_DECLARE(switch_status_t) kz_expand_json_to_event(cJSON *json, switch_event_t *event, char * prefix)
{
char * fmt = switch_mprintf("%s%s%%s", prefix ? prefix : "", prefix ? "_" : "");
if (event) {
cJSON *item = NULL;
char *response = NULL;
cJSON_ArrayForEach(item, json) {
if (item->type == cJSON_String) {
response = strdup(item->valuestring);
} else if (item->type == cJSON_Object) {
char * fmt1 = switch_mprintf(fmt, item->string);
kz_expand_json_to_event(item, event, fmt1);
switch_safe_free(fmt1);
continue;
} else {
response = cJSON_PrintUnformatted(item);
}
kz_switch_event_add_variable_name_printf(event, SWITCH_STACK_BOTTOM, response, fmt, item->string);
switch_safe_free(response);
}
}
switch_safe_free(fmt);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_xml_t) kz_xml_child(switch_xml_t xml, const char *name)
{
xml = (xml) ? xml->child : NULL;
while (xml && strcasecmp(name, xml->name))
xml = xml->sibling;
return xml;
}
void kz_xml_process(switch_xml_t cfg)
{
switch_xml_t xml_process;
for (xml_process = kz_xml_child(cfg, "X-PRE-PROCESS"); xml_process; xml_process = xml_process->next) {
const char *cmd = switch_xml_attr(xml_process, "cmd");
const char *data = switch_xml_attr(xml_process, "data");
if(cmd != NULL && !strcasecmp(cmd, "set") && data) {
char *name = (char *) data;
char *val = strchr(name, '=');
if (val) {
char *ve = val++;
while (*val && *val == ' ') {
val++;
}
*ve-- = '\0';
while (*ve && *ve == ' ') {
*ve-- = '\0';
}
}
if (name && val) {
switch_core_set_variable(name, val);
}
}
}
}
void kz_event_decode(switch_event_t *event)
{
switch_event_header_t *hp;
int i;
for (hp = event->headers; hp; hp = hp->next) {
if (strncmp(hp->name, "_json_", 6)) {
if (hp->idx) {
for(i = 0; i < hp->idx; i++) {
switch_url_decode(hp->array[i]);
}
} else {
switch_url_decode(hp->value);
}
}
}
}
void kz_expand_headers(switch_event_t *resolver, switch_event_t *event) {
switch_event_t *clone = NULL;
switch_event_header_t *header = NULL;
switch_event_create_plain(&clone, event->event_id);
for(header = event->headers; header; header = header->next) {
char *expanded = kz_event_expand_headers(resolver, header->value);
if (expanded != header->value) {
switch_event_add_header_string(clone, SWITCH_STACK_BOTTOM, header->name, expanded);
switch_safe_free(expanded);
}
}
/* we don't want to force unique headers
* so we delete and then merge
*/
for(header = clone->headers; header; header = header->next) {
switch_event_del_header(event, header->name);
}
switch_event_merge(event, clone);
switch_event_destroy(&clone);
}
void kz_expand_headers_self(switch_event_t *event) {
kz_expand_headers(event, event);
}
char * kz_expand_vars(char *xml_str) {
return kz_expand_vars_pool(xml_str, NULL);
}
char * kz_expand_vars_pool(char *xml_str, switch_memory_pool_t *pool) {
char *var, *val;
char *rp = xml_str; /* read pointer */
char *ep, *wp, *buff; /* end pointer, write pointer, write buffer */
if (!(strstr(xml_str, "$${"))) {
return xml_str;
}
switch_zmalloc(buff, strlen(xml_str) * 2);
wp = buff;
ep = buff + (strlen(xml_str) * 2) - 1;
while (*rp && wp < ep) {
if (*rp == '$' && *(rp + 1) == '$' && *(rp + 2) == '{') {
char *e = switch_find_end_paren(rp + 2, '{', '}');
if (e) {
rp += 3;
var = rp;
*e++ = '\0';
rp = e;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "trying to expand %s \n", var);
if ((val = switch_core_get_variable_dup(var))) {
char *p;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "expanded %s to %s\n", var, val);
for (p = val; p && *p && wp <= ep; p++) {
*wp++ = *p;
}
switch_safe_free(val);
}
continue;
}
}
*wp++ = *rp++;
}
*wp++ = '\0';
if(pool) {
char * ret = switch_core_strdup(pool, buff);
switch_safe_free(buff);
return ret;
} else {
switch_safe_free(xml_str);
return buff;
}
}
switch_status_t kz_json_api(const char * command, cJSON *args, cJSON **res)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
cJSON *req = cJSON_CreateObject();
cJSON_AddItemToObject(req, "command", cJSON_CreateString(command));
cJSON_AddItemToObject(req, "data", args ? args : cJSON_CreateObject());
status = switch_json_api_execute(req, NULL, res);
cJSON_Delete(req);
return status;
}
/* 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:
*/

View File

@ -1,51 +0,0 @@
#pragma once
#include <switch.h>
#ifdef __cplusplus
#define KZ_BEGIN_EXTERN_C extern "C" {
#define KZ_END_EXTERN_C }
#else
#define KZ_BEGIN_EXTERN_C
#define KZ_END_EXTERN_C
#endif
KZ_BEGIN_EXTERN_C
void kz_check_set_profile_var(switch_channel_t *channel, char* var, char *val);
SWITCH_DECLARE(switch_status_t) kz_switch_core_merge_variables(switch_event_t *event);
SWITCH_DECLARE(switch_status_t) kz_switch_core_base_headers_for_expand(switch_event_t **event);
SWITCH_DECLARE(switch_status_t) kz_expand_api_execute(const char *cmd, const char *arg, switch_core_session_t *session, switch_stream_handle_t *stream);
SWITCH_DECLARE(char *) kz_event_expand_headers_check(switch_event_t *event, const char *in, switch_event_t *var_list, switch_event_t *api_list, uint32_t recur);
SWITCH_DECLARE(char *) kz_event_expand_headers(switch_event_t *event, const char *in);
SWITCH_DECLARE(char *) kz_event_expand_headers_pool(switch_memory_pool_t *pool, switch_event_t *event, char *val);
SWITCH_DECLARE(char *) kz_expand(const char *in, const char *uuid);
SWITCH_DECLARE(char *) kz_expand_pool(switch_memory_pool_t *pool, const char *in);
char* kz_switch_event_get_first_of(switch_event_t *event, const char *list[]);
SWITCH_DECLARE(switch_status_t) kz_switch_event_add_variable_name_printf(switch_event_t *event, switch_stack_t stack, const char *val, const char *fmt, ...);
SWITCH_DECLARE(switch_xml_t) kz_xml_child(switch_xml_t xml, const char *name);
void kz_xml_process(switch_xml_t cfg);
void kz_event_decode(switch_event_t *event);
char * kz_expand_vars(char *xml_str);
void kz_expand_headers(switch_event_t *resolver, switch_event_t *event);
void kz_expand_headers_self(switch_event_t *event);
char * kz_expand_vars_pool(char *xml_str, switch_memory_pool_t *pool);
switch_status_t kz_json_api(const char * command, cJSON *args, cJSON **res);
SWITCH_DECLARE(switch_status_t) kz_expand_json_to_event(cJSON *json, switch_event_t *event, char * prefix);
KZ_END_EXTERN_C

View File

@ -1,91 +0,0 @@
#include "mod_kazoo.h"
static int kz_nodes_module_names_array_callback(void *pArg, const char *module_name)
{
cJSON *json = (cJSON *) pArg;
if(!strstr(module_name, "CORE")) {
cJSON_AddItemToArray(json, cJSON_CreateString(module_name));
}
return 0;
}
void kz_nodes_collect_media_role(cJSON *container)
{
cJSON *retval = NULL;
if(kz_json_api("sofia.status.info", NULL, &retval) == SWITCH_STATUS_SUCCESS) {
if(retval != NULL && (!(retval->type & cJSON_NULL))) {
cJSON_AddItemToObject(container, "Media", cJSON_Duplicate(retval, 1));
}
}
if(retval) {
cJSON_Delete(retval);
}
}
void kz_nodes_collect_modules(cJSON *container)
{
cJSON *modules = cJSON_CreateObject();
cJSON *loaded = cJSON_CreateArray();
cJSON *available = cJSON_CreateArray();
switch_loadable_module_enumerate_available(SWITCH_GLOBAL_dirs.mod_dir, kz_nodes_module_names_array_callback, available);
switch_loadable_module_enumerate_loaded(kz_nodes_module_names_array_callback, loaded);
cJSON_AddItemToObject(modules, "available", available);
cJSON_AddItemToObject(modules, "loaded", loaded);
cJSON_AddItemToObject(container, "Modules", modules);
}
void kz_nodes_collect_runtime(cJSON *container)
{
cJSON *retval = NULL;
if(kz_json_api("status", NULL, &retval) == SWITCH_STATUS_SUCCESS) {
if(retval != NULL && (!(retval->type & cJSON_NULL))) {
cJSON *val = cJSON_Duplicate(retval, 1);
cJSON_AddItemToObject(val, "Core-UUID", cJSON_CreateString(switch_core_get_uuid()));
cJSON_AddItemToObject(container, "Runtime-Info", val);
}
}
if(retval) {
cJSON_Delete(retval);
}
}
void kz_nodes_collect_apps(cJSON *container)
{
cJSON *apps = cJSON_CreateObject();
cJSON *app = cJSON_CreateObject();
cJSON_AddItemToObject(app, "Uptime", cJSON_CreateNumber(switch_core_uptime()));
cJSON_AddItemToObject(apps, "freeswitch", app);
cJSON_AddItemToObject(container, "WhApps", apps);
}
void kz_nodes_collect_roles(cJSON *container)
{
cJSON *roles = cJSON_CreateObject();
cJSON_AddItemToObject(container, "Roles", roles);
kz_nodes_collect_media_role(roles);
}
cJSON * kz_node_create()
{
cJSON *node = cJSON_CreateObject();
kz_nodes_collect_apps(node);
kz_nodes_collect_runtime(node);
kz_nodes_collect_modules(node);
kz_nodes_collect_roles(node);
return node;
}
SWITCH_STANDARD_JSON_API(kz_node_info_json_function)
{
cJSON * ret = kz_node_create();
*json_reply = ret;
return SWITCH_STATUS_SUCCESS;
}
void add_kz_node(switch_loadable_module_interface_t **module_interface)
{
switch_json_api_interface_t *json_api_interface = NULL;
SWITCH_ADD_JSON_API(json_api_interface, "node.info", "JSON node API", kz_node_info_json_function, "");
}

View File

@ -1,152 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Karl Anderson <karl@2600hz.com>
* Darren Schreiber <darren@2600hz.com>
*
*
* mod_kazoo.c -- Socket Controlled Event Handler
*
*/
#include "mod_kazoo.h"
kz_globals_t kazoo_globals = {0};
SWITCH_MODULE_DEFINITION(mod_kazoo, mod_kazoo_load, mod_kazoo_shutdown, mod_kazoo_runtime);
SWITCH_MODULE_LOAD_FUNCTION(mod_kazoo_load)
{
kz_erl_init();
memset(&kazoo_globals, 0, sizeof(kazoo_globals));
kazoo_globals.pool = pool;
kz_set_hostname();
if(kazoo_load_config() != SWITCH_STATUS_SUCCESS) {
// TODO: what would we need to clean up here?
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Improper configuration!\n");
return SWITCH_STATUS_TERM;
}
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
switch_thread_rwlock_create(&kazoo_globals.ei_nodes_lock, pool);
switch_set_flag(&kazoo_globals, LFLAG_RUNNING);
/* create all XML fetch agents */
bind_fetch_agents();
/* create an api for cli debug commands */
add_cli_api(module_interface);
/* add our modified commands */
add_kz_commands(module_interface);
/* add our modified dptools */
add_kz_dptools(module_interface);
/* add our endpoints */
add_kz_endpoints(module_interface);
/* add our kz_node api */
add_kz_node(module_interface);
/* add tweaks */
kz_tweaks_start();
/* add our cdr */
kz_cdr_start();
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_kazoo_shutdown) {
int sanity = 0;
remove_cli_api();
kz_cdr_stop();
kz_tweaks_stop();
/* stop taking new requests and start shuting down the threads */
switch_clear_flag(&kazoo_globals, LFLAG_RUNNING);
/* give everyone time to cleanly shutdown */
while (switch_atomic_read(&kazoo_globals.threads)) {
switch_yield(100000);
if (++sanity >= 200) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to kill all threads, continuing. This probably wont end well.....good luck!\n");
break;
}
}
/* close the connection to epmd and the acceptor */
close_socketfd(&kazoo_globals.epmdfd);
close_socket(&kazoo_globals.acceptor);
/* remove all XML fetch agents */
unbind_fetch_agents();
if (kazoo_globals.event_filter) {
switch_core_hash_destroy(&kazoo_globals.event_filter);
}
switch_thread_rwlock_wrlock(kazoo_globals.ei_nodes_lock);
switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
switch_thread_rwlock_destroy(kazoo_globals.ei_nodes_lock);
/* Close the port we reserved for uPnP/Switch behind firewall, if necessary */
if (kazoo_globals.nat_map && switch_nat_get_type()) {
switch_nat_del_mapping(kazoo_globals.port, SWITCH_NAT_TCP);
}
kazoo_destroy_config();
/* clean up our allocated preferences */
switch_safe_free(kazoo_globals.ip);
switch_safe_free(kazoo_globals.ei_cookie);
switch_safe_free(kazoo_globals.ei_nodename);
kz_erl_shutdown();
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:
*/

View File

@ -1,87 +0,0 @@
#include <switch.h>
#include <switch_event.h>
#include <switch_json.h>
#include <ei.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <float.h>
#define MAX_ACL 100
#define CMD_BUFLEN 1024 * 1000
#define MAX_QUEUE_LEN 25000
#define MAX_MISSED 500
#define MAX_PID_CHARS 255
extern const char kz_default_config[];
extern const int kz_default_config_size;
#include "kazoo_defs.h"
#include "kazoo_tweaks.h"
#include "kazoo_ei.h"
#include "kazoo_message.h"
#include "kazoo_utils.h"
typedef enum {
LFLAG_RUNNING = (1 << 0)
} event_flag_t;
/* kazoo_commands.c */
void add_kz_commands(switch_loadable_module_interface_t **module_interface);
/* kazoo_dptools.c */
void add_kz_dptools(switch_loadable_module_interface_t **module_interface);
/* kazoo_api.c */
void add_cli_api(switch_loadable_module_interface_t **module_interface);
void remove_cli_api();
/* kazoo_utils.c */
/*
SWITCH_DECLARE(switch_status_t) kz_switch_core_merge_variables(switch_event_t *event);
SWITCH_DECLARE(switch_status_t) kz_switch_core_base_headers_for_expand(switch_event_t **event);
void kz_check_set_profile_var(switch_channel_t *channel, char* var, char *val);
char* kz_switch_event_get_first_of(switch_event_t *event, const char *list[]);
SWITCH_DECLARE(switch_status_t) kz_switch_event_add_variable_name_printf(switch_event_t *event, switch_stack_t stack, const char *val, const char *fmt, ...);
void kz_xml_process(switch_xml_t cfg);
void kz_event_decode(switch_event_t *event);
char * kz_expand_vars(char *xml_str);
char * kz_expand_vars_pool(char *xml_str, switch_memory_pool_t *pool);
SWITCH_DECLARE(char *) kz_event_expand_headers(switch_event_t *event, const char *in);
SWITCH_DECLARE(char *) kz_expand(const char *in);
SWITCH_DECLARE(char *) kz_expand_pool(switch_memory_pool_t *pool, const char *in);
switch_status_t kz_json_api(const char * command, cJSON *args, cJSON **res);
*/
/* kazoo_endpoints.c */
void add_kz_endpoints(switch_loadable_module_interface_t **module_interface);
/* kazoo_cdr.c */
void kz_cdr_start();
void kz_cdr_stop();
/* kazoo_tweaks.c */
void kz_tweaks_start();
void kz_tweaks_stop();
SWITCH_DECLARE(const char *) kz_tweak_name(kz_tweak_t tweak);
SWITCH_DECLARE(switch_status_t) kz_name_tweak(const char *name, kz_tweak_t *type);
/* kazoo_node.c */
void add_kz_node(switch_loadable_module_interface_t **module_interface);
SWITCH_MODULE_LOAD_FUNCTION(mod_kazoo_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_kazoo_shutdown);
/* 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:
*/

View File

@ -1096,7 +1096,8 @@ static switch_status_t vlc_file_read(switch_file_handle_t *handle, void *data, s
switch_thread_cond_wait(context->cond, context->cond_mutex); switch_thread_cond_wait(context->cond, context->cond_mutex);
status = libvlc_media_get_state(context->m); status = libvlc_media_get_state(context->m);
} }
switch_mutex_lock(context->cond_mutex);
switch_mutex_unlock(context->cond_mutex);
if (context->err == 1) { if (context->err == 1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "VLC error\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "VLC error\n");

View File

@ -2129,6 +2129,46 @@ SWIGEXPORT int SWIGSTDCALL CSharp_FreeSWITCHfNative_LOST_BURST_CAPTURE_get___()
} }
SWIGEXPORT void SWIGSTDCALL CSharp_FreeSWITCHfNative_switch_uint31_t_value_set___(void * jarg1, unsigned int jarg2) {
switch_uint31_t *arg1 = (switch_uint31_t *) 0 ;
unsigned int arg2 ;
arg1 = (switch_uint31_t *)jarg1;
arg2 = (unsigned int)jarg2;
if (arg1) (arg1)->value = arg2;
}
SWIGEXPORT unsigned int SWIGSTDCALL CSharp_FreeSWITCHfNative_switch_uint31_t_value_get___(void * jarg1) {
unsigned int jresult ;
switch_uint31_t *arg1 = (switch_uint31_t *) 0 ;
unsigned int result;
arg1 = (switch_uint31_t *)jarg1;
result = (unsigned int) ((arg1)->value);
jresult = result;
return jresult;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_FreeSWITCHfNative_new_switch_uint31_t___() {
void * jresult ;
switch_uint31_t *result = 0 ;
result = (switch_uint31_t *)new switch_uint31_t();
jresult = (void *)result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_FreeSWITCHfNative_delete_switch_uint31_t___(void * jarg1) {
switch_uint31_t *arg1 = (switch_uint31_t *) 0 ;
arg1 = (switch_uint31_t *)jarg1;
delete arg1;
}
SWIGEXPORT void SWIGSTDCALL CSharp_FreeSWITCHfNative_switch_dtmf_t_digit_set___(void * jarg1, char jarg2) { SWIGEXPORT void SWIGSTDCALL CSharp_FreeSWITCHfNative_switch_dtmf_t_digit_set___(void * jarg1, char jarg2) {
switch_dtmf_t *arg1 = (switch_dtmf_t *) 0 ; switch_dtmf_t *arg1 = (switch_dtmf_t *) 0 ;
char arg2 ; char arg2 ;
@ -3361,6 +3401,16 @@ SWIGEXPORT int SWIGSTDCALL CSharp_FreeSWITCHfNative_SWITCH_MAX_MANAGEMENT_BUFFER
} }
SWIGEXPORT int SWIGSTDCALL CSharp_FreeSWITCHfNative_SWITCH_RAND_MAX_get___() {
int jresult ;
int result;
result = (int)(0x7fff);
jresult = result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_FreeSWITCHfNative_switch_error_period_t_start_set___(void * jarg1, long long jarg2) { SWIGEXPORT void SWIGSTDCALL CSharp_FreeSWITCHfNative_switch_error_period_t_start_set___(void * jarg1, long long jarg2) {
error_period *arg1 = (error_period *) 0 ; error_period *arg1 = (error_period *) 0 ;
int64_t arg2 ; int64_t arg2 ;
@ -23521,6 +23571,16 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_FreeSWITCHfNative_switch_memory_usage_strea
} }
SWIGEXPORT int SWIGSTDCALL CSharp_FreeSWITCHfNative_switch_rand___() {
int jresult ;
int result;
result = (int)switch_rand();
jresult = result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_FreeSWITCHfNative_profile_node_t_var_set___(void * jarg1, char * jarg2) { SWIGEXPORT void SWIGSTDCALL CSharp_FreeSWITCHfNative_profile_node_t_var_set___(void * jarg1, char * jarg2) {
profile_node_s *arg1 = (profile_node_s *) 0 ; profile_node_s *arg1 = (profile_node_s *) 0 ;
char *arg2 = (char *) 0 ; char *arg2 = (char *) 0 ;
@ -45237,6 +45297,50 @@ SWIGEXPORT unsigned char SWIGSTDCALL CSharp_FreeSWITCHfNative_icand_t_ready_get_
} }
SWIGEXPORT void SWIGSTDCALL CSharp_FreeSWITCHfNative_icand_t_responsive_set___(void * jarg1, unsigned char jarg2) {
icand_s *arg1 = (icand_s *) 0 ;
uint8_t arg2 ;
arg1 = (icand_s *)jarg1;
arg2 = (uint8_t)jarg2;
if (arg1) (arg1)->responsive = arg2;
}
SWIGEXPORT unsigned char SWIGSTDCALL CSharp_FreeSWITCHfNative_icand_t_responsive_get___(void * jarg1) {
unsigned char jresult ;
icand_s *arg1 = (icand_s *) 0 ;
uint8_t result;
arg1 = (icand_s *)jarg1;
result = (uint8_t) ((arg1)->responsive);
jresult = result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_FreeSWITCHfNative_icand_t_use_candidate_set___(void * jarg1, unsigned char jarg2) {
icand_s *arg1 = (icand_s *) 0 ;
uint8_t arg2 ;
arg1 = (icand_s *)jarg1;
arg2 = (uint8_t)jarg2;
if (arg1) (arg1)->use_candidate = arg2;
}
SWIGEXPORT unsigned char SWIGSTDCALL CSharp_FreeSWITCHfNative_icand_t_use_candidate_get___(void * jarg1) {
unsigned char jresult ;
icand_s *arg1 = (icand_s *) 0 ;
uint8_t result;
arg1 = (icand_s *)jarg1;
result = (uint8_t) ((arg1)->use_candidate);
jresult = result;
return jresult;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_FreeSWITCHfNative_new_icand_t___() { SWIGEXPORT void * SWIGSTDCALL CSharp_FreeSWITCHfNative_new_icand_t___() {
void * jresult ; void * jresult ;
icand_s *result = 0 ; icand_s *result = 0 ;

View File

@ -11585,6 +11585,11 @@ else
return ret; return ret;
} }
public static int switch_rand() {
int ret = freeswitchPINVOKE.switch_rand();
return ret;
}
public static switch_caller_extension switch_caller_extension_new(SWIGTYPE_p_switch_core_session session, string extension_name, string extension_number) { public static switch_caller_extension switch_caller_extension_new(SWIGTYPE_p_switch_core_session session, string extension_name, string extension_number) {
global::System.IntPtr cPtr = freeswitchPINVOKE.switch_caller_extension_new(SWIGTYPE_p_switch_core_session.getCPtr(session), extension_name, extension_number); global::System.IntPtr cPtr = freeswitchPINVOKE.switch_caller_extension_new(SWIGTYPE_p_switch_core_session.getCPtr(session), extension_name, extension_number);
switch_caller_extension ret = (cPtr == global::System.IntPtr.Zero) ? null : new switch_caller_extension(cPtr, false); switch_caller_extension ret = (cPtr == global::System.IntPtr.Zero) ? null : new switch_caller_extension(cPtr, false);
@ -15179,6 +15184,7 @@ else
public static readonly int SWITCH_MAX_STATE_HANDLERS = freeswitchPINVOKE.SWITCH_MAX_STATE_HANDLERS_get(); public static readonly int SWITCH_MAX_STATE_HANDLERS = freeswitchPINVOKE.SWITCH_MAX_STATE_HANDLERS_get();
public static readonly int SWITCH_CORE_QUEUE_LEN = freeswitchPINVOKE.SWITCH_CORE_QUEUE_LEN_get(); public static readonly int SWITCH_CORE_QUEUE_LEN = freeswitchPINVOKE.SWITCH_CORE_QUEUE_LEN_get();
public static readonly int SWITCH_MAX_MANAGEMENT_BUFFER_LEN = freeswitchPINVOKE.SWITCH_MAX_MANAGEMENT_BUFFER_LEN_get(); public static readonly int SWITCH_MAX_MANAGEMENT_BUFFER_LEN = freeswitchPINVOKE.SWITCH_MAX_MANAGEMENT_BUFFER_LEN_get();
public static readonly int SWITCH_RAND_MAX = freeswitchPINVOKE.SWITCH_RAND_MAX_get();
public static readonly int SWITCH_RTP_CNG_PAYLOAD = freeswitchPINVOKE.SWITCH_RTP_CNG_PAYLOAD_get(); public static readonly int SWITCH_RTP_CNG_PAYLOAD = freeswitchPINVOKE.SWITCH_RTP_CNG_PAYLOAD_get();
public static readonly int SWITCH_MEDIA_TYPE_TOTAL = freeswitchPINVOKE.SWITCH_MEDIA_TYPE_TOTAL_get(); public static readonly int SWITCH_MEDIA_TYPE_TOTAL = freeswitchPINVOKE.SWITCH_MEDIA_TYPE_TOTAL_get();
public static readonly int SWITCH_SOCK_INVALID = freeswitchPINVOKE.SWITCH_SOCK_INVALID_get(); public static readonly int SWITCH_SOCK_INVALID = freeswitchPINVOKE.SWITCH_SOCK_INVALID_get();
@ -15975,6 +15981,18 @@ class freeswitchPINVOKE {
[global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_LOST_BURST_CAPTURE_get___")] [global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_LOST_BURST_CAPTURE_get___")]
public static extern int LOST_BURST_CAPTURE_get(); public static extern int LOST_BURST_CAPTURE_get();
[global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_switch_uint31_t_value_set___")]
public static extern void switch_uint31_t_value_set(global::System.Runtime.InteropServices.HandleRef jarg1, uint jarg2);
[global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_switch_uint31_t_value_get___")]
public static extern uint switch_uint31_t_value_get(global::System.Runtime.InteropServices.HandleRef jarg1);
[global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_new_switch_uint31_t___")]
public static extern global::System.IntPtr new_switch_uint31_t();
[global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_delete_switch_uint31_t___")]
public static extern void delete_switch_uint31_t(global::System.Runtime.InteropServices.HandleRef jarg1);
[global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_switch_dtmf_t_digit_set___")] [global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_switch_dtmf_t_digit_set___")]
public static extern void switch_dtmf_t_digit_set(global::System.Runtime.InteropServices.HandleRef jarg1, char jarg2); public static extern void switch_dtmf_t_digit_set(global::System.Runtime.InteropServices.HandleRef jarg1, char jarg2);
@ -16275,6 +16293,9 @@ class freeswitchPINVOKE {
[global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_SWITCH_MAX_MANAGEMENT_BUFFER_LEN_get___")] [global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_SWITCH_MAX_MANAGEMENT_BUFFER_LEN_get___")]
public static extern int SWITCH_MAX_MANAGEMENT_BUFFER_LEN_get(); public static extern int SWITCH_MAX_MANAGEMENT_BUFFER_LEN_get();
[global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_SWITCH_RAND_MAX_get___")]
public static extern int SWITCH_RAND_MAX_get();
[global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_switch_error_period_t_start_set___")] [global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_switch_error_period_t_start_set___")]
public static extern void switch_error_period_t_start_set(global::System.Runtime.InteropServices.HandleRef jarg1, long jarg2); public static extern void switch_error_period_t_start_set(global::System.Runtime.InteropServices.HandleRef jarg1, long jarg2);
@ -21099,6 +21120,9 @@ class freeswitchPINVOKE {
[global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_switch_memory_usage_stream___")] [global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_switch_memory_usage_stream___")]
public static extern string switch_memory_usage_stream(global::System.Runtime.InteropServices.HandleRef jarg1); public static extern string switch_memory_usage_stream(global::System.Runtime.InteropServices.HandleRef jarg1);
[global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_switch_rand___")]
public static extern int switch_rand();
[global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_profile_node_t_var_set___")] [global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_profile_node_t_var_set___")]
public static extern void profile_node_t_var_set(global::System.Runtime.InteropServices.HandleRef jarg1, string jarg2); public static extern void profile_node_t_var_set(global::System.Runtime.InteropServices.HandleRef jarg1, string jarg2);
@ -26316,6 +26340,18 @@ class freeswitchPINVOKE {
[global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_icand_t_ready_get___")] [global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_icand_t_ready_get___")]
public static extern byte icand_t_ready_get(global::System.Runtime.InteropServices.HandleRef jarg1); public static extern byte icand_t_ready_get(global::System.Runtime.InteropServices.HandleRef jarg1);
[global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_icand_t_responsive_set___")]
public static extern void icand_t_responsive_set(global::System.Runtime.InteropServices.HandleRef jarg1, byte jarg2);
[global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_icand_t_responsive_get___")]
public static extern byte icand_t_responsive_get(global::System.Runtime.InteropServices.HandleRef jarg1);
[global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_icand_t_use_candidate_set___")]
public static extern void icand_t_use_candidate_set(global::System.Runtime.InteropServices.HandleRef jarg1, byte jarg2);
[global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_icand_t_use_candidate_get___")]
public static extern byte icand_t_use_candidate_get(global::System.Runtime.InteropServices.HandleRef jarg1);
[global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_new_icand_t___")] [global::System.Runtime.InteropServices.DllImport("mod_managed", EntryPoint="CSharp_FreeSWITCHfNative_new_icand_t___")]
public static extern global::System.IntPtr new_icand_t(); public static extern global::System.IntPtr new_icand_t();
@ -28339,6 +28375,26 @@ public class icand_t : global::System.IDisposable {
} }
} }
public byte responsive {
set {
freeswitchPINVOKE.icand_t_responsive_set(swigCPtr, value);
}
get {
byte ret = freeswitchPINVOKE.icand_t_responsive_get(swigCPtr);
return ret;
}
}
public byte use_candidate {
set {
freeswitchPINVOKE.icand_t_use_candidate_set(swigCPtr, value);
}
get {
byte ret = freeswitchPINVOKE.icand_t_use_candidate_get(swigCPtr);
return ret;
}
}
public icand_t() : this(freeswitchPINVOKE.new_icand_t(), true) { public icand_t() : this(freeswitchPINVOKE.new_icand_t(), true) {
} }
@ -45023,8 +45079,8 @@ public class switch_scheduler_task : global::System.IDisposable {
namespace FreeSWITCH.Native { namespace FreeSWITCH.Native {
public enum switch_sdp_type_t { public enum switch_sdp_type_t {
SDP_TYPE_REQUEST, SDP_OFFER,
SDP_TYPE_RESPONSE SDP_ANSWER
} }
} }
@ -47301,6 +47357,64 @@ public class switch_timer_interface : global::System.IDisposable {
namespace FreeSWITCH.Native { namespace FreeSWITCH.Native {
public class switch_uint31_t : global::System.IDisposable {
private global::System.Runtime.InteropServices.HandleRef swigCPtr;
protected bool swigCMemOwn;
internal switch_uint31_t(global::System.IntPtr cPtr, bool cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr);
}
internal static global::System.Runtime.InteropServices.HandleRef getCPtr(switch_uint31_t obj) {
return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr;
}
~switch_uint31_t() {
Dispose();
}
public virtual void Dispose() {
lock(this) {
if (swigCPtr.Handle != global::System.IntPtr.Zero) {
if (swigCMemOwn) {
swigCMemOwn = false;
freeswitchPINVOKE.delete_switch_uint31_t(swigCPtr);
}
swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero);
}
global::System.GC.SuppressFinalize(this);
}
}
public uint value {
set {
freeswitchPINVOKE.switch_uint31_t_value_set(swigCPtr, value);
}
get {
uint ret = freeswitchPINVOKE.switch_uint31_t_value_get(swigCPtr);
return ret;
}
}
public switch_uint31_t() : this(freeswitchPINVOKE.new_switch_uint31_t(), true) {
}
}
}
//------------------------------------------------------------------------------
// <auto-generated />
//
// This file was automatically generated by SWIG (http://www.swig.org).
// Version 3.0.12
//
// Do not make changes to this file unless you know what you are doing--modify
// the SWIG interface file instead.
//------------------------------------------------------------------------------
namespace FreeSWITCH.Native {
public class switch_unicast_conninfo : global::System.IDisposable { public class switch_unicast_conninfo : global::System.IDisposable {
private global::System.Runtime.InteropServices.HandleRef swigCPtr; private global::System.Runtime.InteropServices.HandleRef swigCPtr;
protected bool swigCMemOwn; protected bool swigCMemOwn;

View File

@ -671,7 +671,7 @@ JS_SESSION_FUNCTION_IMPL(SayPhrase)
String::Utf8Value str(info[2]); String::Utf8Value str(info[2]);
tmp = js_safe_str(*str); tmp = js_safe_str(*str);
if (!zstr(tmp.c_str())) { if (!zstr(tmp.c_str())) {
phrase_lang = tmp; phrase_lang = std::move(tmp);
} }
} }

View File

@ -713,7 +713,7 @@ SWITCH_DECLARE(payload_map_t *) switch_core_media_add_payload_map(switch_core_se
for (pmap = engine->payload_map; pmap && pmap->allocated; pmap = pmap->next) { for (pmap = engine->payload_map; pmap && pmap->allocated; pmap = pmap->next) {
if (sdp_type == SDP_TYPE_RESPONSE) { if (sdp_type == SDP_ANSWER) {
switch(type) { switch(type) {
case SWITCH_MEDIA_TYPE_TEXT: case SWITCH_MEDIA_TYPE_TEXT:
exists = (type == pmap->type && !strcasecmp(name, pmap->iananame)); exists = (type == pmap->type && !strcasecmp(name, pmap->iananame));
@ -722,11 +722,11 @@ SWITCH_DECLARE(payload_map_t *) switch_core_media_add_payload_map(switch_core_se
exists = (type == pmap->type && !strcasecmp(name, pmap->iananame) && pmap->pt == pt && (!pmap->rate || rate == pmap->rate) && (!pmap->ptime || pmap->ptime == ptime)); exists = (type == pmap->type && !strcasecmp(name, pmap->iananame) && pmap->pt == pt && (!pmap->rate || rate == pmap->rate) && (!pmap->ptime || pmap->ptime == ptime));
break; break;
case SWITCH_MEDIA_TYPE_VIDEO: case SWITCH_MEDIA_TYPE_VIDEO:
exists = (pmap->sdp_type == SDP_TYPE_REQUEST && type == pmap->type && !strcasecmp(name, pmap->iananame)); exists = (pmap->sdp_type == SDP_OFFER && type == pmap->type && !strcasecmp(name, pmap->iananame));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "CHECK PMAP %s:%s %d %s:%s %d ... %d\n", switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "CHECK PMAP %s:%s %d %s:%s %d ... %d\n",
name, "RES", pt, name, "RES", pt,
pmap->iananame, pmap->sdp_type == SDP_TYPE_REQUEST ? "REQ" : "RES", pmap->pt, exists); pmap->iananame, pmap->sdp_type == SDP_OFFER ? "REQ" : "RES", pmap->pt, exists);
break; break;
@ -797,7 +797,7 @@ SWITCH_DECLARE(payload_map_t *) switch_core_media_add_payload_map(switch_core_se
} }
if (!zstr(fmtp)) { if (!zstr(fmtp)) {
if (sdp_type == SDP_TYPE_REQUEST || !exists) { if (sdp_type == SDP_OFFER || !exists) {
pmap->rm_fmtp = switch_core_strdup(session->pool, fmtp); pmap->rm_fmtp = switch_core_strdup(session->pool, fmtp);
} }
} }
@ -807,7 +807,7 @@ SWITCH_DECLARE(payload_map_t *) switch_core_media_add_payload_map(switch_core_se
pmap->recv_pt = (switch_payload_t) pt; pmap->recv_pt = (switch_payload_t) pt;
if (sdp_type == SDP_TYPE_REQUEST || !exists) { if (sdp_type == SDP_OFFER || !exists) {
pmap->pt = (switch_payload_t) pt; pmap->pt = (switch_payload_t) pt;
} }
@ -818,7 +818,7 @@ SWITCH_DECLARE(payload_map_t *) switch_core_media_add_payload_map(switch_core_se
if (!exists) { if (!exists) {
pmap->sdp_type = sdp_type; pmap->sdp_type = sdp_type;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "ADD PMAP %s %s %d\n", sdp_type == SDP_TYPE_REQUEST ? "REQ" : "RES", name, pt); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "ADD PMAP %s %s %d\n", sdp_type == SDP_OFFER ? "REQ" : "RES", name, pt);
if (pmap == engine->payload_map) { if (pmap == engine->payload_map) {
engine->pmap_tail = pmap; engine->pmap_tail = pmap;
@ -1724,7 +1724,7 @@ SWITCH_DECLARE(int) switch_core_session_check_incoming_crypto(switch_core_sessio
const char *a = switch_stristr("AE", engine->ssec[engine->crypto_type].remote_crypto_key); const char *a = switch_stristr("AE", engine->ssec[engine->crypto_type].remote_crypto_key);
const char *b = switch_stristr("AE", crypto); const char *b = switch_stristr("AE", crypto);
if (sdp_type == SDP_TYPE_REQUEST) { if (sdp_type == SDP_OFFER) {
if (!vval) { if (!vval) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Unsupported Crypto [%s]\n", crypto); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Unsupported Crypto [%s]\n", crypto);
goto end; goto end;
@ -4633,7 +4633,7 @@ static void check_stream_changes(switch_core_session_t *session, const char *r_s
switch_channel_set_flag(other_session->channel, CF_PROCESSING_STREAM_CHANGE); switch_channel_set_flag(other_session->channel, CF_PROCESSING_STREAM_CHANGE);
switch_channel_set_flag(session->channel, CF_AWAITING_STREAM_CHANGE); switch_channel_set_flag(session->channel, CF_AWAITING_STREAM_CHANGE);
if (sdp_type == SDP_TYPE_REQUEST && r_sdp) { if (sdp_type == SDP_OFFER && r_sdp) {
const char *filter_codec_string = switch_channel_get_variable(session->channel, "filter_codec_string"); const char *filter_codec_string = switch_channel_get_variable(session->channel, "filter_codec_string");
switch_channel_set_variable(session->channel, "codec_string", NULL); switch_channel_set_variable(session->channel, "codec_string", NULL);
@ -4654,7 +4654,7 @@ static void check_stream_changes(switch_core_session_t *session, const char *r_s
} }
if (other_session) { if (other_session) {
if (sdp_type == SDP_TYPE_RESPONSE && switch_channel_test_flag(session->channel, CF_PROCESSING_STREAM_CHANGE)) { if (sdp_type == SDP_ANSWER && switch_channel_test_flag(session->channel, CF_PROCESSING_STREAM_CHANGE)) {
switch_channel_clear_flag(session->channel, CF_PROCESSING_STREAM_CHANGE); switch_channel_clear_flag(session->channel, CF_PROCESSING_STREAM_CHANGE);
if (switch_channel_test_flag(other_session->channel, CF_AWAITING_STREAM_CHANGE)) { if (switch_channel_test_flag(other_session->channel, CF_AWAITING_STREAM_CHANGE)) {
@ -4667,7 +4667,7 @@ static void check_stream_changes(switch_core_session_t *session, const char *r_s
} }
sdp_in = switch_channel_get_variable(other_session->channel, SWITCH_R_SDP_VARIABLE); sdp_in = switch_channel_get_variable(other_session->channel, SWITCH_R_SDP_VARIABLE);
res = switch_core_media_negotiate_sdp(other_session, sdp_in, &proceed, SDP_TYPE_REQUEST); res = switch_core_media_negotiate_sdp(other_session, sdp_in, &proceed, SDP_OFFER);
(void)res; (void)res;
switch_core_media_activate_rtp(other_session); switch_core_media_activate_rtp(other_session);
msg = switch_core_session_alloc(other_session, sizeof(*msg)); msg = switch_core_session_alloc(other_session, sizeof(*msg));
@ -4715,11 +4715,11 @@ SWITCH_DECLARE(void) switch_core_media_set_smode(switch_core_session_t *session,
engine->pass_codecs = 0; engine->pass_codecs = 0;
if (switch_channel_var_true(session->channel, "rtp_pass_codecs_on_stream_change")) { if (switch_channel_var_true(session->channel, "rtp_pass_codecs_on_stream_change")) {
if (sdp_type == SDP_TYPE_REQUEST && switch_channel_test_flag(session->channel, CF_REINVITE) && if (sdp_type == SDP_OFFER && switch_channel_test_flag(session->channel, CF_REINVITE) &&
switch_channel_media_up(session->channel) && (pass_codecs || old_smode != smode)) { switch_channel_media_up(session->channel) && (pass_codecs || old_smode != smode)) {
if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) { if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
switch_core_media_set_smode(other_session, type, opp_smode, SDP_TYPE_REQUEST); switch_core_media_set_smode(other_session, type, opp_smode, SDP_OFFER);
switch_channel_set_flag(session->channel, CF_STREAM_CHANGED); switch_channel_set_flag(session->channel, CF_STREAM_CHANGED);
switch_core_session_rwunlock(other_session); switch_core_session_rwunlock(other_session);
} }
@ -4752,7 +4752,7 @@ static void switch_core_media_set_rmode(switch_core_session_t *session, switch_m
if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) { if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
if (sdp_type == SDP_TYPE_RESPONSE && (switch_channel_test_flag(other_session->channel, CF_REINVITE) || switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND)) { if (sdp_type == SDP_ANSWER && (switch_channel_test_flag(other_session->channel, CF_REINVITE) || switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND)) {
switch_core_media_set_smode(other_session, type, rmode, sdp_type); switch_core_media_set_smode(other_session, type, rmode, sdp_type);
} }
@ -5099,7 +5099,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
switch_channel_clear_app_flag_key("T38", session->channel, CF_APP_T38); switch_channel_clear_app_flag_key("T38", session->channel, CF_APP_T38);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s T38 REFUSE on %s\n", switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s T38 REFUSE on %s\n",
switch_channel_get_name(channel), switch_channel_get_name(channel),
sdp_type == SDP_TYPE_RESPONSE ? "response" : "request"); sdp_type == SDP_ANSWER ? "response" : "request");
restore_pmaps(a_engine); restore_pmaps(a_engine);
fmatch = 0; fmatch = 0;
@ -5112,7 +5112,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s T38 ACCEPT on %s\n", switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s T38 ACCEPT on %s\n",
switch_channel_get_name(channel), switch_channel_get_name(channel),
sdp_type == SDP_TYPE_RESPONSE ? "response" : "request"); sdp_type == SDP_ANSWER ? "response" : "request");
if (switch_channel_test_app_flag_key("T38", session->channel, CF_APP_T38)) { if (switch_channel_test_app_flag_key("T38", session->channel, CF_APP_T38)) {
if (proceed) *proceed = 0; if (proceed) *proceed = 0;
@ -5217,7 +5217,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s T38 %s POSSIBLE on %s\n", switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s T38 %s POSSIBLE on %s\n",
switch_channel_get_name(channel), switch_channel_get_name(channel),
fmatch ? "IS" : "IS NOT", fmatch ? "IS" : "IS NOT",
sdp_type == SDP_TYPE_RESPONSE ? "response" : "request"); sdp_type == SDP_ANSWER ? "response" : "request");
goto done; goto done;
@ -5249,7 +5249,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
switch_core_media_set_rmode(smh->session, SWITCH_MEDIA_TYPE_AUDIO, sdp_media_flow(m->m_mode), sdp_type); switch_core_media_set_rmode(smh->session, SWITCH_MEDIA_TYPE_AUDIO, sdp_media_flow(m->m_mode), sdp_type);
if (sdp_type == SDP_TYPE_REQUEST) { if (sdp_type == SDP_OFFER) {
switch(a_engine->rmode) { switch(a_engine->rmode) {
case SWITCH_MEDIA_FLOW_RECVONLY: case SWITCH_MEDIA_FLOW_RECVONLY:
switch_core_media_set_smode(smh->session, SWITCH_MEDIA_TYPE_AUDIO, SWITCH_MEDIA_FLOW_SENDONLY, sdp_type); switch_core_media_set_smode(smh->session, SWITCH_MEDIA_TYPE_AUDIO, SWITCH_MEDIA_FLOW_SENDONLY, sdp_type);
@ -5315,7 +5315,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
switch_channel_set_variable(session->channel, "media_audio_mode", NULL); switch_channel_set_variable(session->channel, "media_audio_mode", NULL);
} }
if (sdp_type == SDP_TYPE_RESPONSE) { if (sdp_type == SDP_ANSWER) {
if (inactive) { if (inactive) {
// When freeswitch had previously sent inactive in sip request. it should remain inactive otherwise smode should be sendrecv // When freeswitch had previously sent inactive in sip request. it should remain inactive otherwise smode should be sendrecv
if (a_engine->smode==SWITCH_MEDIA_FLOW_INACTIVE) { if (a_engine->smode==SWITCH_MEDIA_FLOW_INACTIVE) {
@ -5834,7 +5834,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
if (smh->mparams->dtmf_type == DTMF_AUTO || smh->mparams->dtmf_type == DTMF_2833 || if (smh->mparams->dtmf_type == DTMF_AUTO || smh->mparams->dtmf_type == DTMF_2833 ||
switch_channel_test_flag(session->channel, CF_LIBERAL_DTMF)) { switch_channel_test_flag(session->channel, CF_LIBERAL_DTMF)) {
if (sdp_type == SDP_TYPE_REQUEST) { if (sdp_type == SDP_OFFER) {
smh->mparams->te = smh->mparams->recv_te = (switch_payload_t) best_te; smh->mparams->te = smh->mparams->recv_te = (switch_payload_t) best_te;
switch_channel_set_variable(session->channel, "dtmf_type", "rfc2833"); switch_channel_set_variable(session->channel, "dtmf_type", "rfc2833");
smh->mparams->dtmf_type = DTMF_2833; smh->mparams->dtmf_type = DTMF_2833;
@ -5902,7 +5902,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
map->rm_encoding, map->rm_encoding,
NULL, NULL,
NULL, NULL,
SDP_TYPE_REQUEST, SDP_OFFER,
map->rm_pt, map->rm_pt,
1000, 1000,
0, 0,
@ -5980,7 +5980,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
switch_core_media_set_rmode(smh->session, SWITCH_MEDIA_TYPE_VIDEO, sdp_media_flow(m->m_mode), sdp_type); switch_core_media_set_rmode(smh->session, SWITCH_MEDIA_TYPE_VIDEO, sdp_media_flow(m->m_mode), sdp_type);
if (sdp_type == SDP_TYPE_REQUEST) { if (sdp_type == SDP_OFFER) {
sdp_bandwidth_t *bw; sdp_bandwidth_t *bw;
int tias = 0; int tias = 0;
@ -6146,7 +6146,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
vmatch = strcasecmp(rm_encoding, imp->iananame) ? 0 : 1; vmatch = strcasecmp(rm_encoding, imp->iananame) ? 0 : 1;
} }
if (sdp_type == SDP_TYPE_RESPONSE && consider_video_fmtp && vmatch && !zstr(map->rm_fmtp) && !zstr(smh->fmtps[i])) { if (sdp_type == SDP_ANSWER && consider_video_fmtp && vmatch && !zstr(map->rm_fmtp) && !zstr(smh->fmtps[i])) {
almost_vmatch = 1; almost_vmatch = 1;
vmatch = !strcasecmp(smh->fmtps[i], map->rm_fmtp); vmatch = !strcasecmp(smh->fmtps[i], map->rm_fmtp);
} }
@ -6321,7 +6321,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
"L16", "L16",
NULL, NULL,
NULL, NULL,
SDP_TYPE_REQUEST, SDP_OFFER,
97, 97,
8000, 8000,
20, 20,
@ -6378,7 +6378,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
if (switch_channel_test_flag(channel, CF_VIDEO) && !saw_video) { if (switch_channel_test_flag(channel, CF_VIDEO) && !saw_video) {
//switch_core_media_set_rmode(smh->session, SWITCH_MEDIA_TYPE_VIDEO, SWITCH_MEDIA_FLOW_INACTIVE, sdp_type); //switch_core_media_set_rmode(smh->session, SWITCH_MEDIA_TYPE_VIDEO, SWITCH_MEDIA_FLOW_INACTIVE, sdp_type);
if (sdp_type == SDP_TYPE_REQUEST) { if (sdp_type == SDP_OFFER) {
switch_core_media_set_smode(smh->session, SWITCH_MEDIA_TYPE_VIDEO, SWITCH_MEDIA_FLOW_INACTIVE, sdp_type); switch_core_media_set_smode(smh->session, SWITCH_MEDIA_TYPE_VIDEO, SWITCH_MEDIA_FLOW_INACTIVE, sdp_type);
} }
} }
@ -9708,7 +9708,7 @@ static const char *get_media_profile_name(switch_core_session_t *session, int se
static char *get_setup(switch_rtp_engine_t *engine, switch_core_session_t *session, switch_sdp_type_t sdp_type) static char *get_setup(switch_rtp_engine_t *engine, switch_core_session_t *session, switch_sdp_type_t sdp_type)
{ {
if (sdp_type == SDP_TYPE_REQUEST) { if (sdp_type == SDP_OFFER) {
engine->dtls_controller = 0; engine->dtls_controller = 0;
engine->new_dtls = 1; engine->new_dtls = 1;
engine->new_ice = 1; engine->new_ice = 1;
@ -9809,7 +9809,7 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen,
} }
if (smh->mparams->dtmf_type == DTMF_2833 && smh->mparams->te > 95) { if (smh->mparams->dtmf_type == DTMF_2833 && smh->mparams->te > 95) {
if (sdp_type == SDP_TYPE_RESPONSE) { if (sdp_type == SDP_ANSWER) {
switch_rtp_engine_t *a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO]; switch_rtp_engine_t *a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
if (a_engine) { if (a_engine) {
payload_map_t *pmap; payload_map_t *pmap;
@ -9915,7 +9915,7 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen,
if ((smh->mparams->dtmf_type == DTMF_2833 || switch_channel_test_flag(session->channel, CF_LIBERAL_DTMF)) && smh->mparams->te > 95) { if ((smh->mparams->dtmf_type == DTMF_2833 || switch_channel_test_flag(session->channel, CF_LIBERAL_DTMF)) && smh->mparams->te > 95) {
if (smh->mparams->dtmf_type == DTMF_2833 && sdp_type == SDP_TYPE_RESPONSE) { if (smh->mparams->dtmf_type == DTMF_2833 && sdp_type == SDP_ANSWER) {
switch_rtp_engine_t *a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO]; switch_rtp_engine_t *a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
if (a_engine) { if (a_engine) {
payload_map_t *pmap; payload_map_t *pmap;
@ -10264,7 +10264,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
v_engine->rtcp_mux = -1; v_engine->rtcp_mux = -1;
} }
if ((a_engine->rtcp_mux != -1 && v_engine->rtcp_mux != -1) && (sdp_type == SDP_TYPE_REQUEST)) { if ((a_engine->rtcp_mux != -1 && v_engine->rtcp_mux != -1) && (sdp_type == SDP_OFFER)) {
a_engine->rtcp_mux = 1; a_engine->rtcp_mux = 1;
v_engine->rtcp_mux = 1; v_engine->rtcp_mux = 1;
} }
@ -10347,7 +10347,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
continue; continue;
} }
if (sdp_type == SDP_TYPE_REQUEST) { if (sdp_type == SDP_OFFER) {
for (j = 0; j < SWITCH_MAX_CODECS; j++) { for (j = 0; j < SWITCH_MAX_CODECS; j++) {
if (smh->rates[j] == 0) { if (smh->rates[j] == 0) {
break; break;
@ -10365,7 +10365,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
continue; continue;
} }
if (sdp_type == SDP_TYPE_REQUEST) { if (sdp_type == SDP_OFFER) {
switch_core_session_t *orig_session = NULL; switch_core_session_t *orig_session = NULL;
switch_core_session_get_partner(session, &orig_session); switch_core_session_get_partner(session, &orig_session);
@ -11180,7 +11180,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
} }
} }
if (sdp_type == SDP_TYPE_REQUEST) { if (sdp_type == SDP_OFFER) {
fir++; fir++;
pli++; pli++;
nack++; nack++;
@ -11441,7 +11441,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
// RTP TEXT // RTP TEXT
if (sdp_type == SDP_TYPE_RESPONSE && !switch_channel_test_flag(session->channel, CF_RTT)) { if (sdp_type == SDP_ANSWER && !switch_channel_test_flag(session->channel, CF_RTT)) {
if (switch_channel_test_flag(session->channel, CF_TEXT_SDP_RECVD)) { if (switch_channel_test_flag(session->channel, CF_TEXT_SDP_RECVD)) {
switch_channel_clear_flag(session->channel, CF_TEXT_SDP_RECVD); switch_channel_clear_flag(session->channel, CF_TEXT_SDP_RECVD);
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=text 0 %s 19\r\n", switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=text 0 %s 19\r\n",
@ -11456,7 +11456,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
t_engine->t140_pt = 0; t_engine->t140_pt = 0;
t_engine->red_pt = 0; t_engine->red_pt = 0;
if (sdp_type == SDP_TYPE_REQUEST) { if (sdp_type == SDP_OFFER) {
t_engine->t140_pt = 96; t_engine->t140_pt = 96;
t_engine->red_pt = 97; t_engine->red_pt = 97;
@ -11465,7 +11465,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
"red", "red",
NULL, NULL,
NULL, NULL,
SDP_TYPE_REQUEST, SDP_OFFER,
t_engine->red_pt, t_engine->red_pt,
1000, 1000,
0, 0,
@ -11477,7 +11477,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
"t140", "t140",
NULL, NULL,
NULL, NULL,
SDP_TYPE_REQUEST, SDP_OFFER,
t_engine->t140_pt, t_engine->t140_pt,
1000, 1000,
0, 0,
@ -11978,7 +11978,7 @@ SWITCH_DECLARE(void) switch_core_media_patch_sdp(switch_core_session_t *session)
"PROXY", "PROXY",
NULL, NULL,
NULL, NULL,
SDP_TYPE_RESPONSE, SDP_ANSWER,
0, 0,
8000, 8000,
20, 20,
@ -12135,7 +12135,7 @@ SWITCH_DECLARE(void) switch_core_media_patch_sdp(switch_core_session_t *session)
"PROXY-VID", "PROXY-VID",
NULL, NULL,
NULL, NULL,
SDP_TYPE_RESPONSE, SDP_ANSWER,
0, 0,
90000, 90000,
90000, 90000,
@ -12198,7 +12198,7 @@ SWITCH_DECLARE(void) switch_core_media_patch_sdp(switch_core_session_t *session)
"PROXY-TXT", "PROXY-TXT",
NULL, NULL,
NULL, NULL,
SDP_TYPE_RESPONSE, SDP_ANSWER,
0, 0,
90000, 90000,
90000, 90000,
@ -13099,7 +13099,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_se
switch_core_media_prepare_codecs(session, 1); switch_core_media_prepare_codecs(session, 1);
clear_pmaps(a_engine); clear_pmaps(a_engine);
clear_pmaps(v_engine); clear_pmaps(v_engine);
switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, ip, (switch_port_t)atoi(port), NULL, 1); switch_core_media_gen_local_sdp(session, SDP_OFFER, ip, (switch_port_t)atoi(port), NULL, 1);
} }
} }
@ -13151,7 +13151,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_se
switch_core_media_prepare_codecs(session, SWITCH_TRUE); switch_core_media_prepare_codecs(session, SWITCH_TRUE);
switch_core_media_check_video_codecs(session); switch_core_media_check_video_codecs(session);
switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 1); switch_core_media_gen_local_sdp(session, SDP_OFFER, NULL, 0, NULL, 1);
} }
if (msg->numeric_arg && switch_core_session_get_partner(session, &nsession) == SWITCH_STATUS_SUCCESS) { if (msg->numeric_arg && switch_core_session_get_partner(session, &nsession) == SWITCH_STATUS_SUCCESS) {
@ -13964,7 +13964,7 @@ SWITCH_DECLARE(void) switch_core_media_check_outgoing_proxy(switch_core_session_
"PROXY", "PROXY",
NULL, NULL,
NULL, NULL,
SDP_TYPE_RESPONSE, SDP_ANSWER,
0, 0,
8000, 8000,
20, 20,
@ -13980,7 +13980,7 @@ SWITCH_DECLARE(void) switch_core_media_check_outgoing_proxy(switch_core_session_
"PROXY-VID", "PROXY-VID",
NULL, NULL,
NULL, NULL,
SDP_TYPE_RESPONSE, SDP_ANSWER,
0, 0,
90000, 90000,
90000, 90000,
@ -14001,7 +14001,7 @@ SWITCH_DECLARE(void) switch_core_media_check_outgoing_proxy(switch_core_session_
"PROXY-TXT", "PROXY-TXT",
NULL, NULL,
NULL, NULL,
SDP_TYPE_RESPONSE, SDP_ANSWER,
0, 0,
1000, 1000,
1000, 1000,
@ -14155,7 +14155,7 @@ SWITCH_DECLARE (void) switch_core_media_recover_session(switch_core_session_t *s
} }
} }
switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 1); switch_core_media_gen_local_sdp(session, SDP_OFFER, NULL, 0, NULL, 1);
switch_core_media_set_video_codec(session, 1); switch_core_media_set_video_codec(session, 1);
if (switch_core_media_activate_rtp(session) != SWITCH_STATUS_SUCCESS) { if (switch_core_media_activate_rtp(session) != SWITCH_STATUS_SUCCESS) {

View File

@ -150,12 +150,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_port_allocator_request_port(switch_c
switch_mutex_lock(alloc->mutex); switch_mutex_lock(alloc->mutex);
srand((unsigned) ((unsigned) (intptr_t) port_ptr + (unsigned) (intptr_t) switch_thread_self() + switch_micro_time_now())); srand((unsigned) ((unsigned) (intptr_t) port_ptr + (unsigned) (intptr_t) switch_thread_self() + switch_micro_time_now()));
while (alloc->track_used < alloc->track_len) { while (alloc->track_len && alloc->track_used < alloc->track_len) {
uint32_t index; uint32_t index;
uint32_t tries = 0; uint32_t tries = 0;
/* randomly pick a port */ /* randomly pick a port */
index = rand() % alloc->track_len; index = switch_rand() % alloc->track_len;
/* if it is used walk up the list to find a free one */ /* if it is used walk up the list to find a free one */
while (alloc->track[index] && tries < alloc->track_len) { while (alloc->track[index] && tries < alloc->track_len) {

View File

@ -702,7 +702,7 @@ static switch_status_t switch_cache_db_execute_sql_real(switch_cache_db_handle_t
case SCDB_TYPE_ODBC: case SCDB_TYPE_ODBC:
{ {
type = "ODBC"; type = "ODBC";
status = switch_odbc_handle_exec(dbh->native_handle.odbc_dbh, sql, NULL, &errmsg); status = switch_odbc_handle_exec(dbh->native_handle.odbc_dbh, sql, NULL, &errmsg) == SWITCH_ODBC_SUCCESS ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
} }
break; break;
case SCDB_TYPE_CORE_DB: case SCDB_TYPE_CORE_DB:
@ -904,7 +904,7 @@ SWITCH_DECLARE(char *) switch_cache_db_execute_sql2str(switch_cache_db_handle_t
break; break;
case SCDB_TYPE_ODBC: case SCDB_TYPE_ODBC:
{ {
status = switch_odbc_handle_exec_string(dbh->native_handle.odbc_dbh, sql, str, len, err); status = switch_odbc_handle_exec_string(dbh->native_handle.odbc_dbh, sql, str, len, err) == SWITCH_ODBC_SUCCESS ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
} }
break; break;
case SCDB_TYPE_DATABASE_INTERFACE: case SCDB_TYPE_DATABASE_INTERFACE:
@ -1189,7 +1189,7 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_execute_sql_event_callback(switc
break; break;
case SCDB_TYPE_ODBC: case SCDB_TYPE_ODBC:
{ {
status = switch_odbc_handle_callback_exec(dbh->native_handle.odbc_dbh, sql, helper_callback, &h, err); status = switch_odbc_handle_callback_exec(dbh->native_handle.odbc_dbh, sql, helper_callback, &h, err) == SWITCH_ODBC_SUCCESS ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
} }
break; break;
case SCDB_TYPE_CORE_DB: case SCDB_TYPE_CORE_DB:
@ -1248,7 +1248,7 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_execute_sql_event_callback_err(s
break; break;
case SCDB_TYPE_ODBC: case SCDB_TYPE_ODBC:
{ {
status = switch_odbc_handle_callback_exec(dbh->native_handle.odbc_dbh, sql, helper_callback, &h, err); status = switch_odbc_handle_callback_exec(dbh->native_handle.odbc_dbh, sql, helper_callback, &h, err) == SWITCH_ODBC_SUCCESS ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
if (err && *err) { if (err && *err) {
(*err_callback)(pdata, (const char*)*err); (*err_callback)(pdata, (const char*)*err);
} }
@ -1305,7 +1305,7 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_execute_sql_callback(switch_cach
break; break;
case SCDB_TYPE_ODBC: case SCDB_TYPE_ODBC:
{ {
status = switch_odbc_handle_callback_exec(dbh->native_handle.odbc_dbh, sql, callback, pdata, err); status = switch_odbc_handle_callback_exec(dbh->native_handle.odbc_dbh, sql, callback, pdata, err) == SWITCH_ODBC_SUCCESS ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
} }
break; break;
case SCDB_TYPE_CORE_DB: case SCDB_TYPE_CORE_DB:
@ -1358,7 +1358,7 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_execute_sql_callback_err(switch_
break; break;
case SCDB_TYPE_ODBC: case SCDB_TYPE_ODBC:
{ {
status = switch_odbc_handle_callback_exec(dbh->native_handle.odbc_dbh, sql, callback, pdata, err); status = switch_odbc_handle_callback_exec(dbh->native_handle.odbc_dbh, sql, callback, pdata, err) == SWITCH_ODBC_SUCCESS ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
if (err && *err) { if (err && *err) {
(*err_callback)(pdata, (const char*)*err); (*err_callback)(pdata, (const char*)*err);
} }

View File

@ -2151,7 +2151,7 @@ SWITCH_DECLARE(void) switch_ivr_check_hold(switch_core_session_t *session)
msg.message_id = SWITCH_MESSAGE_INDICATE_MEDIA_RENEG; msg.message_id = SWITCH_MESSAGE_INDICATE_MEDIA_RENEG;
msg.from = __FILE__; msg.from = __FILE__;
switch_core_media_set_smode(session, SWITCH_MEDIA_TYPE_AUDIO, SWITCH_MEDIA_FLOW_SENDRECV, SDP_TYPE_REQUEST); switch_core_media_set_smode(session, SWITCH_MEDIA_TYPE_AUDIO, SWITCH_MEDIA_FLOW_SENDRECV, SDP_OFFER);
switch_core_session_receive_message(session, &msg); switch_core_session_receive_message(session, &msg);
} }

View File

@ -185,6 +185,10 @@ typedef struct {
char body[SWITCH_RTCP_MAX_BUF_LEN]; char body[SWITCH_RTCP_MAX_BUF_LEN];
} rtcp_msg_t; } rtcp_msg_t;
typedef struct {
switch_rtcp_hdr_t header;
uint32_t ssrc;
} sdes_ssrc_t;
typedef enum { typedef enum {
VAD_FIRE_TALK = (1 << 0), VAD_FIRE_TALK = (1 << 0),
@ -254,10 +258,11 @@ typedef struct {
uint8_t sending; uint8_t sending;
uint8_t ready; uint8_t ready;
uint8_t rready; uint8_t rready;
uint8_t init; uint8_t initializing;
int missed_count; int missed_count;
char last_sent_id[13]; char last_sent_id[13];
switch_time_t last_ok; switch_time_t last_ok;
uint8_t cand_responsive;
} switch_rtp_ice_t; } switch_rtp_ice_t;
struct switch_rtp; struct switch_rtp;
@ -401,7 +406,6 @@ struct switch_rtp {
char *eff_remote_host_str; char *eff_remote_host_str;
switch_time_t first_stun; switch_time_t first_stun;
switch_time_t last_stun; switch_time_t last_stun;
uint32_t wrong_addrs;
uint32_t samples_per_interval; uint32_t samples_per_interval;
uint32_t samples_per_second; uint32_t samples_per_second;
uint32_t conf_samples_per_interval; uint32_t conf_samples_per_interval;
@ -474,7 +478,11 @@ struct switch_rtp {
payload_map_t *pmap_tail; payload_map_t *pmap_tail;
kalman_estimator_t *estimators[KALMAN_SYSTEM_MODELS]; kalman_estimator_t *estimators[KALMAN_SYSTEM_MODELS];
cusum_kalman_detector_t *detectors[KALMAN_SYSTEM_MODELS]; cusum_kalman_detector_t *detectors[KALMAN_SYSTEM_MODELS];
int ice_adj; switch_time_t last_adj;
switch_time_t adj_window;
uint32_t elapsed_stun;
uint32_t elapsed_media;
uint32_t elapsed_adj;
uint8_t has_rtp; uint8_t has_rtp;
uint8_t has_rtcp; uint8_t has_rtcp;
uint8_t has_ice; uint8_t has_ice;
@ -540,9 +548,25 @@ static void switch_rtp_change_ice_dest(switch_rtp_t *rtp_session, switch_rtp_ice
{ {
int is_rtcp = ice == &rtp_session->rtcp_ice; int is_rtcp = ice == &rtp_session->rtcp_ice;
const char *err = ""; const char *err = "";
int i;
uint8_t ice_cand_found_idx = 0;
for (i = 0; i < ice->ice_params->cand_idx[ice->proto]; i++) {
if (!strcmp(host, ice->ice_params->cands[i][ice->proto].con_addr) && port == ice->ice_params->cands[i][ice->proto].con_port) {
ice_cand_found_idx = i;
}
}
if (!ice_cand_found_idx) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG5, "ICE candidate [%s:%d] replaced with [%s:%d]\n",
ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_addr, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_port, host, port);
ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_addr = switch_core_strdup(rtp_session->pool, host);
ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_port = port;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG5, "ICE chosen candidate [%s:%d] set to idx [%d]\n", host, port, ice_cand_found_idx);
ice->ice_params->chosen[ice->proto] = ice_cand_found_idx;
}
ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_addr = switch_core_strdup(rtp_session->pool, host);
ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_port = port;
ice->missed_count = 0; ice->missed_count = 0;
if (is_rtcp) { if (is_rtcp) {
@ -796,7 +820,41 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
rtp_msg_t *send_msg, void *data, uint32_t datalen, switch_payload_t payload, uint32_t timestamp, switch_frame_flag_t *flags); rtp_msg_t *send_msg, void *data, uint32_t datalen, switch_payload_t payload, uint32_t timestamp, switch_frame_flag_t *flags);
static switch_status_t ice_out(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice) #define MEDIA_TOO_LONG 2000
#define STUN_TOO_LONG 20000
#define ADJ_TOO_LONG 1000
static void calc_elapsed(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice)
{
switch_time_t ref_point;
switch_time_t now;
now = switch_micro_time_now();
if (ice->last_ok && (!rtp_session->dtls || rtp_session->dtls->state == DS_READY)) {
ref_point = ice->last_ok;
} else {
ref_point = rtp_session->first_stun;
}
if (!ref_point) ref_point = now;
rtp_session->elapsed_stun = (unsigned int) ((now - ref_point) / 1000);
if (rtp_session->last_media) {
rtp_session->elapsed_media = (unsigned int) ((now - rtp_session->last_media) / 1000);
} else {
rtp_session->elapsed_media = MEDIA_TOO_LONG + 1;
}
if (rtp_session->last_adj) {
rtp_session->elapsed_adj = (unsigned int) ((now - rtp_session->last_adj) / 1000);
} else {
rtp_session->elapsed_adj = ADJ_TOO_LONG + 1;
}
}
static switch_status_t ice_out(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, switch_bool_t force)
{ {
uint8_t buf[256] = { 0 }; uint8_t buf[256] = { 0 };
switch_stun_packet_t *packet; switch_stun_packet_t *packet;
@ -812,7 +870,7 @@ static switch_status_t ice_out(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice)
return SWITCH_STATUS_BREAK; return SWITCH_STATUS_BREAK;
} }
if (ice->next_run && ice->next_run > now) { if (!force && ice->next_run && ice->next_run >= now) {
return SWITCH_STATUS_BREAK; return SWITCH_STATUS_BREAK;
} }
@ -907,8 +965,19 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
int ok = 1; int ok = 1;
uint32_t *pri = NULL; uint32_t *pri = NULL;
int is_rtcp = ice == &rtp_session->rtcp_ice; int is_rtcp = ice == &rtp_session->rtcp_ice;
uint32_t elapsed; switch_channel_t *channel;
switch_time_t ref_point; int i;
switch_sockaddr_t *from_addr = rtp_session->from_addr;
const char *from_host = NULL;
switch_port_t from_port = 0;
char faddr_buf[80] = "";
if (is_rtcp) {
from_addr = rtp_session->rtcp_from_addr;
}
from_host = switch_get_addr(faddr_buf, sizeof(faddr_buf), from_addr);
from_port = switch_sockaddr_get_port(from_addr);
//if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) { //if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
// switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_WARNING, "WTF OK %s CALL\n", rtp_type(rtp_session)); // switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_WARNING, "WTF OK %s CALL\n", rtp_type(rtp_session));
@ -931,6 +1000,7 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
cpylen = sizeof(buf); cpylen = sizeof(buf);
} }
channel = switch_core_session_get_channel(rtp_session->session);
memcpy(buf, data, cpylen); memcpy(buf, data, cpylen);
packet = switch_stun_packet_parse(buf, (uint32_t)cpylen); packet = switch_stun_packet_parse(buf, (uint32_t)cpylen);
@ -946,14 +1016,7 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
rtp_session->first_stun = rtp_session->last_stun; rtp_session->first_stun = rtp_session->last_stun;
} }
if (ice->last_ok && (!rtp_session->dtls || rtp_session->dtls->state == DS_READY)) { calc_elapsed(rtp_session, ice);
ref_point = ice->last_ok;
} else {
ref_point = rtp_session->first_stun;
}
elapsed = (unsigned int) ((switch_micro_time_now() - ref_point) / 1000);
end_buf = buf + ((sizeof(buf) > packet->header.length) ? packet->header.length : sizeof(buf)); end_buf = buf + ((sizeof(buf) > packet->header.length) ? packet->header.length : sizeof(buf));
@ -968,6 +1031,12 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
case SWITCH_STUN_ATTR_USE_CAND: case SWITCH_STUN_ATTR_USE_CAND:
{ {
ice->rready = 1; ice->rready = 1;
for (i = 0; i < ice->ice_params->cand_idx[ice->proto]; i++) {
if (!strcmp(ice->ice_params->cands[i][ice->proto].con_addr, from_host) && ice->ice_params->cands[i][ice->proto].con_port == from_port) {
ice->ice_params->cands[i][ice->proto].use_candidate = 1;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG6, "Got USE-CANDIDATE on %s:%d\n", ice->ice_params->cands[i][ice->proto].con_addr, ice->ice_params->cands[i][ice->proto].con_port);
}
}
} }
break; break;
case SWITCH_STUN_ATTR_ERROR_CODE: case SWITCH_STUN_ATTR_ERROR_CODE:
@ -1048,18 +1117,33 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
if (packet->header.type == SWITCH_STUN_BINDING_RESPONSE) { if (packet->header.type == SWITCH_STUN_BINDING_RESPONSE) {
ok = 1; ok = 1;
if (!ice->rready) {
if (rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) {
rtp_session->ice.rready = 1;
rtp_session->rtcp_ice.rready = 1;
} else {
ice->rready = 1;
}
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) { if (rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) {
switch_core_session_video_reinit(rtp_session->session); rtp_session->ice.rready = 1;
rtp_session->rtcp_ice.rready = 1;
} else {
ice->rready = 1;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG6, "Received STUN Binding Response from %s\n", from_host);
if (ice->ice_params) {
for (i = 0; i < ice->ice_params->cand_idx[ice->proto]; i++) {
if (!strcmp(ice->ice_params->cands[i][ice->proto].con_addr, from_host) && ice->ice_params->cands[i][ice->proto].con_port == from_port) {
ice->ice_params->cands[i][ice->proto].responsive = 1;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG5, "Marked ICE candidate %s:%d as responsive\n", ice->ice_params->cands[i][ice->proto].con_addr, ice->ice_params->cands[i][ice->proto].con_port);
if (!strcmp(ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_addr, from_host) && ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_port == from_port) {
ice->cand_responsive = 1;
ice->initializing = 0;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG5, "Chosen ICE candidate %s:%d is responsive\n", ice->ice_params->cands[i][ice->proto].con_addr, ice->ice_params->cands[i][ice->proto].con_port);
}
}
} }
} }
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
switch_core_session_video_reinit(rtp_session->session);
}
} }
if (!ok && ice == &rtp_session->ice && rtp_session->rtcp_ice.ice_params && pri && if (!ok && ice == &rtp_session->ice && rtp_session->rtcp_ice.ice_params && pri &&
@ -1084,7 +1168,7 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
switch_port_t port = 0; switch_port_t port = 0;
char *host = NULL; char *host = NULL;
if (elapsed > 20000 && pri) { if (rtp_session->elapsed_stun > STUN_TOO_LONG && pri) {
int i, j; int i, j;
uint32_t old; uint32_t old;
//const char *tx_host; //const char *tx_host;
@ -1176,6 +1260,7 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_WARNING, "missed too many: %d, looking for new ICE dest.\n", switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_WARNING, "missed too many: %d, looking for new ICE dest.\n",
ice->missed_count); ice->missed_count);
ice->rready = 0; ice->rready = 0;
ice->cand_responsive = 0;
ok = 1; ok = 1;
} }
@ -1185,9 +1270,8 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
//} //}
if (ok) { if (ok) {
const char *host = NULL, *host2 = NULL; const char *host2 = NULL;
switch_port_t port = 0, port2 = 0; switch_port_t port2 = 0;
char buf[80] = "";
char buf2[80] = ""; char buf2[80] = "";
if (packet->header.type == SWITCH_STUN_BINDING_REQUEST) { if (packet->header.type == SWITCH_STUN_BINDING_REQUEST) {
@ -1196,16 +1280,13 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
const char *remote_ip; const char *remote_ip;
switch_size_t bytes; switch_size_t bytes;
char ipbuf[50]; char ipbuf[50];
switch_sockaddr_t *from_addr = rtp_session->from_addr;
switch_socket_t *sock_output = rtp_session->sock_output; switch_socket_t *sock_output = rtp_session->sock_output;
uint8_t do_adj = 0; uint8_t do_adj = 0;
switch_time_t now = switch_micro_time_now(); switch_time_t now = switch_micro_time_now();
int cmp = 0; int cmp = 0;
int cur_idx = -1;//, is_relay = 0; int cur_idx = -1, is_relay = 0, is_responsive = 0, use_candidate = 0;
int i;
if (is_rtcp) { if (is_rtcp) {
from_addr = rtp_session->rtcp_from_addr;
sock_output = rtp_session->rtcp_sock_output; sock_output = rtp_session->rtcp_sock_output;
} }
@ -1231,58 +1312,123 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
bytes = switch_stun_packet_length(rpacket); bytes = switch_stun_packet_length(rpacket);
host = switch_get_addr(buf, sizeof(buf), from_addr);
port = switch_sockaddr_get_port(from_addr);
host2 = switch_get_addr(buf2, sizeof(buf2), ice->addr); host2 = switch_get_addr(buf2, sizeof(buf2), ice->addr);
port2 = switch_sockaddr_get_port(ice->addr); port2 = switch_sockaddr_get_port(ice->addr);
cmp = switch_cmp_addr(from_addr, ice->addr, SWITCH_FALSE); cmp = switch_cmp_addr(from_addr, ice->addr, SWITCH_FALSE);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG2, for (i = 0; i < ice->ice_params->cand_idx[ice->proto]; i++) {
"STUN from %s:%d %s\n", host, port, cmp ? "EXPECTED" : "IGNORED"); if (!strcmp(ice->ice_params->cands[i][ice->proto].con_addr, from_host) && ice->ice_params->cands[i][ice->proto].con_port == from_port) {
if (!strcasecmp(ice->ice_params->cands[i][ice->proto].cand_type, "relay")) {
is_relay = 1;
}
if (ice->init && !cmp && switch_cmp_addr(from_addr, ice->addr, SWITCH_TRUE)) { if (ice->ice_params->cands[i][ice->proto].responsive) {
do_adj++; is_responsive = 1;
rtp_session->ice_adj++; }
rtp_session->wrong_addrs = 0;
ice->init = 0;
}
if (cmp) {
ice->last_ok = now;
rtp_session->wrong_addrs = 0;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG10, "ICE %d dt:%d i:%d i2:%d w:%d cmp:%d adj:%d\n", elapsed, (rtp_session->dtls && rtp_session->dtls->state != DS_READY), !ice->ready, !ice->rready, rtp_session->wrong_addrs, switch_cmp_addr(from_addr, ice->addr, SWITCH_TRUE), rtp_session->ice_adj);
if ((rtp_session->dtls && rtp_session->dtls->state != DS_READY) || if (ice->ice_params->cands[i][ice->proto].use_candidate) {
((!ice->ready || !ice->rready) && (rtp_session->wrong_addrs > 2 || switch_cmp_addr(from_addr, ice->addr, SWITCH_TRUE)) && use_candidate = 1;
rtp_session->ice_adj < 10)) {
do_adj++;
rtp_session->ice_adj++;
rtp_session->wrong_addrs = 0;
} else if (rtp_session->wrong_addrs > 10 || elapsed >= 5000) {
do_adj++;
}
if (!do_adj) {
rtp_session->wrong_addrs++;
}
for (i = 0; i < ice->ice_params->cand_idx[ice->proto]; i++) {
if (!strcmp(ice->ice_params->cands[i][ice->proto].con_addr, host)) {
cur_idx = i;
//if (!strcasecmp(ice->ice_params->cands[i][ice->proto].cand_type, "relay")) {
// is_relay = 1;
//}
} }
} }
}
if (ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].cand_type && switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG5,
!strcasecmp(ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].cand_type, "relay")) { "%s %s STUN from %s:%d %s is_relay: %d is_responsive: %d use_candidate: %d ready: %d, rready: %d\n", switch_channel_get_name(channel), rtp_type(rtp_session), from_host, from_port, cmp ? "EXPECTED" : "IGNORED",
is_relay, is_responsive, use_candidate, ice->ready, ice->rready);
if (ice->initializing && !cmp) {
if (!rtp_session->adj_window && (!ice->ready || !ice->rready || (!rtp_session->dtls || rtp_session->dtls->state != DS_READY))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG5, "%s %s %s ICE set ADJUST window to 10 seconds on binding request from %s:%d (is_relay: %d, is_responsivie: %d, use_candidate: %d) Current cand: %s:%d typ: %s\n",
switch_channel_get_name(channel), rtp_type(rtp_session), is_rtcp ? "rtcp" : "rtp", from_host, from_port, is_relay, is_responsive, use_candidate,
ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_addr, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_port, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].cand_type);
rtp_session->adj_window = now + 10000000;
}
if (rtp_session->adj_window) {
if (rtp_session->adj_window > now) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG5, "%s %s %s ICE check: %d >= 3000 or window closed and not from relay on binding request from %s:%d (is_relay: %d, is_responsive: %d, use_candidate: %d) Current cand: %s:%d typ: %s\n",
switch_channel_get_name(channel), rtp_type(rtp_session), is_rtcp ? "rtcp" : "rtp", rtp_session->elapsed_stun, from_host, from_port, is_relay, is_responsive, use_candidate,
ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_addr, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_port, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].cand_type);
if (!is_relay && (rtp_session->elapsed_stun >= 3000 || rtp_session->adj_window == (now + 10000000))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG5, "%s %s %s ICE ADJUST HIT 1 on binding request from %s:%d (is_relay: %d, is_responsive: %d, use_candidate: %d) Current cand: %s:%d typ: %s\n",
switch_channel_get_name(channel), rtp_type(rtp_session), is_rtcp ? "rtcp" : "rtp", from_host, from_port, is_relay, is_responsive, use_candidate,
ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_addr, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_port, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].cand_type);
do_adj++;
rtp_session->last_adj = now;
}
} else {
rtp_session->adj_window = 0;
}
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG5, "%s %s %s ICE CHECK SAME IP DIFFT PORT %d %d on binding request from %s:%d (is_relay: %d, is_responsive: %d, use_candidate: %d) Current cand: %s:%d typ: %s\n",
switch_channel_get_name(channel), rtp_type(rtp_session), is_rtcp ? "rtcp" : "rtp",ice->initializing, switch_cmp_addr(from_addr, ice->addr, SWITCH_TRUE), from_host, from_port, is_relay, is_responsive, use_candidate,
ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_addr, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_port, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].cand_type);
if (!do_adj && (switch_cmp_addr(from_addr, ice->addr, SWITCH_TRUE) || use_candidate)) {
do_adj++; do_adj++;
rtp_session->last_adj = now;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG5, "%s %s %s ICE ADJUST HIT 2 on binding request from %s:%d (is_relay: %d, is_responsive: %d, use_candidate: %d) Current cand: %s:%d typ: %s\n",
switch_channel_get_name(channel), rtp_type(rtp_session), is_rtcp ? "rtcp" : "rtp", from_host, from_port, is_relay, is_responsive, use_candidate,
ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_addr, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_port, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].cand_type);
} }
} }
if (cmp) {
ice->last_ok = now;
} else if (!do_adj) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG5, "ICE %d/%d dt:%d i:%d i2:%d cmp:%d\n", rtp_session->elapsed_stun, rtp_session->elapsed_media, (rtp_session->dtls && rtp_session->dtls->state != DS_READY), !ice->ready, !ice->rready, switch_cmp_addr(from_addr, ice->addr, SWITCH_TRUE));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG5, "%s %s %s ICE ADJUST ELAPSED vs 1000 %d on binding request from %s:%d (is_relay: %d, is_responsive: %d, use_candidate: %d) Current cand: %s:%d typ: %s\n",
switch_channel_get_name(channel), rtp_type(rtp_session), is_rtcp ? "rtcp" : "rtp" ,rtp_session->elapsed_adj, from_host, from_port, is_relay, is_responsive, use_candidate,
ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_addr, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_port, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].cand_type);
if (rtp_session->elapsed_adj > 1000) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG5, "%s %s %s ICE IF DTLS NOT READY or %d >= 3000 or media too long %d or stun too long %d on binding request from %s:%d (is_relay: %d, is_responsive: %d, use_candidate: %d) Current cand: %s:%d typ: %s\n",
switch_channel_get_name(channel), rtp_type(rtp_session), is_rtcp ? "rtcp" : "rtp", rtp_session->elapsed_stun, rtp_session->elapsed_media >= MEDIA_TOO_LONG,
rtp_session->elapsed_stun >= STUN_TOO_LONG, from_host, from_port, is_relay, is_responsive, use_candidate,
ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_addr, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_port, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].cand_type);
if (!is_relay && ((rtp_session->dtls && rtp_session->dtls->state != DS_READY) ||
((!ice->ready || !ice->rready) && (rtp_session->elapsed_stun >= 3000 || switch_cmp_addr(from_addr, ice->addr, SWITCH_TRUE))))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG5, "%s %s %s ICE ADJUST HIT 3 on binding request from %s:%d (is_relay: %d, is_responsive: %d, use_candidate: %d) Current cand: %s:%d typ: %s\n",
switch_channel_get_name(channel), rtp_type(rtp_session), is_rtcp ? "rtcp" : "rtp", from_host, from_port, is_relay, is_responsive, use_candidate,
ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_addr, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_port, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].cand_type);
do_adj++;
rtp_session->last_adj = now;
} else if (is_relay && ice->initializing && rtp_session->elapsed_stun >= 1000) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG5, "%s %s %s ICE ADJUST HIT 4 (FLIP TO TURN) on binding request from %s:%d (is_relay: %d, is_responsive: %d, use_candidate: %d) Current cand: %s:%d typ: %s\n",
switch_channel_get_name(channel), rtp_type(rtp_session), is_rtcp ? "rtcp" : "rtp", from_host, from_port, is_relay, is_responsive, use_candidate,
ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_addr, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_port, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].cand_type);
do_adj++;
rtp_session->last_adj = now;
} else if ((ice->initializing && rtp_session->elapsed_stun >= 3000) ||
(rtp_session->elapsed_media >= MEDIA_TOO_LONG || rtp_session->elapsed_stun >= STUN_TOO_LONG)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG5, "%s %s %s ICE ADJUST HIT 5 on binding request from %s:%d (is_relay: %d, is_responsive: %d, use_candidate: %d) Current cand: %s:%d typ: %s\n",
switch_channel_get_name(channel), rtp_type(rtp_session), is_rtcp ? "rtcp" : "rtp", from_host, from_port, is_relay, is_responsive, use_candidate,
ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_addr, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_port, ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].cand_type);
do_adj++;
rtp_session->last_adj = now;
}
for (i = 0; i < ice->ice_params->cand_idx[ice->proto]; i++) {
if (!strcmp(ice->ice_params->cands[i][ice->proto].con_addr, from_host)) {
cur_idx = i;
}
}
}
}
if ((ice->type & ICE_VANILLA) && ice->ice_params && do_adj) { if ((ice->type & ICE_VANILLA) && ice->ice_params && do_adj) {
ice->missed_count = 0; ice->missed_count = 0;
ice->rready = 1; ice->rready = 1;
@ -1294,15 +1440,29 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_NOTICE, switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_NOTICE,
"Auto Changing %s stun/%s/dtls port from %s:%u to %s:%u idx:%d\n", rtp_type(rtp_session), is_rtcp ? "rtcp" : "rtp", "Auto Changing %s stun/%s/dtls port from %s:%u to %s:%u idx:%d\n", rtp_type(rtp_session), is_rtcp ? "rtcp" : "rtp",
host2, port2, host2, port2,
host, port, cur_idx); from_host, from_port, cur_idx);
switch_rtp_change_ice_dest(rtp_session, ice, from_host, from_port);
ice->cand_responsive = is_responsive;
if (ice->cand_responsive) {
ice->initializing = 0;
}
switch_rtp_change_ice_dest(rtp_session, ice, host, port);
ice->last_ok = now; ice->last_ok = now;
rtp_session->wrong_addrs = 0;
} }
//if (cmp) { //if (cmp) {
switch_socket_sendto(sock_output, from_addr, 0, (void *) rpacket, &bytes); switch_socket_sendto(sock_output, from_addr, 0, (void *) rpacket, &bytes);
//} //}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG6, "Send STUN Binding Response to %s:%u\n", from_host, from_port);
if (ice->initializing && !is_responsive) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG5, "Send STUN Binding Request on ICE candidate still unresponsive to %s:%u\n", from_host, from_port);
if (ice_out(rtp_session, ice, SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_WARNING, "Error sending STUN Binding Request on ICE candidate still unresponsive to %s:%u\n", from_host, from_port);
}
}
} }
} else if (packet->header.type == SWITCH_STUN_BINDING_ERROR_RESPONSE) { } else if (packet->header.type == SWITCH_STUN_BINDING_ERROR_RESPONSE) {
@ -2072,9 +2232,9 @@ static int check_rtcp_and_ice(switch_rtp_t *rtp_session)
struct switch_rtcp_report_block *rtcp_report_block = NULL; struct switch_rtcp_report_block *rtcp_report_block = NULL;
switch_size_t rtcp_bytes = sizeof(struct switch_rtcp_hdr_s)+sizeof(uint32_t); /* add size of the packet header and the ssrc */ switch_size_t rtcp_bytes = sizeof(struct switch_rtcp_hdr_s)+sizeof(uint32_t); /* add size of the packet header and the ssrc */
switch_rtcp_hdr_t *sdes; switch_rtcp_hdr_t *sdes;
sdes_ssrc_t *sdes_ssrc;
uint8_t *p; uint8_t *p;
switch_size_t sdes_bytes = sizeof(struct switch_rtcp_hdr_s); switch_size_t sdes_bytes = sizeof(struct switch_rtcp_hdr_s);
uint32_t *ssrc;
switch_rtcp_sdes_unit_t *unit; switch_rtcp_sdes_unit_t *unit;
switch_bool_t is_only_receiver = FALSE; switch_bool_t is_only_receiver = FALSE;
@ -2270,14 +2430,13 @@ static int check_rtcp_and_ice(switch_rtp_t *rtp_session)
//SDES + CNAME //SDES + CNAME
p = (uint8_t *) (&rtp_session->rtcp_send_msg) + rtcp_bytes; p = (uint8_t *) (&rtp_session->rtcp_send_msg) + rtcp_bytes;
sdes = (switch_rtcp_hdr_t *) p; sdes_ssrc = (sdes_ssrc_t *) p;
sdes = &sdes_ssrc->header;
sdes->version = 2; sdes->version = 2;
sdes->type = _RTCP_PT_SDES; sdes->type = _RTCP_PT_SDES;
sdes->count = 1; sdes->count = 1;
sdes->p = 0; sdes->p = 0;
p = (uint8_t *) (sdes) + sdes_bytes; sdes_ssrc->ssrc = htonl(rtp_session->ssrc);
ssrc = (uint32_t *) p;
*ssrc = htonl(rtp_session->ssrc);
sdes_bytes += sizeof(uint32_t); sdes_bytes += sizeof(uint32_t);
@ -2358,7 +2517,7 @@ static int check_rtcp_and_ice(switch_rtp_t *rtp_session)
} }
if (rtp_session->ice.ice_user) { if (rtp_session->ice.ice_user) {
if (ice_out(rtp_session, &rtp_session->ice) == SWITCH_STATUS_GENERR) { if (ice_out(rtp_session, &rtp_session->ice, SWITCH_FALSE) == SWITCH_STATUS_GENERR) {
ret = -1; ret = -1;
goto end; goto end;
} }
@ -2366,7 +2525,7 @@ static int check_rtcp_and_ice(switch_rtp_t *rtp_session)
if (!rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) { if (!rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) {
if (rtp_session->rtcp_ice.ice_user) { if (rtp_session->rtcp_ice.ice_user) {
if (ice_out(rtp_session, &rtp_session->rtcp_ice) == SWITCH_STATUS_GENERR) { if (ice_out(rtp_session, &rtp_session->rtcp_ice, SWITCH_FALSE) == SWITCH_STATUS_GENERR) {
ret = -1; ret = -1;
goto end; goto end;
} }
@ -2852,10 +3011,9 @@ SWITCH_DECLARE(void) switch_rtp_reset(switch_rtp_t *rtp_session)
memset(&rtp_session->ts_norm, 0, sizeof(rtp_session->ts_norm)); memset(&rtp_session->ts_norm, 0, sizeof(rtp_session->ts_norm));
rtp_session->last_stun = rtp_session->first_stun = 0; rtp_session->last_stun = rtp_session->first_stun = 0;
rtp_session->wrong_addrs = 0;
rtp_session->rtcp_sent_packets = 0; rtp_session->rtcp_sent_packets = 0;
rtp_session->rtcp_last_sent = 0; rtp_session->rtcp_last_sent = 0;
rtp_session->ice_adj = 0; rtp_session->last_adj = 0;
//switch_rtp_del_dtls(rtp_session, DTLS_TYPE_RTP|DTLS_TYPE_RTCP); //switch_rtp_del_dtls(rtp_session, DTLS_TYPE_RTP|DTLS_TYPE_RTCP);
switch_rtp_set_flag(rtp_session, SWITCH_RTP_FLAG_PAUSE); switch_rtp_set_flag(rtp_session, SWITCH_RTP_FLAG_PAUSE);
@ -2865,6 +3023,7 @@ SWITCH_DECLARE(void) switch_rtp_reset(switch_rtp_t *rtp_session)
if (rtp_session->ice.ready) { if (rtp_session->ice.ready) {
switch_rtp_reset_vb(rtp_session); switch_rtp_reset_vb(rtp_session);
rtp_session->ice.ready = rtp_session->ice.rready = 0; rtp_session->ice.ready = rtp_session->ice.rready = 0;
rtp_session->ice.cand_responsive = 0;
} }
} }
@ -3210,13 +3369,31 @@ static int do_dtls(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
int r = 0, ret = 0, len; int r = 0, ret = 0, len;
switch_size_t bytes; switch_size_t bytes;
unsigned char buf[MAX_DTLS_MTU] = ""; unsigned char buf[MAX_DTLS_MTU] = "";
int ready = rtp_session->ice.ice_user ? (rtp_session->ice.rready && rtp_session->ice.ready) : 1; uint8_t is_ice = rtp_session->ice.ice_user ? 1 : 0;
int ready = is_ice ? (rtp_session->ice.rready && rtp_session->ice.ready) : 1;
int pending; int pending;
if (!dtls->bytes && !ready) { if (!dtls->bytes && !ready) {
return 0; return 0;
} }
if (is_ice && !(rtp_session->ice.type & ICE_LITE) && !rtp_session->ice.cand_responsive) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG6, "Got DTLS packet but candidate is not responsive\n");
return 0;
}
if (is_ice && !switch_cmp_addr(rtp_session->from_addr, rtp_session->ice.addr, SWITCH_TRUE)) {
char tmp_buf1[80] = "";
char tmp_buf2[80] = "";
const char *host_from = switch_get_addr(tmp_buf1, sizeof(tmp_buf1), rtp_session->from_addr);
const char *host_ice_cur_addr = switch_get_addr(tmp_buf2, sizeof(tmp_buf2), rtp_session->ice.addr);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG5, "Got DTLS packet from [%s] whilst current ICE negotiated address is [%s]. Ignored.\n", host_from, host_ice_cur_addr);
return 0;
}
if (dtls->bytes > 0 && dtls->data) { if (dtls->bytes > 0 && dtls->data) {
ret = BIO_write(dtls->read_bio, dtls->data, (int)dtls->bytes); ret = BIO_write(dtls->read_bio, dtls->data, (int)dtls->bytes);
if (ret <= 0) { if (ret <= 0) {
@ -4058,6 +4235,20 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess
switch_channel_set_variable(channel, "rtp_has_crypto", "AES_CM_256_HMAC_SHA1_32"); switch_channel_set_variable(channel, "rtp_has_crypto", "AES_CM_256_HMAC_SHA1_32");
} }
break; break;
case AES_CM_192_HMAC_SHA1_80:
srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(&policy->rtp);
srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(&policy->rtcp);
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
switch_channel_set_variable(channel, "rtp_has_crypto", "AES_CM_192_HMAC_SHA1_80");
}
break;
case AES_CM_192_HMAC_SHA1_32:
srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(&policy->rtp);
srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(&policy->rtcp);
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
switch_channel_set_variable(channel, "rtp_has_crypto", "AES_CM_192_HMAC_SHA1_32");
}
break;
case AES_CM_128_NULL_AUTH: case AES_CM_128_NULL_AUTH:
srtp_crypto_policy_set_aes_cm_128_null_auth(&policy->rtp); srtp_crypto_policy_set_aes_cm_128_null_auth(&policy->rtp);
srtp_crypto_policy_set_aes_cm_128_null_auth(&policy->rtcp); srtp_crypto_policy_set_aes_cm_128_null_auth(&policy->rtcp);
@ -4067,6 +4258,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess
} }
break; break;
default: default:
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Missing crypto type!\n");
break; break;
} }
@ -4325,7 +4517,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session
switch_sockaddr_create(&rtp_session->rtcp_from_addr, pool); switch_sockaddr_create(&rtp_session->rtcp_from_addr, pool);
} }
rtp_session->seq = (uint16_t) rand(); rtp_session->seq = (uint16_t) switch_rand();
rtp_session->ssrc = (uint32_t) ((intptr_t) rtp_session + (switch_time_t) switch_epoch_time_now(NULL)); rtp_session->ssrc = (uint32_t) ((intptr_t) rtp_session + (switch_time_t) switch_epoch_time_now(NULL));
#ifdef DEBUG_TS_ROLLOVER #ifdef DEBUG_TS_ROLLOVER
rtp_session->last_write_ts = TS_ROLLOVER_START; rtp_session->last_write_ts = TS_ROLLOVER_START;
@ -4764,11 +4956,13 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_ice(switch_rtp_t *rtp_sessio
switch_snprintf(user_ice, sizeof(user_ice), "%s:%s", rlogin, login); switch_snprintf(user_ice, sizeof(user_ice), "%s:%s", rlogin, login);
switch_snprintf(luser_ice, sizeof(luser_ice), "%s%s", rlogin, login); switch_snprintf(luser_ice, sizeof(luser_ice), "%s%s", rlogin, login);
ice->ready = ice->rready = 0; ice->ready = ice->rready = 0;
ice->cand_responsive = 0;
} else { } else {
switch_snprintf(ice_user, sizeof(ice_user), "%s%s", login, rlogin); switch_snprintf(ice_user, sizeof(ice_user), "%s%s", login, rlogin);
switch_snprintf(user_ice, sizeof(user_ice), "%s%s", rlogin, login); switch_snprintf(user_ice, sizeof(user_ice), "%s%s", rlogin, login);
switch_snprintf(luser_ice, sizeof(luser_ice), ""); switch_snprintf(luser_ice, sizeof(luser_ice), "");
ice->ready = ice->rready = 1; ice->ready = ice->rready = 1;
ice->cand_responsive = 0;
} }
ice->ice_user = switch_core_strdup(rtp_session->pool, ice_user); ice->ice_user = switch_core_strdup(rtp_session->pool, ice_user);
@ -4779,7 +4973,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_ice(switch_rtp_t *rtp_sessio
ice->pass = ""; ice->pass = "";
ice->rpass = ""; ice->rpass = "";
ice->next_run = switch_micro_time_now(); ice->next_run = switch_micro_time_now();
ice->init = 1; ice->initializing = 1;
if (password) { if (password) {
ice->pass = switch_core_strdup(rtp_session->pool, password); ice->pass = switch_core_strdup(rtp_session->pool, password);
@ -5725,7 +5919,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
/* version 2 probably rtp */ /* version 2 probably rtp */
rtp_session->has_rtp = (rtp_session->recv_msg.header.version == 2); rtp_session->has_rtp = (rtp_session->recv_msg.header.version == 2);
if (rtp_session->media_timeout) { if (rtp_session->media_timeout || rtp_session->ice.ice_user) {
rtp_session->last_media = switch_micro_time_now(); rtp_session->last_media = switch_micro_time_now();
} }
@ -8073,11 +8267,11 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
if (switch_rtp_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)) { if (switch_rtp_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)) {
int external = (flags && *flags & SFF_EXTERNAL); int external = (flags && *flags & SFF_EXTERNAL);
/* Normalize the timestamps to our own base by generating a made up starting point then adding the measured deltas to that base /* Normalize the timestamps to our own base by generating a made up starting point then adding the measured deltas to that base
so if the timestamps and ssrc of the source change, it will not break the other end's jitter bufffer / decoder etc *cough* CHROME *cough* so if the timestamps and ssrc of the source change, it will not break the other end's jitter buffer / decoder etc *cough* CHROME *cough*
*/ */
if (!rtp_session->ts_norm.ts) { if (!rtp_session->ts_norm.ts) {
rtp_session->ts_norm.ts = (uint32_t) rand() % 1000000 + 1; rtp_session->ts_norm.ts = (uint32_t) switch_rand() % 1000000 + 1;
} }
if (!rtp_session->ts_norm.last_ssrc || send_msg->header.ssrc != rtp_session->ts_norm.last_ssrc || rtp_session->ts_norm.last_external != external) { if (!rtp_session->ts_norm.last_ssrc || send_msg->header.ssrc != rtp_session->ts_norm.last_ssrc || rtp_session->ts_norm.last_external != external) {
@ -8326,9 +8520,9 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
} }
if (!rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND_MKI]) { if (!rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND_MKI]) {
stat = srtp_protect(rtp_session->send_ctx[rtp_session->srtp_idx_rtp], &send_msg->header, &sbytes); stat = srtp_protect(rtp_session->send_ctx[rtp_session->srtp_idx_rtp], send_msg, &sbytes);
} else { } else {
stat = srtp_protect_mki(rtp_session->send_ctx[rtp_session->srtp_idx_rtp], &send_msg->header, &sbytes, 1, SWITCH_CRYPTO_MKI_INDEX); stat = srtp_protect_mki(rtp_session->send_ctx[rtp_session->srtp_idx_rtp], send_msg, &sbytes, 1, SWITCH_CRYPTO_MKI_INDEX);
} }
if (stat) { if (stat) {
@ -8850,9 +9044,9 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_write_raw(switch_rtp_t *rtp_session,
} }
if (!rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND_MKI]) { if (!rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND_MKI]) {
stat = srtp_protect(rtp_session->send_ctx[rtp_session->srtp_idx_rtp], &rtp_session->write_msg.header, &sbytes); stat = srtp_protect(rtp_session->send_ctx[rtp_session->srtp_idx_rtp], &rtp_session->write_msg, &sbytes);
} else { } else {
stat = srtp_protect_mki(rtp_session->send_ctx[rtp_session->srtp_idx_rtp], &rtp_session->write_msg.header, &sbytes, 1, SWITCH_CRYPTO_MKI_INDEX); stat = srtp_protect_mki(rtp_session->send_ctx[rtp_session->srtp_idx_rtp], &rtp_session->write_msg, &sbytes, 1, SWITCH_CRYPTO_MKI_INDEX);
} }
if (stat) { if (stat) {

View File

@ -135,7 +135,7 @@ SWITCH_DECLARE(void) switch_stun_random_string(char *buf, uint16_t len, char *se
max = (int) strlen(set); max = (int) strlen(set);
for (x = 0; x < len; x++) { for (x = 0; x < len; x++) {
int j = (int) (max * 1.0 * rand() / (RAND_MAX + 1.0)); int j = (int) (max * 1.0 * switch_rand() / (SWITCH_RAND_MAX + 1.0));
buf[x] = set[j]; buf[x] = set[j];
} }
} }
@ -401,13 +401,17 @@ SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_get_mapped_address(switch_s
SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_get_xor_mapped_address(switch_stun_packet_attribute_t *attribute, switch_stun_packet_header_t *header, char *ipstr, switch_size_t iplen, uint16_t *port) SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_get_xor_mapped_address(switch_stun_packet_attribute_t *attribute, switch_stun_packet_header_t *header, char *ipstr, switch_size_t iplen, uint16_t *port)
{ {
switch_stun_ip_t *ip; switch_stun_ip_t *ip;
switch_stun_ipv6_t *ipv6;
uint8_t x, *i; uint8_t x, *i;
char *p = ipstr; char *p = ipstr;
ip = (switch_stun_ip_t *) attribute->value; ip = (switch_stun_ip_t *) attribute->value;
if (ip->family == 2) { if (ip->family == 2) {
uint8_t *v6addr = (uint8_t *) &ip->address; uint8_t *v6addr;
ipv6 = (switch_stun_ipv6_t *)attribute->value;
v6addr = (uint8_t *) &ipv6->address;
v6_xor(v6addr, (uint8_t *)header->id); v6_xor(v6addr, (uint8_t *)header->id);
inet_ntop(AF_INET6, v6addr, ipstr, iplen); inet_ntop(AF_INET6, v6addr, ipstr, iplen);
} else { } else {

View File

@ -1384,10 +1384,13 @@ SWITCH_DECLARE(const char *) switch_lookup_timezone(const char *tz_name)
return NULL; return NULL;
} }
switch_mutex_lock(globals.mutex);
if ((value = switch_core_hash_find(TIMEZONES_LIST.hash, tz_name)) == NULL) { if ((value = switch_core_hash_find(TIMEZONES_LIST.hash, tz_name)) == NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Timezone '%s' not found!\n", tz_name); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Timezone '%s' not found!\n", tz_name);
} }
switch_mutex_unlock(globals.mutex);
return value; return value;
} }
@ -1522,7 +1525,7 @@ SWITCH_MODULE_LOAD_FUNCTION(softtimer_load)
#endif #endif
memset(&globals, 0, sizeof(globals)); memset(&globals, 0, sizeof(globals));
switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, module_pool); switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);
if ((switch_event_bind_removable(modname, SWITCH_EVENT_RELOADXML, NULL, event_handler, NULL, &NODE) != SWITCH_STATUS_SUCCESS)) { if ((switch_event_bind_removable(modname, SWITCH_EVENT_RELOADXML, NULL, event_handler, NULL, &NODE) != SWITCH_STATUS_SUCCESS)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
@ -1599,18 +1602,21 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(softtimer_shutdown)
DeleteCriticalSection(&timer_section); DeleteCriticalSection(&timer_section);
#endif #endif
if (NODE) {
switch_event_unbind(&NODE);
}
switch_mutex_lock(globals.mutex);
if (TIMEZONES_LIST.hash) { if (TIMEZONES_LIST.hash) {
switch_core_hash_destroy(&TIMEZONES_LIST.hash); switch_core_hash_destroy(&TIMEZONES_LIST.hash);
} }
switch_mutex_unlock(globals.mutex);
if (TIMEZONES_LIST.pool) { if (TIMEZONES_LIST.pool) {
switch_core_destroy_memory_pool(&TIMEZONES_LIST.pool); switch_core_destroy_memory_pool(&TIMEZONES_LIST.pool);
} }
if (NODE) {
switch_event_unbind(&NODE);
}
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }

View File

@ -1160,7 +1160,7 @@ SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to,
switch_safe_free(dupfile); switch_safe_free(dupfile);
} }
switch_snprintf(filename, 80, "%s%smail.%d%04x", SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, (int)(switch_time_t) switch_epoch_time_now(NULL), rand() & 0xffff); switch_snprintf(filename, 80, "%s%smail.%d%04x", SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, (int)(switch_time_t) switch_epoch_time_now(NULL), switch_rand() & 0xffff);
if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644)) > -1) { if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644)) > -1) {
if (file) { if (file) {
@ -2015,7 +2015,7 @@ SWITCH_DECLARE(switch_status_t) switch_find_local_ip(char *buf, int len, int *ma
} }
doh: doh:
if (tmp_socket > 0) { if (tmp_socket >= 0) {
close(tmp_socket); close(tmp_socket);
} }
#endif #endif
@ -4811,6 +4811,67 @@ done:
return status; return status;
} }
SWITCH_DECLARE(int) switch_rand(void)
{
uint32_t random_number = 0;
#ifdef WIN32
BCRYPT_ALG_HANDLE hAlgorithm = NULL;
NTSTATUS status = BCryptOpenAlgorithmProvider(&hAlgorithm, BCRYPT_RNG_ALGORITHM, NULL, 0);
if (!BCRYPT_SUCCESS(status)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "BCryptOpenAlgorithmProvider failed with status %d\n", status);
return 1;
}
status = BCryptGenRandom(hAlgorithm, (PUCHAR)&random_number, sizeof(random_number), 0);
if (!BCRYPT_SUCCESS(status)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "BCryptGenRandom failed with status %d\n", status);
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
return 1;
}
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
/* Make sure we return from 0 to SWITCH_RAND_MAX */
return (random_number & (SWITCH_RAND_MAX));
#elif defined(__unix__) || defined(__APPLE__)
int random_fd = open("/dev/urandom", O_RDONLY);
ssize_t result;
char error_msg[100];
if (random_fd == -1) {
strncpy(error_msg, strerror(errno), sizeof(error_msg) - 1);
error_msg[sizeof(error_msg) - 1] = '\0';
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open failed: %s\n", error_msg);
return 1;
}
result = read(random_fd, &random_number, sizeof(random_number));
if (result < 0) {
strncpy(error_msg, strerror(errno), sizeof(error_msg) - 1);
error_msg[sizeof(error_msg) - 1] = '\0';
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "read failed: %s\n", error_msg);
close(random_fd);
return 1;
}
close(random_fd);
/* Make sure we return from 0 to SWITCH_RAND_MAX */
return (random_number & (SWITCH_RAND_MAX));
#else
return rand();
#endif
}
/* For Emacs: /* For Emacs:
* Local Variables: * Local Variables:
* mode:c * mode:c

View File

@ -206,7 +206,9 @@ SWITCH_DECLARE(switch_vad_state_t) switch_vad_process(switch_vad_t *vad, int16_t
j += vad->channels; j += vad->channels;
} }
score = (uint32_t) (energy / (samples / vad->divisor)); if (samples && vad->divisor && samples >= vad->divisor) {
score = (uint32_t)(energy / (samples / vad->divisor));
}
#ifdef SWITCH_HAVE_FVAD #ifdef SWITCH_HAVE_FVAD
} }
#endif #endif

76
support-d/gdb/README.md Normal file
View File

@ -0,0 +1,76 @@
`gdb` scripts
-----------
Originally from: https://github.com/facebook/folly/tree/593b6e76881042031b7f21d898c8e0874ea79fe0/folly/experimental/gdb
This directory contains a collection of `gdb` scripts that we have found helpful.
These scripts use the [gdb extension Python API](https://sourceware.org/gdb/current/onlinedocs/gdb/Python.html#Python).
### How to run the scripts
To run the scripts, fire up `gdb` and load a script with `source -v`. Example:
```lang=bash
$ gdb -p 123456
(gdb) source -v ./folly/experimental/gdb/deadlock.py
Type "deadlock" to detect deadlocks.
# At this point, any new commands defined in `deadlock.py` are available.
(gdb) deadlock
Found deadlock!
...
```
### What does each script do?
#### `deadlock.py` - Detect deadlocks
Consider the following program that always deadlocks:
```lang=cpp
void deadlock3() {
std::mutex m1, m2, m3;
folly::Baton<> b1, b2, b3;
auto t1 = std::thread([&m1, &m2, &b1, &b2] {
std::lock_guard<std::mutex> g1(m1);
b1.post();
b2.wait();
std::lock_guard<std::mutex> g2(m2);
});
auto t2 = std::thread([&m3, &m2, &b3, &b2] {
std::lock_guard<std::mutex> g2(m2);
b2.post();
b3.wait();
std::lock_guard<std::mutex> g3(m3);
});
auto t3 = std::thread([&m3, &m1, &b3, &b1] {
std::lock_guard<std::mutex> g3(m3);
b3.post();
b1.wait();
std::lock_guard<std::mutex> g1(m1);
});
t1.join();
t2.join();
t3.join();
}
```
The `deadlock.py` script introduces a new `deadlock` command that can help
us identify the threads and mutexes involved with the deadlock.
```lang=bash
$ gdb -p 2174496
(gdb) source -v ./folly/experimental/gdb/deadlock.py
Type "deadlock" to detect deadlocks.
(gdb) deadlock
Found deadlock!
Thread 2 (LWP 2174497) is waiting on mutex (0x00007ffcff42a4c0) held by Thread 3 (LWP 2174498)
Thread 3 (LWP 2174498) is waiting on mutex (0x00007ffcff42a4f0) held by Thread 4 (LWP 2174499)
Thread 4 (LWP 2174499) is waiting on mutex (0x00007ffcff42a490) held by Thread 2 (LWP 2174497)
```
NOTE: This script only works on Linux and requires debug symbols to be installed
for the `pthread` library.

474
support-d/gdb/deadlock.py Normal file
View File

@ -0,0 +1,474 @@
#!/usr/bin/env python3
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# 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.
import re
from collections import defaultdict
from enum import Enum
import gdb
class DiGraph:
"""
Adapted from networkx: http://networkx.github.io/
Represents a directed graph. Edges can store (key, value) attributes.
"""
def __init__(self):
# Map of node -> set of nodes
self.adjacency_map = {}
# Map of (node1, node2) -> map string -> arbitrary attribute
# This will not be copied in subgraph()
self.attributes_map = {}
def neighbors(self, node):
return self.adjacency_map.get(node, set())
def edges(self):
edges = []
for node, neighbors in self.adjacency_map.items():
for neighbor in neighbors:
edges.append((node, neighbor))
return edges
def nodes(self):
return self.adjacency_map.keys()
def attributes(self, node1, node2):
return self.attributes_map[(node1, node2)]
def add_edge(self, node1, node2, **kwargs):
if node1 not in self.adjacency_map:
self.adjacency_map[node1] = set()
if node2 not in self.adjacency_map:
self.adjacency_map[node2] = set()
self.adjacency_map[node1].add(node2)
self.attributes_map[(node1, node2)] = kwargs
def remove_node(self, node):
self.adjacency_map.pop(node, None)
for _, neighbors in self.adjacency_map.items():
neighbors.discard(node)
def subgraph(self, nodes):
graph = DiGraph()
for node in nodes:
for neighbor in self.neighbors(node):
if neighbor in nodes:
graph.add_edge(node, neighbor)
return graph
def node_link_data(self):
"""
Returns the graph as a dictionary in a format that can be
serialized.
"""
data = {
"directed": True,
"multigraph": False,
"graph": {},
"links": [],
"nodes": [],
}
# Do one pass to build a map of node -> position in nodes
node_to_number = {}
for node in self.adjacency_map.keys():
node_to_number[node] = len(data["nodes"])
data["nodes"].append({"id": node})
# Do another pass to build the link information
for node, neighbors in self.adjacency_map.items():
for neighbor in neighbors:
link = self.attributes_map[(node, neighbor)].copy()
link["source"] = node_to_number[node]
link["target"] = node_to_number[neighbor]
data["links"].append(link)
return data
def strongly_connected_components(G): # noqa: C901
"""
Adapted from networkx: http://networkx.github.io/
Parameters
----------
G : DiGraph
Returns
-------
comp : generator of sets
A generator of sets of nodes, one for each strongly connected
component of G.
"""
preorder = {}
lowlink = {}
scc_found = {}
scc_queue = []
i = 0 # Preorder counter
for source in G.nodes():
if source not in scc_found:
queue = [source]
while queue:
v = queue[-1]
if v not in preorder:
i = i + 1
preorder[v] = i
done = 1
v_nbrs = G.neighbors(v)
for w in v_nbrs:
if w not in preorder:
queue.append(w)
done = 0
break
if done == 1:
lowlink[v] = preorder[v]
for w in v_nbrs:
if w not in scc_found:
if preorder[w] > preorder[v]:
lowlink[v] = min([lowlink[v], lowlink[w]])
else:
lowlink[v] = min([lowlink[v], preorder[w]])
queue.pop()
if lowlink[v] == preorder[v]:
scc_found[v] = True
scc = {v}
while scc_queue and preorder[scc_queue[-1]] > preorder[v]:
k = scc_queue.pop()
scc_found[k] = True
scc.add(k)
yield scc
else:
scc_queue.append(v)
def simple_cycles(G): # noqa: C901
"""
Adapted from networkx: http://networkx.github.io/
Parameters
----------
G : DiGraph
Returns
-------
cycle_generator: generator
A generator that produces elementary cycles of the graph.
Each cycle is represented by a list of nodes along the cycle.
"""
def _unblock(thisnode, blocked, B):
stack = {thisnode}
while stack:
node = stack.pop()
if node in blocked:
blocked.remove(node)
stack.update(B[node])
B[node].clear()
# Johnson's algorithm requires some ordering of the nodes.
# We assign the arbitrary ordering given by the strongly connected comps
# There is no need to track the ordering as each node removed as processed.
# save the actual graph so we can mutate it here
# We only take the edges because we do not want to
# copy edge and node attributes here.
subG = G.subgraph(G.nodes())
sccs = list(strongly_connected_components(subG))
while sccs:
scc = sccs.pop()
# order of scc determines ordering of nodes
startnode = scc.pop()
# Processing node runs 'circuit' routine from recursive version
path = [startnode]
blocked = set() # vertex: blocked from search?
closed = set() # nodes involved in a cycle
blocked.add(startnode)
B = defaultdict(set) # graph portions that yield no elementary circuit
stack = [(startnode, list(subG.neighbors(startnode)))]
while stack:
thisnode, nbrs = stack[-1]
if nbrs:
nextnode = nbrs.pop()
if nextnode == startnode:
yield path[:]
closed.update(path)
elif nextnode not in blocked:
path.append(nextnode)
stack.append((nextnode, list(subG.neighbors(nextnode))))
closed.discard(nextnode)
blocked.add(nextnode)
continue
# done with nextnode... look for more neighbors
if not nbrs: # no more nbrs
if thisnode in closed:
_unblock(thisnode, blocked, B)
else:
for nbr in subG.neighbors(thisnode):
if thisnode not in B[nbr]:
B[nbr].add(thisnode)
stack.pop()
path.pop()
# done processing this node
subG.remove_node(startnode)
H = subG.subgraph(scc) # make smaller to avoid work in SCC routine
sccs.extend(list(strongly_connected_components(H)))
def find_cycle(graph):
"""
Looks for a cycle in the graph. If found, returns the first cycle.
If nodes a1, a2, ..., an are in a cycle, then this returns:
[(a1,a2), (a2,a3), ... (an-1,an), (an, a1)]
Otherwise returns an empty list.
"""
cycles = list(simple_cycles(graph))
if cycles:
nodes = cycles[0]
nodes.append(nodes[0])
edges = []
prev = nodes[0]
for node in nodes[1:]:
edges.append((prev, node))
prev = node
return edges
else:
return []
def get_stacktrace(thread_id):
"""
Returns the stack trace for the thread id as a list of strings.
"""
gdb.execute("thread %d" % thread_id, from_tty=False, to_string=True)
output = gdb.execute("bt", from_tty=False, to_string=True)
stacktrace_lines = output.strip().split("\n")
return stacktrace_lines
def is_thread_blocked_with_frame(
thread_id, top_line, expected_top_lines, expected_frame
):
"""
Returns True if we found expected_top_line in top_line, and
we found the expected_frame in the thread's stack trace.
"""
if all(expected not in top_line for expected in expected_top_lines):
return False
stacktrace_lines = get_stacktrace(thread_id)
return any(expected_frame in line for line in stacktrace_lines)
class MutexType(Enum):
"""Types of mutexes that we can detect deadlocks."""
PTHREAD_MUTEX_T = "pthread_mutex_t"
PTHREAD_RWLOCK_T = "pthread_rwlock_t"
@staticmethod
def get_mutex_type(thread_id, top_line):
"""
Returns the probable mutex type, based on the first line
of the thread's stack. Returns None if not found.
"""
WAITLIST = [
"__lll_lock_wait",
"futex_abstimed_wait",
"futex_abstimed_wait_cancelable",
"futex_reltimed_wait",
"futex_reltimed_wait_cancelable",
"futex_wait",
"futex_wait_cancelable",
]
if is_thread_blocked_with_frame(thread_id, top_line, WAITLIST, "pthread_mutex"):
return MutexType.PTHREAD_MUTEX_T
if is_thread_blocked_with_frame(
thread_id, top_line, WAITLIST, "pthread_rwlock"
):
return MutexType.PTHREAD_RWLOCK_T
return None
@staticmethod
def get_mutex_owner_and_address_func_for_type(mutex_type):
"""
Returns a function to resolve the mutex owner and address for
the given type. The returned function f has the following
signature:
f: args: (map of thread lwp -> thread id), blocked thread lwp
returns: (lwp of thread owning mutex, mutex address)
or (None, None) if not found.
Returns None if there is no function for this mutex_type.
"""
if mutex_type == MutexType.PTHREAD_MUTEX_T:
return get_pthread_mutex_t_owner_and_address
if mutex_type == MutexType.PTHREAD_RWLOCK_T:
return get_pthread_rwlock_t_owner_and_address
return None
def print_cycle(graph, lwp_to_thread_id, cycle):
"""Prints the threads and mutexes involved in the deadlock."""
for m, n in cycle:
print(
"Thread %d (LWP %d) is waiting on %s (0x%016x) held by "
"Thread %d (LWP %d)"
% (
lwp_to_thread_id[m],
m,
graph.attributes(m, n)["mutex_type"].value,
graph.attributes(m, n)["mutex"],
lwp_to_thread_id[n],
n,
)
)
def get_thread_info():
"""
Returns a pair of:
- map of LWP -> thread ID
- map of blocked threads LWP -> potential mutex type
"""
# LWP -> thread ID
lwp_to_thread_id = {}
# LWP -> potential mutex type it is blocked on
blocked_threads = {}
output = gdb.execute("info threads", from_tty=False, to_string=True)
lines = output.strip().split("\n")[1:]
regex = re.compile(r"[\s\*]*(\d+).*Thread.*\(LWP (\d+)\).*")
for line in lines:
try:
thread_id = int(regex.match(line).group(1))
thread_lwp = int(regex.match(line).group(2))
lwp_to_thread_id[thread_lwp] = thread_id
mutex_type = MutexType.get_mutex_type(thread_id, line)
if mutex_type:
blocked_threads[thread_lwp] = mutex_type
except Exception:
continue
return (lwp_to_thread_id, blocked_threads)
def get_pthread_mutex_t_owner_and_address(lwp_to_thread_id, thread_lwp):
"""
Finds the thread holding the mutex that this thread is blocked on.
Returns a pair of (lwp of thread owning mutex, mutex address),
or (None, None) if not found.
"""
# Go up the stack to the pthread_mutex_lock frame
gdb.execute(
"thread %d" % lwp_to_thread_id[thread_lwp], from_tty=False, to_string=True
)
gdb.execute("frame 1", from_tty=False, to_string=True)
# Get the owner of the mutex by inspecting the internal
# fields of the mutex.
try:
mutex_info = gdb.parse_and_eval("mutex").dereference()
mutex_owner_lwp = int(mutex_info["__data"]["__owner"])
return (mutex_owner_lwp, int(mutex_info.address))
except gdb.error:
return (None, None)
def get_pthread_rwlock_t_owner_and_address(lwp_to_thread_id, thread_lwp):
"""
If the thread is waiting on a write-locked pthread_rwlock_t, this will
return the pair of:
(lwp of thread that is write-owning the mutex, mutex address)
or (None, None) if not found, or if the mutex is read-locked.
"""
# Go up the stack to the pthread_rwlock_{rd|wr}lock frame
gdb.execute(
"thread %d" % lwp_to_thread_id[thread_lwp], from_tty=False, to_string=True
)
gdb.execute("frame 2", from_tty=False, to_string=True)
# Get the owner of the mutex by inspecting the internal
# fields of the mutex.
try:
rwlock_info = gdb.parse_and_eval("rwlock").dereference()
rwlock_data = rwlock_info["__data"]
field_names = ["__cur_writer", "__writer"]
fields = rwlock_data.type.fields()
field = [f for f in fields if f.name in field_names][0]
rwlock_owner_lwp = int(rwlock_data[field])
# We can only track the owner if it is currently write-locked.
# If it is not write-locked or if it is currently read-locked,
# possibly by multiple threads, we cannot find the owner.
if rwlock_owner_lwp != 0:
return (rwlock_owner_lwp, int(rwlock_info.address))
else:
return (None, None)
except gdb.error:
return (None, None)
class Deadlock(gdb.Command):
"""Detects deadlocks"""
def __init__(self):
super(Deadlock, self).__init__("deadlock", gdb.COMMAND_NONE)
def invoke(self, arg, from_tty):
"""Prints the threads and mutexes in a deadlock, if it exists."""
lwp_to_thread_id, blocked_threads = get_thread_info()
# Nodes represent threads. Edge (A,B) exists if thread A
# is waiting on a mutex held by thread B.
graph = DiGraph()
# Go through all the blocked threads and see which threads
# they are blocked on, and build the thread wait graph.
for thread_lwp, mutex_type in blocked_threads.items():
get_owner_and_address_func = (
MutexType.get_mutex_owner_and_address_func_for_type(mutex_type)
)
if not get_owner_and_address_func:
continue
mutex_owner_lwp, mutex_address = get_owner_and_address_func(
lwp_to_thread_id, thread_lwp
)
if mutex_owner_lwp and mutex_address:
graph.add_edge(
thread_lwp,
mutex_owner_lwp,
mutex=mutex_address,
mutex_type=mutex_type,
)
# A deadlock exists if there is a cycle in the graph.
cycle = find_cycle(graph)
if cycle:
print("Found deadlock!")
print_cycle(graph, lwp_to_thread_id, cycle)
else:
print("No deadlock detected. " "Do you have debug symbols installed?")
def load():
# instantiate the Deadlock command
Deadlock()
print('Type "deadlock" to detect deadlocks.')
def info():
return "Detect deadlocks"
if __name__ == "__main__":
load()

View File

@ -53,6 +53,47 @@ FST_CORE_BEGIN("./conf")
} }
FST_TEARDOWN_END() FST_TEARDOWN_END()
FST_TEST_BEGIN(test_switch_rand)
{
int i, c = 0;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "\nLet's generate a few random numbers.\n");
for (i = 0; i < 10; i++) {
uint32_t rnd = switch_rand();
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Random number %d\n", rnd);
if (rnd == 1) {
c++;
}
}
/* We do not expect all random numbers to be 1 all 10 times. That would mean we have an error OR we are lucky to have 10 random ones! */
fst_check(c < 10);
}
FST_TEST_END()
FST_TEST_BEGIN(test_switch_uint31_t_overflow)
{
switch_uint31_t x;
uint32_t overflow;
x.value = 0x7fffffff;
x.value++;
fst_check_int_equals(x.value, 0);
x.value++;
fst_check_int_equals(x.value, 1);
x.value -= 2;
fst_check_int_equals(x.value, 0x7fffffff);
overflow = (uint32_t)0x7fffffff + 1;
x.value = overflow;
fst_check_int_equals(x.value, 0);
}
FST_TEST_END()
FST_TEST_BEGIN(test_switch_parse_cidr_v6) FST_TEST_BEGIN(test_switch_parse_cidr_v6)
{ {
ip_t ip, mask; ip_t ip, mask;

View File

@ -127,6 +127,32 @@ FST_CORE_BEGIN("./conf")
} }
FST_TEST_END() FST_TEST_END()
FST_TEST_BEGIN(test_mod_opus_switch_status_false)
{
signed char outbuf[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 };
uint32_t decoded_len = 0;
uint32_t decoded_rate = 48000;
unsigned int flags = 0;
switch_codec_t orig_codec = { 0 };
switch_status_t status;
switch_codec_settings_t codec_settings = { { 0 } };
status = switch_core_codec_init(&orig_codec,
"OPUS",
"mod_opus",
NULL,
48000,
20,
1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
&codec_settings, fst_pool);
fst_check(status == SWITCH_STATUS_SUCCESS);
status = switch_core_codec_decode(&orig_codec, NULL, "test", 5, 48000, outbuf, &decoded_len, &decoded_rate, &flags);
fst_check_int_equals(status, SWITCH_STATUS_FALSE);
switch_core_codec_destroy(&orig_codec);
}
FST_TEST_END()
} }
FST_SUITE_END() FST_SUITE_END()
} }

View File

@ -187,7 +187,7 @@ FST_TEARDOWN_END()
switch_core_media_prepare_codecs(session, SWITCH_FALSE); switch_core_media_prepare_codecs(session, SWITCH_FALSE);
match = switch_core_media_negotiate_sdp(session, r_sdp, &p, SDP_TYPE_REQUEST); match = switch_core_media_negotiate_sdp(session, r_sdp, &p, SDP_OFFER);
fst_requires(match == 1); fst_requires(match == 1);
status = switch_core_media_choose_ports(session, SWITCH_TRUE, SWITCH_FALSE); status = switch_core_media_choose_ports(session, SWITCH_TRUE, SWITCH_FALSE);

View File

@ -206,7 +206,7 @@ static switch_status_t rtp_test_start_call(switch_core_session_t **psession)
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
match = switch_core_media_negotiate_sdp(session, r_sdp, &p, SDP_TYPE_REQUEST); match = switch_core_media_negotiate_sdp(session, r_sdp, &p, SDP_OFFER);
if (match != 1) { if (match != 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "switch_core_media_negotiate_sdp() failed\n"); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "switch_core_media_negotiate_sdp() failed\n");
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;

View File

@ -0,0 +1,205 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>test_switch_core_codec</ProjectName>
<RootNamespace>test_switch_core_codec</RootNamespace>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
<ProjectGuid>{589A07E7-5DE5-49FD-A62C-27795B806AFB}</ProjectGuid>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(SolutionDir)w32\openssl.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(SolutionDir)w32\winlibs.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(SolutionDir)w32\winlibs.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(SolutionDir)w32\winlibs.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(SolutionDir)w32\winlibs.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(PlatformName)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(PlatformName)\$(Configuration)\$(ProjectName)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(PlatformName)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(PlatformName)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(PlatformName)\$(Configuration)\$(ProjectName)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(SolutionDir)src\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>SWITCH_TEST_BASE_DIR_FOR_CONF="..\\..\\tests\\unit\\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<BuildLog />
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<EnablePREfast>true</EnablePREfast>
<DisableSpecificWarnings>6031;6340;6246;6011;6387;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>true</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<BuildLog />
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<EnablePREfast>true</EnablePREfast>
<DisableSpecificWarnings>6031;6340;6246;6011;6387;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>true</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<BuildLog />
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>6031;6340;6246;6011;6387;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>true</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<BuildLog />
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>6031;6340;6246;6011;6387;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>true</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="switch_core_codec.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)w32\Library\FreeSwitchCore.2017.vcxproj">
<Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -13,7 +13,7 @@
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<OutputName>FreeSWITCH</OutputName> <OutputName>FreeSWITCH</OutputName>
<OutputType>Package</OutputType> <OutputType>Package</OutputType>
<CertificateThumbprint>bf386393c880967b00adbc438aee534de6211774</CertificateThumbprint> <CertificateThumbprint>076ce3c57198fc39443bd87f4aab86dac0aab62d</CertificateThumbprint>
<TimestampUrl>http://timestamp.comodoca.com</TimestampUrl> <TimestampUrl>http://timestamp.comodoca.com</TimestampUrl>
<SignToolPath Condition=" Exists('$(WindowsSDK80Path)bin\x86\signtool.exe') and '$(SignToolPath)'=='' and '$(PROCESSOR_ARCHITECTURE)'=='x86' ">$(WindowsSDK80Path)bin\x86\signtool.exe</SignToolPath> <SignToolPath Condition=" Exists('$(WindowsSDK80Path)bin\x86\signtool.exe') and '$(SignToolPath)'=='' and '$(PROCESSOR_ARCHITECTURE)'=='x86' ">$(WindowsSDK80Path)bin\x86\signtool.exe</SignToolPath>
<SignToolPath Condition=" Exists('$(WindowsSDK80Path)bin\x64\signtool.exe') and '$(SignToolPath)'=='' and '$(PROCESSOR_ARCHITECTURE)'=='AMD64' ">$(WindowsSDK80Path)bin\x64\signtool.exe</SignToolPath> <SignToolPath Condition=" Exists('$(WindowsSDK80Path)bin\x64\signtool.exe') and '$(SignToolPath)'=='' and '$(PROCESSOR_ARCHITECTURE)'=='AMD64' ">$(WindowsSDK80Path)bin\x64\signtool.exe</SignToolPath>
@ -1032,6 +1032,7 @@
SuppressRegistry="true" SuppressRegistry="true"
SuppressCom="true" SuppressCom="true"
SuppressFragments="true" SuppressFragments="true"
RunAsSeparateProcess="true"
PreprocessorVariable="var.FreeSWITCHConfFilesDir"> PreprocessorVariable="var.FreeSWITCHConfFilesDir">
</HeatDirectory> </HeatDirectory>
<HeatDirectory <HeatDirectory
@ -1045,6 +1046,7 @@
SuppressRegistry="true" SuppressRegistry="true"
SuppressCom="true" SuppressCom="true"
SuppressFragments="true" SuppressFragments="true"
RunAsSeparateProcess="true"
PreprocessorVariable="var.FreeSWITCHSoundFilesDir"> PreprocessorVariable="var.FreeSWITCHSoundFilesDir">
</HeatDirectory> </HeatDirectory>
<HeatDirectory <HeatDirectory
@ -1058,6 +1060,7 @@
SuppressRegistry="true" SuppressRegistry="true"
SuppressCom="true" SuppressCom="true"
SuppressFragments="true" SuppressFragments="true"
RunAsSeparateProcess="true"
PreprocessorVariable="var.FreeSWITCHhtdocsFilesDir"> PreprocessorVariable="var.FreeSWITCHhtdocsFilesDir">
</HeatDirectory> </HeatDirectory>
<HeatDirectory <HeatDirectory
@ -1071,6 +1074,7 @@
SuppressRegistry="true" SuppressRegistry="true"
SuppressCom="true" SuppressCom="true"
SuppressFragments="true" SuppressFragments="true"
RunAsSeparateProcess="true"
PreprocessorVariable="var.FreeSWITCHimagesFilesDir"> PreprocessorVariable="var.FreeSWITCHimagesFilesDir">
</HeatDirectory> </HeatDirectory>
<HeatDirectory <HeatDirectory
@ -1084,6 +1088,7 @@
SuppressRegistry="true" SuppressRegistry="true"
SuppressCom="true" SuppressCom="true"
SuppressFragments="true" SuppressFragments="true"
RunAsSeparateProcess="true"
PreprocessorVariable="var.FreeSWITCHfontsFilesDir"> PreprocessorVariable="var.FreeSWITCHfontsFilesDir">
</HeatDirectory> </HeatDirectory>
<HeatDirectory <HeatDirectory
@ -1097,6 +1102,7 @@
SuppressRegistry="true" SuppressRegistry="true"
SuppressCom="true" SuppressCom="true"
SuppressFragments="true" SuppressFragments="true"
RunAsSeparateProcess="true"
PreprocessorVariable="var.FreeSWITCHgrammarFilesDir"> PreprocessorVariable="var.FreeSWITCHgrammarFilesDir">
</HeatDirectory> </HeatDirectory>
<HeatDirectory <HeatDirectory
@ -1111,6 +1117,7 @@
SuppressRegistry="true" SuppressRegistry="true"
SuppressCom="true" SuppressCom="true"
SuppressFragments="true" SuppressFragments="true"
RunAsSeparateProcess="true"
PreprocessorVariable="var.FreeSWITCHBaseDir"> PreprocessorVariable="var.FreeSWITCHBaseDir">
</HeatDirectory> </HeatDirectory>
</Target> </Target>

View File

@ -29,7 +29,7 @@
<Target Name="LDNSDownloadTarget" BeforeTargets="CustomBuild;PreBuildEvent;" DependsOnTargets="7za"> <Target Name="LDNSDownloadTarget" BeforeTargets="CustomBuild;PreBuildEvent;" DependsOnTargets="7za">
<DownloadPackageTask <DownloadPackageTask
package="http://files.freeswitch.org/downloads/libs/ldns-1.6.9-1-win.tar.gz" package="http://files.freeswitch.org/downloads/libs/ldns-1.6.9-2-win.tar.gz"
expectfileordirectory="$(BaseDir)libs\ldns\configure.ac" expectfileordirectory="$(BaseDir)libs\ldns\configure.ac"
outputfolder="" outputfolder=""
outputfilename="" outputfilename=""