Merge branch 'signalwire:master' into ss

This commit is contained in:
uyuy2043 2024-10-12 12:42:31 +08:00 committed by GitHub
commit b4705da799
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
146 changed files with 8611 additions and 21640 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-release ${CODENAME} main
deb-src [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/debian-release ${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-release/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,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-release ${CODENAME} main
deb-src [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/rpi/debian-release ${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-release/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-release ${CODENAME} main
deb-src [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/debian-release ${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-release/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-release ${CODENAME} main
deb-src [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/debian-release ${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-release/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-release ${CODENAME} main
deb-src [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/rpi/debian-release ${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-release/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-release ${CODENAME} main
deb-src [signed-by=${GPG_KEY}] https://${REPO_DOMAIN}/repo/deb/debian-release ${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-release/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/ /

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

@ -0,0 +1,130 @@
name: Build and Distribute
on:
pull_request:
push:
branches:
- master
- v1.10
paths:
- "**"
workflow_dispatch:
concurrency:
group: ${{ github.head_ref || github.ref }}
jobs:
preconfig:
runs-on: ubuntu-latest
outputs:
deb: ${{ steps.deb.outputs.excludes }}
release: ${{ steps.release.outputs.release }}
steps:
- name: Generate Matrix excludes for DEB
id: 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
- name: Get release type based on branch
id: release
run: |
if [[ '${{ github.event_name }}' == 'pull_request' ]]; then
if [[ '${{ github.base_ref }}' == 'master' ]]; then
echo 'release=unstable' | tee -a $GITHUB_OUTPUT
elif [[ '${{ github.base_ref }}' == 'v1.10' ]]; then
echo 'release=release' | tee -a $GITHUB_OUTPUT
fi
elif [[ '${{ github.ref }}' == 'refs/heads/master' ]]; then
echo 'release=unstable' | tee -a $GITHUB_OUTPUT
elif [[ '${{ github.ref }}' == 'refs/heads/v1.10' ]]; then
echo 'release=release' | tee -a $GITHUB_OUTPUT
else
exit 1
fi
deb-public:
name: 'DEB-PUBLIC'
permissions:
id-token: write
contents: read
needs:
- preconfig
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
release:
- ${{ needs.preconfig.outputs.release }}
exclude: ${{ fromJson(needs.preconfig.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 }}/public.${{ matrix.release }}.Dockerfile
MAINTAINER: 'Andrey Volk <andrey@signalwire.com>'
META_FILE_PATH_PREFIX: /var/www/freeswitch/public/${{ matrix.release }}/${{ 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 }}-public-${{ matrix.release }}-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-public
permissions:
id-token: write
contents: read
uses: signalwire/actions-template/.github/workflows/meta-repo-content.yml@main
with:
META_CONTENT: '/var/www/freeswitch/public/{release,unstable}/${{ 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 }}

94
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,94 @@
name: CI
on:
push:
branches:
- master
pull_request:
types:
- opened
- synchronize
jobs:
unit-tests_1:
name: "unit-tests (group 1)"
uses: ./.github/workflows/unit-test.yml
with:
total-groups: 2
current-group: 1
secrets: inherit
unit-tests_2:
name: "unit-tests (group 2)"
uses: ./.github/workflows/unit-test.yml
with:
total-groups: 2
current-group: 2
secrets: inherit
scan-build:
runs-on: ubuntu-latest
container:
image: signalwire/freeswitch-public-base:bookworm
credentials:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
options: --privileged
env:
REPOTOKEN: ${{ secrets.REPOTOKEN }}
DEBIAN_FRONTEND: noninteractive
steps:
- name: Install dependencies
shell: bash
run: |
echo "machine freeswitch.signalwire.com password $REPOTOKEN" > /etc/apt/auth.conf && \
apt-get update && \
apt-get -y remove \
libsofia-sip-ua0 \
libspandsp-dev && \
apt-get -y install \
autoconf \
libsofia-sip-ua-dev \
libspandsp3-dev && \
rm -rf /etc/apt/auth.conf
- name: Checkout code
uses: actions/checkout@v4
with:
path: /__w/freeswitch/freeswitch
- name: Bootstrap
shell: bash
working-directory: /__w/freeswitch/freeswitch
run: |
./bootstrap.sh -j || exit 1
- name: Scan-build FreeSwitch
shell: bash
working-directory: /__w/freeswitch/freeswitch
run: |
cp build/modules.conf.most modules.conf && \
echo 'codecs/mod_openh264' >> modules.conf && \
sed -i \
-e '/mod_mariadb/s/^#//g' \
-e '/mod_v8/s/^#//g' \
-e '/mod_ilbc/s/^/#/g' \
-e '/mod_isac/s/^/#/g' \
-e '/mod_mp4/s/^/#/g' \
-e '/mod_mongo/s/^/#/g' \
-e '/mod_pocketsphinx/s/^/#/g' \
-e '/mod_sangoma_codec/s/^/#/g' \
-e '/mod_siren/s/^/#/g' \
-e '/mod_avmd/s/^/#/g' \
-e '/mod_basic/s/^/#/g' \
-e '/mod_cdr_mongodb/s/^/#/g' \
-e '/mod_cv/s/^/#/g' \
-e '/mod_erlang_event/s/^/#/g' \
-e '/mod_perl/s/^/#/g' \
-e '/mod_rtmp/s/^/#/g' \
-e '/mod_unimrcp/s/^/#/g' \
-e '/mod_xml_rpc/s/^/#/g' \
modules.conf && \
./configure && \
./scan_build.sh

111
.github/workflows/unit-test.yml vendored Normal file
View File

@ -0,0 +1,111 @@
name: Unit tests
on:
workflow_call:
inputs:
total-groups:
description: 'Total number of test groups'
required: true
type: number
current-group:
description: 'Current test group number'
required: true
type: number
jobs:
unit-tests:
runs-on: ubuntu-latest
container:
image: signalwire/freeswitch-public-base:bookworm
credentials:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
options: --privileged
env:
DEBIAN_FRONTEND: noninteractive
ASAN_OPTIONS: log_path=stdout:disable_coredump=0:unmap_shadow_on_exit=1:fast_unwind_on_malloc=0
steps:
- name: Override core_pattern
shell: bash
run: |
cat /proc/sys/kernel/core_pattern
echo '/cores/core.%s.%E.%e.%p.%t' > /proc/sys/kernel/core_pattern
cat /proc/sys/kernel/core_pattern
- name: Install dependencies
shell: bash
env:
REPOTOKEN: ${{ secrets.REPOTOKEN }}
run: |
echo "machine freeswitch.signalwire.com password $REPOTOKEN" > /etc/apt/auth.conf && \
apt-get update && \
apt-get -y remove \
libsofia-sip-ua0 \
libspandsp-dev && \
apt-get -y install \
libspandsp3-dev && \
rm -rf /etc/apt/auth.conf
- name: Checkout code
uses: actions/checkout@v4
with:
path: /__w/freeswitch/freeswitch
- name: Bootstrap
shell: bash
working-directory: /__w/freeswitch/freeswitch
run: |
./bootstrap.sh -j || exit 1
- name: Checkout Sofia-Sip
uses: actions/checkout@v4
with:
repository: freeswitch/sofia-sip
path: /__w/freeswitch/freeswitch/sofia-sip
- name: Build sofia-sip
shell: bash
working-directory: /__w/freeswitch/freeswitch/sofia-sip
run: |
./autogen.sh && \
./configure.gnu && \
make -j$(nproc --all) install
- name: Build FreeSwitch
shell: bash
working-directory: /__w/freeswitch/freeswitch
run: |
echo 'codecs/mod_openh264' >> modules.conf && \
sed -i \
-e '/applications\/mod_http_cache/s/^#//g' \
-e '/event_handlers\/mod_rayo/s/^#//g' \
-e '/formats\/mod_opusfile/s/^#//g' \
-e '/languages\/mod_lua/s/^#//g' \
modules.conf && \
./configure \
--enable-address-sanitizer \
--enable-fake-dlclose && \
make -j$(nproc --all) |& tee ./unit-tests-build-result.txt
echo ${PIPESTATUS[0]} > ./build-status.txt
if ! test "$(cat ./build-status.txt | tr -d '[:space:]')" -eq 0; then
exit "$(cat ./build-status.txt | tr -d '[:space:]')"
fi
make install
- name: Run tests
shell: bash
working-directory: /__w/freeswitch/freeswitch/tests/unit
run: |
./run-tests.sh ${{ inputs.total-groups }} ${{ inputs.current-group }}
mkdir logs && (mv log_run-tests_*.html logs || true) && (mv backtrace_*.txt logs || true)
./collect-test-logs.sh
- name: Notify result
if: failure()
uses: signalwire/actions-template/.github/actions/notify-ci-result@main
with:
for: "run_tests"
test_logs_path: /__w/freeswitch/freeswitch/tests/unit
test_artifacts_suffix: "-${{ inputs.current-group }}"

2
.gitignore vendored
View File

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

View File

@ -554,6 +554,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_switch_core_db", "test
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_switch_ivr_originate", "tests\unit\test_switch_ivr_originate.2017.vcxproj", "{69A7464A-9B0D-4804-A108-835229DACF58}"
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
GlobalSection(SolutionConfigurationPlatforms) = preSolution
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|x64.ActiveCfg = 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
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -2714,6 +2728,7 @@ Global
{0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC} = {31C2761D-20E0-4BF8-98B9-E32F0D8DD6E1}
{580675D7-C1C9-4197-AAC5-00F64FAFDE78} = {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
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {09840DE7-9208-45AA-9667-1A71EE93BD1E}

View File

@ -67,8 +67,8 @@ This is the place to get answers faster and chat with other users in real time.
Slack Community:
* https://signalwire.community/
Mailing list:
Mailing list (ARCHIVED):
* http://lists.freeswitch.org/mailman/listinfo/freeswitch-users
* http://lists.freeswitch.org/pipermail/freeswitch-users/
**Thank you for using FreeSWITCH!**

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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>

File diff suppressed because it is too large Load Diff

View File

@ -3,10 +3,10 @@
# Must change all of the below together
# 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_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_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])
])
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])],[
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_format_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_odbc_cdr/Makefile
src/mod/event_handlers/mod_rayo/Makefile

69
debian/bootstrap.sh vendored
View File

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

View File

@ -542,12 +542,6 @@ Module: event_handlers/mod_json_cdr
Description: 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
Description: 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')"
}
create_orig () {
prep_create_orig () {
{
set -e
local OPTIND OPTARG
local uver="" hrev="" bundle_deps=true modules_list="" zl=9e
while getopts 'bm:nv:z:' o "$@"; do
local uver="" hrev="" bundle_deps=true soft_reset=false
while getopts 'bm:nv:V:xz:' o "$@"; do
case "$o" in
m) modules_list="$OPTARG";;
b) ;;
m) ;;
n) uver="nightly";;
v) uver="$OPTARG";;
z) zl="$OPTARG";;
V) uver="$OPTARG";;
x) soft_reset=true;;
z) ;;
esac
done
shift $(($OPTIND-1))
if [ -z "$uver" ] || [ "$uver" = "nightly" ]; then
uver="$(get_nightly_version)"
hrev="$(get_nightly_revision_human)"
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"
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
local -a args=(-e '\bdebian-ignore\b')
test "$modules_list" = "non-dfsg" || args+=(-e '\bdfsg-nonfree\b')
grep .gitattributes.orig "${args[@]}" \
| while xread l; do
echo "$l export-ignore" >> .gitattributes
done
if $bundle_deps; then
(cd libs && getlibs)
git add -f libs
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"
local tmpsrcdir="$(mktemp -d)"
git archive -v \
--worktree-attributes \
--format=tar \
--prefix=freeswitch-$uver/ \
HEAD \
| xz -c -${zl}v > $orig
--prefix=$git_archive_prefix \
HEAD | tar --extract --directory="$tmpsrcdir"
# 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
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
echo $orig
}
@ -190,11 +275,12 @@ applications/mod_commands
EOF
}
create_dsc () {
prep_create_dsc () {
{
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
case "$o" in
a) avoid_mods_arch="$OPTARG";;
@ -202,47 +288,93 @@ create_dsc () {
m) modules_list="$OPTARG";;
p) modules_add="$modules_add $OPTARG";;
s) speed="$OPTARG";;
u) suite_postfix="$OPTARG"; suite_postfix_p=true;;
z) zl="$OPTARG";;
u) ;;
z) ;;
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"
local distro="$(find_distro $1)"
if [ -n "$modules_conf" ]; then
cp $modules_conf debian/modules.conf
fi
local bootstrap_args=""
if [ -n "$modules_list" ]; then
if [ "$modules_list" = "non-dfsg" ]; then
bootstrap_args="-mnon-dfsg"
else set_modules_${modules_list}; fi
else
set_modules_${modules_list}
fi
fi
if test -n "$modules_add"; then
for x in $modules_add; do
bootstrap_args="$bootstrap_args -p${x}"
done
fi
(cd debian && ./bootstrap.sh -a "$avoid_mods_arch" -c $distro $bootstrap_args)
case "$speed" in
paranoid) sed -i ./debian/rules \
-e '/\.stamp-bootstrap:/{:l2 n; /\.\/bootstrap.sh -j/{s/ -j//; :l3 n; b l3}; b l2};' ;;
reckless) sed -i ./debian/rules \
-e '/\.stamp-build:/{:l2 n; /make/{s/$/ -j/; :l3 n; b l3}; b l2};' ;;
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
git add debian/rules
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-genchanges -S > ../$(dsc_base)_source.changes
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
echo $dsc
}
@ -588,7 +720,7 @@ commands:
create-dbg-pkgs
create-dsc <distro> <orig-file>
create-dsc <distro> <orig-file> (same for 'prep-create-dsc')
-f <modules.conf>
Build only modules listed in this file
@ -600,14 +732,17 @@ commands:
Set FS bootstrap/build -j flags
-u <suite-postfix>
Specify a custom suite postfix
-x Use git soft reset instead of hard reset
-z Set compression level
create-orig <treeish>
create-orig <treeish> (same for 'prep_create_orig')
-m [ quicktest | non-dfsg ]
Choose custom list of modules to build
-n Nightly build
-v Set version
-V Set version (without replacing every '-' to '~')
-x Use git soft reset instead of hard reset
-z Set compression level
EOF
@ -629,7 +764,9 @@ case "$cmd" in
build-all) build_all "$@" ;;
build-debs) build_debs "$@" ;;
create-dbg-pkgs) create_dbg_pkgs ;;
prep-create-dsc) prep_create_dsc "$@" ;;
create-dsc) create_dsc "$@" ;;
prep-create-orig) prep_create_orig "$@" ;;
create-orig) create_orig "$@" ;;
*) usage ;;
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

@ -2,7 +2,7 @@
These are the official Docker files for master branch and the current release packages.
## Volumes
These containers are setup so that you can mount your freeswitch configuration form a host or data volume container.
These containers are set up so that you can mount your freeswitch configuration from a host or data volume container.
To mount freeswitch Configuration
```
@ -16,17 +16,19 @@ To mount tmp directory for storing recordings, etc
The container also has a healthcheck where it does a fs_cli status check to make sure the freeswitch service is still running.
# Ports
## Ports
The container exposes the following ports:
The container should be run with host networking using `docker run --network host ...`.
- 5060/tcp 5060/udp 5080/tcp 5080/udp as SIP Signaling ports.
- 5066/tcp 7443/tcp as WebSocket Signaling ports.
- 8021/tcp as Event Socket port.
- 64535-65535/udp as media ports.
- 16384-32768/udp
If you prefer to (or for some reason must) publish individual ports via `--publish/-p`, refer to this [issue](https://github.com/moby/moby/issues/11185) and this [potential workaround](https://hub.docker.com/r/bettervoice/freeswitch-container/) regarding using docker with large port ranges.
The following ports will be used, depending upon your specific configuration:
- 5060/tcp, 5060/udp, 5080/tcp, 5080/udp - SIP signaling
- 5061/tcp, 5081/tcp - SIPS signaling
- 5066/tcp, 7443/tcp - WebSocket signaling
- 8021/tcp - the Event Socket
- 16384-32768/udp, 64535-65535/udp - media
If you wish to help improve these please submit a pull request at:

View File

@ -1,56 +1,63 @@
# vim:set ft=dockerfile:
ARG DEBIAN_VERSION=buster
ARG DEBIAN_VERSION=bookworm
FROM debian:${DEBIAN_VERSION}
# ARGs are cleared after every FROM
# see: https://docs.docker.com/engine/reference/builder/#understand-how-arg-and-from-interact
ARG DEBIAN_VERSION
ARG TOKEN
# By default, install the full set of FreeSWITCH packages. Specify an alternative with:
# --build-arg="FS_META_PACKAGE=freeswitch-meta-vanilla"
# alternatives include:
# freeswitch-meta-bare
# freeswitch-meta-vanilla
# freeswitch-meta-sorbet
# freeswitch-meta-all-dbg
ARG FS_META_PACKAGE=freeswitch-meta-all
# Source Dockerfile:
# https://github.com/docker-library/postgres/blob/master/9.4/Dockerfile
# explicitly set user/group IDs
RUN groupadd -r freeswitch --gid=999 && useradd -r -g freeswitch --uid=999 freeswitch
# grab gosu for easy step-down from root
RUN apt-get update && apt-get install -y --no-install-recommends dirmngr gnupg2 ca-certificates wget \
&& gpg2 --keyserver hkp://keyserver.ubuntu.com --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \
&& gpg2 --keyserver hkp://keyserver.ubuntu.com --recv-keys 655DA1341B5207915210AFE936B4249FA7B0FB03 \
&& gpg2 --output /usr/share/keyrings/signalwire-freeswitch-repo.gpg --export 655DA1341B5207915210AFE936B4249FA7B0FB03 \
&& rm -rf /var/lib/apt/lists/* \
&& wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.2/gosu-$(dpkg --print-architecture)" \
&& wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/1.2/gosu-$(dpkg --print-architecture).asc" \
&& gpg --verify /usr/local/bin/gosu.asc \
&& rm /usr/local/bin/gosu.asc \
&& chmod +x /usr/local/bin/gosu \
&& apt-get purge -y --auto-remove ca-certificates wget dirmngr gnupg2
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
RUN apt-get update && apt-get install -y locales && rm -rf /var/lib/apt/lists/* \
RUN apt-get update -qq \
&& apt-get install -y --no-install-recommends ca-certificates gnupg2 gosu locales wget \
&& localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8
ENV LANG en_US.utf8
# https://freeswitch.org/confluence/display/FREESWITCH/Debian
# https://developer.signalwire.com/freeswitch/FreeSWITCH-Explained/Installation/Linux/Debian_67240088/
RUN apt-get update && apt-get install ca-certificates lsb-release -y --no-install-recommends \
RUN wget --no-verbose --http-user=signalwire --http-password=${TOKEN} \
-O /usr/share/keyrings/signalwire-freeswitch-repo.gpg \
https://freeswitch.signalwire.com/repo/deb/debian-release/signalwire-freeswitch-repo.gpg \
&& echo "machine freeswitch.signalwire.com login signalwire password ${TOKEN}" > /etc/apt/auth.conf \
&& echo "deb [signed-by=/usr/share/keyrings/signalwire-freeswitch-repo.gpg] https://freeswitch.signalwire.com/repo/deb/debian-release/ `lsb_release -sc` main" > /etc/apt/sources.list.d/freeswitch.list \
&& apt-get update && apt-get install -y freeswitch-all \
&& apt-get purge -y --auto-remove ca-certificates lsb-release \
&& echo "deb [signed-by=/usr/share/keyrings/signalwire-freeswitch-repo.gpg] https://freeswitch.signalwire.com/repo/deb/debian-release/ ${DEBIAN_VERSION} main" > /etc/apt/sources.list.d/freeswitch.list \
&& apt-get -qq update \
&& apt-get install -y ${FS_META_PACKAGE} \
&& apt-get purge -y --auto-remove \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
COPY docker-entrypoint.sh /
# Add anything else here
## Ports
# Open the container up to the world.
### 8021 fs_cli, 5060 5061 5080 5081 sip and sips, 64535-65535 rtp
# Document ports used by this container
### 8021 fs_cli, 5060 5061 5080 5081 sip and sips, 5066 ws, 7443 wss, 8081 8082 verto, 16384-32768, 64535-65535 rtp
EXPOSE 8021/tcp
EXPOSE 5060/tcp 5060/udp 5080/tcp 5080/udp
EXPOSE 5061/tcp 5061/udp 5081/tcp 5081/udp
EXPOSE 5066/tcp
EXPOSE 7443/tcp
EXPOSE 5070/udp 5070/tcp
EXPOSE 8081/tcp 8082/tcp
EXPOSE 64535-65535/udp
EXPOSE 16384-32768/udp
# Volumes
## Freeswitch Configuration
VOLUME ["/etc/freeswitch"]
@ -61,11 +68,9 @@ VOLUME ["/tmp"]
COPY build/freeswitch.limits.conf /etc/security/limits.d/
# Healthcheck to make sure the service is running
SHELL ["/bin/bash"]
SHELL ["/bin/bash", "-c"]
HEALTHCHECK --interval=15s --timeout=5s \
CMD fs_cli -x status | grep -q ^UP || exit 1
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["freeswitch"]

View File

@ -140,7 +140,7 @@ BuildRequires: curl-devel >= 7.19
BuildRequires: gcc-c++
BuildRequires: libtool >= 1.5.17
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: pcre-devel
BuildRequires: speex-devel
@ -952,16 +952,6 @@ Requires: %{name} = %{version}-%{release}
%description event-format-cdr
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
Summary: Multicast Event System for the FreeSWITCH open source telephony platform
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/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"
%if %{build_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/ivr.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/local_stream.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/logfile.conf.xml
@ -2286,9 +2275,6 @@ fi
%files event-json-cdr
%{MODINSTDIR}/mod_json_cdr.so*
%files kazoo
%{MODINSTDIR}/mod_kazoo.so*
%files event-radius-cdr
%{MODINSTDIR}/mod_radius_cdr.so*

View File

@ -1447,6 +1447,11 @@ void vp8_change_config(VP8_COMP *cpi, VP8_CONFIG *oxcf) {
last_h = cpi->oxcf.Height;
prev_number_of_layers = cpi->oxcf.number_of_layers;
if (cpi->initial_width) {
// TODO(https://crbug.com/1486441): Allow changing thread counts; the
// allocation is done once in vp8_create_compressor().
oxcf->multi_threaded = cpi->oxcf.multi_threaded;
}
cpi->oxcf = *oxcf;
switch (cpi->oxcf.Mode) {

View File

@ -123,12 +123,6 @@ int vp9_alloc_context_buffers(VP9_COMMON *cm, int width, int height) {
if (cm->alloc_mi(cm, new_mi_size)) goto fail;
}
if (cm->seg_map_alloc_size < cm->mi_rows * cm->mi_cols) {
// Create the segmentation map structure and set to 0.
free_seg_map(cm);
if (alloc_seg_map(cm, cm->mi_rows * cm->mi_cols)) goto fail;
}
if (cm->above_context_alloc_cols < cm->mi_cols) {
vpx_free(cm->above_context);
cm->above_context = (ENTROPY_CONTEXT *)vpx_calloc(
@ -143,6 +137,12 @@ int vp9_alloc_context_buffers(VP9_COMMON *cm, int width, int height) {
cm->above_context_alloc_cols = cm->mi_cols;
}
if (cm->seg_map_alloc_size < cm->mi_rows * cm->mi_cols) {
// Create the segmentation map structure and set to 0.
free_seg_map(cm);
if (alloc_seg_map(cm, cm->mi_rows * cm->mi_cols)) goto fail;
}
if (vp9_alloc_loop_filter(cm)) goto fail;
return 0;

View File

@ -1915,6 +1915,17 @@ static void alloc_copy_partition_data(VP9_COMP *cpi) {
}
}
static void free_copy_partition_data(VP9_COMP *cpi) {
vpx_free(cpi->prev_partition);
cpi->prev_partition = NULL;
vpx_free(cpi->prev_segment_id);
cpi->prev_segment_id = NULL;
vpx_free(cpi->prev_variance_low);
cpi->prev_variance_low = NULL;
vpx_free(cpi->copied_frame_cnt);
cpi->copied_frame_cnt = NULL;
}
void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) {
VP9_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc;
@ -1999,6 +2010,8 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) {
new_mi_size = cm->mi_stride * calc_mi_size(cm->mi_rows);
if (cm->mi_alloc_size < new_mi_size) {
vp9_free_context_buffers(cm);
vp9_free_pc_tree(&cpi->td);
vpx_free(cpi->mbmi_ext_base);
alloc_compressor_data(cpi);
realloc_segmentation_maps(cpi);
cpi->initial_width = cpi->initial_height = 0;
@ -2014,8 +2027,18 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) {
update_frame_size(cpi);
if (last_w != cpi->oxcf.width || last_h != cpi->oxcf.height) {
memset(cpi->consec_zero_mv, 0,
cm->mi_rows * cm->mi_cols * sizeof(*cpi->consec_zero_mv));
vpx_free(cpi->consec_zero_mv);
CHECK_MEM_ERROR(
cm, cpi->consec_zero_mv,
vpx_calloc(cm->mi_rows * cm->mi_cols, sizeof(*cpi->consec_zero_mv)));
vpx_free(cpi->skin_map);
CHECK_MEM_ERROR(
cm, cpi->skin_map,
vpx_calloc(cm->mi_rows * cm->mi_cols, sizeof(cpi->skin_map[0])));
free_copy_partition_data(cpi);
alloc_copy_partition_data(cpi);
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
vp9_cyclic_refresh_reset_resize(cpi);
rc->rc_1_frame = 0;

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,
18, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 19,
};
assert(m > 0);
v--;
m--;
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;
assert(dest_scale);
/* These asserts are needed if there are boundary issues... */
/*assert ( dest_scale > 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_
#define VPX_VPX_SCALE_VPX_SCALE_H_
#include <assert.h>
#include "vpx_scale/yv12config.h"
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
calls it, or to nothing if 'inline' is not supported under any name. */
#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
#if _MSC_VER >= 1900

28
scan_build.sh Executable file
View File

@ -0,0 +1,28 @@
#!/bin/bash
mkdir -p scan-build
scan-build-14 --force-analyze-debug-code -o ./scan-build/ make -j`nproc --all` |& tee ./scan-build-result.txt
exitstatus=${PIPESTATUS[0]}
echo "*** Exit status is $exitstatus"
export SubString="scan-build: No bugs found"
export COMPILATION_FAILED="false"
export BUGS_FOUND="false"
if [[ "0" != "$exitstatus" ]] ; then
export COMPILATION_FAILED="true"
echo MESSAGE="compilation failed" >> $GITHUB_OUTPUT
fi
export RESULTFILE="$PWD/scan-build-result.txt"
# cat $RESULTFILE
if ! grep -sq "$SubString" $RESULTFILE; then
export BUGS_FOUND="true"
echo MESSAGE="found bugs" >> $GITHUB_OUTPUT
fi
export REPORT=$PWD/`find scan-build* -mindepth 1 -type d`
echo "COMPILATION_FAILED: $COMPILATION_FAILED"
echo "BUGS_FOUND: $BUGS_FOUND"
echo "COMPILATION_FAILED=$COMPILATION_FAILED" >> $GITHUB_OUTPUT
echo "BUGS_FOUND=$BUGS_FOUND" >> $GITHUB_OUTPUT
echo "REPORT=$REPORT" >> $GITHUB_OUTPUT
if [[ "0" != "$exitstatus" ]] || ! grep -sq "$SubString" $RESULTFILE; then
exit 1
fi
exit 0

View File

@ -0,0 +1,28 @@
#!/usr/bin/perl
use strict;
use warnings;
my $remote_version = `wget --quiet https://data.iana.org/time-zones/tzdb/version --output-document -` =~ s/\n//r;
my $local_version;
if ( open my $in, "<data/version" ) {
$local_version = do { local $/; <$in> };
close $in;
}
my $up_to_date = defined($local_version) && $local_version eq $remote_version;
if ( ! $up_to_date ) {
open my $out, ">data/version";
print $out $remote_version;
close $out;
}
$local_version = $remote_version;
`wget --quiet --timestamping --directory-prefix=data https://data.iana.org/time-zones/tzdb-latest.tar.lz`;
`tar --extract --file=data/tzdb-latest.tar.lz --directory=data`;
`make DESTDIR=../ TZDIR=zones-$local_version --directory=data/tzdb-$local_version posix_only`;
print("Yay. Now you can run\n ./timezone-gen.pl --base=data/zones-$local_version --output=timezones-$local_version.conf.xml")

View File

@ -0,0 +1,4 @@
tzdb-*
zones-*
version
tzdb-latest.tar.lz

View File

@ -0,0 +1,61 @@
#!/usr/bin/perl
sub fixTzstr {
# switch_time.c expects POSIX-style TZ rule, but it won't process quoted TZ
# rules that look like this: <-04>4 or <-04>4<-03>
# See https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03
# Instead it defaults to UTC for these values. Here we process the quoted
# values and convert them into letters. If the zone name has "GMT", we use
# that as the replacement prefix, otherwise a default "STD" is used. Zones
# that have a quoted suffix have their suffix replaced with "DST".
my ($tzstr, $name) = @_;
if ( $tzstr =~ /(<(?<std>[^>]+)>)([^<]+)(?<dst><.+>)?(?<rest>.+)?/ ) {
my ($tzprefix, $tzsuffix, $tzrest, $offset, $offsetprefix) = ("") x 5;
if ( defined($+{std}) ) {
my $std = $+{std};
if ( lc($name) =~ m/gmt/) {
$tzprefix = "GMT";
} else {
$tzprefix = "STD";
}
if ( $std =~ m/\+/ ) {
$offset = sprintf "%d", $std =~ s/\+//r;
$offsetprefix = "-";
} else {
$offset = sprintf "%d", $std =~ s/\-//r;
}
my @chars = split(//, $offset);
if ( @chars > 2 ) {
my $hours = $chars[-3];
if ( defined( $chars[-4] ) ) {
$hours = $chars[-4].$hours;
}
$offset = $hours.":".$chars[-2].$chars[-1];
}
$offset = $offsetprefix.$offset;
}
if ( defined($+{dst}) ) {
$tzsuffix = "DST";
}
if ( defined($+{rest}) ) {
$tzrest = $+{rest};
}
return $tzprefix.$offset.$tzsuffix.$tzrest;
}
return $tzstr;
}
1;

View File

@ -0,0 +1,65 @@
#!/usr/bin/perl
=pod
Tests to verify that the provided modifications to timezone formats produce
the correct results. The first set of tests verify the fixTzstr subroutine
converts the quoted values to something that won't make FreeSWITCH default to
UTC.
The second set of tests confirms that those timezone changes actually produce
the correct timestamps.
Make sure FreeSWITCH already has already loaded the timezones.conf.xml that you
want to test.
To run tests:
TIMEZONES_XML_PATH=path/to/timezones.conf.xml prove tests.pl
=cut
use strict;
use warnings;
use Test::More;
use ESL;
use XML::LibXML::Reader;
require "./fix-tzstr.pl";
use Env qw(TIMEZONES_XML_PATH);
die "The TIMEZONES_XML_PATH environment variable must be set to test timezones." unless ( defined($TIMEZONES_XML_PATH) );
ok( fixTzstr("<-02>2", "doesntmatterhere") eq "STD2" );
ok( fixTzstr("EST5EDT,M3.2.0,M11.1.0", "US/Eastern") eq "EST5EDT,M3.2.0,M11.1.0" );
ok( fixTzstr("<+11>-11", "GMT-11") eq "GMT-11" );
ok( fixTzstr("<-02>2<-01>,M3.5.0/-1,M10.5.0/0", "America/Godthab") eq "STD2DST,M3.5.0/-1,M10.5.0/0" );
my $test_count = 4;
my $tz_fmt = "%Y-%m-%d %H:%M:%S";
my $c = new ESL::ESLconnection("127.0.0.1", "8021", "ClueCon");
$c->api("reloadxml")->getBody();
my $epoch = $c->api("strepoch")->getBody();
run_tests($epoch);
run_tests("1699613236"); # testing DST, add more epochs as needed
sub run_tests {
my $epoch = shift;
my $reader = XML::LibXML::Reader->new(location => $TIMEZONES_XML_PATH);
while ($reader->read) {
my $tag = $reader;
if ( $tag->name eq "zone" && $tag->hasAttributes() ) {
my $zn = $tag->getAttribute("name");
my $cmd = `TZ='$zn' date +'$tz_fmt' --date='\@$epoch'`;
my $sys_time = $cmd =~ s/\n//r;
my $fs_time = $c->api("strftime_tz $zn $epoch|$tz_fmt")->getBody();
ok ( $sys_time eq $fs_time, $zn ) or diag(
" (sys) $sys_time\t(fs) $fs_time"
);
$test_count++;
}
}
}
done_testing($test_count);

View File

@ -1,10 +1,12 @@
#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
use XML::Entities;
use HTML::Entities;
require "./fix-tzstr.pl";
my $base = "/usr/share/zoneinfo";
my $output = "timezones.conf.xml";
@ -18,7 +20,7 @@ my $res = GetOptions(
"base=s" => \$base,
"debug+" => \$debug,
"help" => \$help,
"output" => \$output
"output=s" => \$output
);
if ( !$res || $help ) {
print "$0 [--base=/usr/share/zoneinfo] [--output=timezones.conf.xml] [--debug] [--help]\n";
@ -64,7 +66,9 @@ foreach my $name ( sort( keys(%name_to_file) ) ) {
next;
}
$zones{$name} = pop(@strings);
my $tzstr = fixTzstr( pop(@strings), $name );
$zones{$name} = $tzstr;
}
open( my $out, ">$output" );
@ -83,7 +87,7 @@ foreach my $zone ( sort( keys(%zones) ) ) {
}
$lastprefix = $newprefix;
print $out "\t<zone name=\"$zone\" value=\"$str\" />\n";
print $out " " x 8, "<zone name=\"$zone\" value=\"$str\" />\n";
}
print $out " " x 4, "</timezones>\n";
print $out "</configuration>\n";

View File

@ -1104,34 +1104,32 @@ static unsigned char *print(const cJSON * const item, cJSON_bool format, const i
buffer->length = default_buffer_size;
buffer->format = format;
buffer->hooks = *hooks;
if (buffer->buffer == NULL)
{
if (buffer->buffer == NULL) {
goto fail;
}
/* print the value */
if (!print_value(item, buffer))
{
if (!print_value(item, buffer)) {
goto fail;
}
update_offset(buffer);
/* check if reallocate is available */
if (hooks->reallocate != NULL)
{
if (hooks->reallocate != NULL) {
printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
if (printed == NULL) {
goto fail;
}
buffer->buffer = NULL;
}
else /* otherwise copy the JSON over to a new buffer */
{
} else { /* otherwise copy the JSON over to a new buffer */
printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
if (printed == NULL)
{
if (printed == NULL) {
goto fail;
}
memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
printed[buffer->offset] = '\0'; /* just to be sure */
@ -1142,16 +1140,10 @@ static unsigned char *print(const cJSON * const item, cJSON_bool format, const i
return printed;
fail:
if (buffer->buffer != NULL)
{
if (buffer->buffer != NULL) {
hooks->deallocate(buffer->buffer);
}
if (printed != NULL)
{
hooks->deallocate(printed);
}
return NULL;
}
@ -1942,33 +1934,41 @@ static cJSON_bool add_item_to_object(cJSON * const object, const char * const st
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
{
add_item_to_object(object, string, item, &global_hooks, false);
cJSON_bool res = add_item_to_object(object, string, item, &global_hooks, false);
(void)res;
}
/* Add an item to an object with constant string as key */
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
{
add_item_to_object(object, string, item, &global_hooks, true);
cJSON_bool res = add_item_to_object(object, string, item, &global_hooks, true);
(void)res;
}
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
{
cJSON_bool res;
if (array == NULL)
{
return;
}
add_item_to_array(array, create_reference(item, &global_hooks));
res = add_item_to_array(array, create_reference(item, &global_hooks));
(void)res;
}
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
{
cJSON_bool res;
if ((object == NULL) || (string == NULL))
{
return;
}
add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
res = add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
(void)res;
}
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)

View File

@ -1822,6 +1822,17 @@ SWITCH_DECLARE(void) switch_core_session_unlock_codec_write(_In_ switch_core_ses
SWITCH_DECLARE(void) switch_core_session_lock_codec_read(_In_ switch_core_session_t *session);
SWITCH_DECLARE(void) switch_core_session_unlock_codec_read(_In_ switch_core_session_t *session);
/*!
\brief Lock codec read mutex and codec write mutex using trylock in an infinite loop
\param session session to lock the codec in
*/
SWITCH_DECLARE(void) switch_core_codec_lock_full(switch_core_session_t *session);
/*!
\brief Unlock codec read mutex and codec write mutex
\param session session to unlock the codec in
*/
SWITCH_DECLARE(void) switch_core_codec_unlock_full(switch_core_session_t *session);
SWITCH_DECLARE(switch_status_t) switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp);
SWITCH_DECLARE(switch_status_t) switch_core_session_get_real_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp);

View File

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

View File

@ -141,6 +141,13 @@ typedef struct {
uint32_t address;
} 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
typedef struct {

View File

@ -255,6 +255,10 @@ SWITCH_BEGIN_EXTERN_C
typedef uint8_t switch_byte_t;
typedef struct {
unsigned int value : 31;
} switch_uint31_t;
typedef enum {
SWITCH_PVT_PRIMARY = 0,
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)
/* 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 {
SWITCH_RW_READ,
SWITCH_RW_WRITE
@ -2656,10 +2667,12 @@ struct switch_live_array_s;
typedef struct switch_live_array_s switch_live_array_t;
typedef enum {
SDP_TYPE_REQUEST,
SDP_TYPE_RESPONSE
SDP_OFFER,
SDP_ANSWER
} switch_sdp_type_t;
#define SDP_TYPE_REQUEST SDP_OFFER
#define SDP_TYPE_RESPONSE SDP_ANSWER
typedef enum {
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(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
#endif
/* 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)
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
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
}
}
@ -1581,7 +1581,6 @@ GCC_DIAG_ON(deprecated-declarations)
} else if (ret == AVERROR(EAGAIN)) {
/* 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");
ret = AVERROR_BUG;
goto error;
} else if (ret < 0) {
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)) {
/* 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");
ret = AVERROR_BUG;
goto do_break;
} else if (ret < 0) {
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);
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]);
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) {
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]))) {
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]) {
context->audio_st[1].frame = av_frame_alloc();
switch_assert(context->audio_st[1].frame);
}
if (c[0] && c[1]) {
context->audio_st[0].channels = 1;
context->audio_st[1].channels = 1;
} else {
@ -2016,7 +2015,6 @@ GCC_DIAG_ON(deprecated-declarations)
} else if (dret == AVERROR(EAGAIN)) {
/* 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");
dret = AVERROR_BUG;
goto do_continue;
} else if (dret < 0) {
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;
if (sample_to_skip_n > 0) {
sample_to_skip_n--;
valid_amplitude = 0;
valid_omega = 0;
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(sqa_amp_b);
buffer->samples_streak_amp = s->settings.sample_n_continuous_streak_amp;
sample_to_skip_n = s->settings.sample_n_to_skip;
}
} else {
if (ISINF(amplitude)) {
amplitude = buffer->amplitude_max;
}
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);
if (s->settings.require_continuous_streak_amp == 1) {
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) {
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(sqa_b_fir);
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) {
valid_omega = 0;
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(sqa_b_fir);
buffer->samples_streak = s->settings.sample_n_continuous_streak;
sample_to_skip_n = s->settings.sample_n_to_skip;
}
} else {
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)) {
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)) {
return AVMD_DETECT_AMP;
}
}
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 */
if ((mode == AVMD_DETECT_FREQ) && (avmd_decision_freq(s, buffer, v_fir, AVMD_VARIANCE_RSD_THRESHOLD) == 1)) {
return AVMD_DETECT_FREQ;
}
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_NONE;
}

View File

@ -1316,15 +1316,15 @@ void conference_loop_output(conference_member_t *member)
uint32_t flush_len;
uint32_t low_count, bytes;
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;
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);
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);
//csamples = samples;
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)
{
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_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);
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);
} else {
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 VERSION 4202
typedef struct fsv_video_data_s {
uint32_t size;
uint8_t data[];
} fsv_video_data_t;
struct file_header {
int32_t version;
char video_codec_name[32];
@ -983,15 +988,16 @@ again:
}
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_assert(video_data);
size &= ~VID_BIT;
video_data = malloc(sizeof(fsv_video_data_t) + size);
switch_assert(video_data);
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) {
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;
switch_image_t *dup = NULL;
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_status_t decode_status = SWITCH_STATUS_MORE_DATA;
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;
while (1) {
video_packet = NULL;
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);
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;
}
size = *(uint32_t *)video_packet;
size = video_packet->size;
if (size > sizeof(context->video_packet_buffer)) {
free(video_packet);
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);
video_packet = NULL;
@ -1093,14 +1100,15 @@ static switch_status_t fsv_file_read_video(switch_file_handle_t *handle, switch_
uint32_t size;
switch_rtp_hdr_t *rtp;
switch_mutex_lock(context->mutex);
status = switch_queue_trypop(context->video_queue, &video_packet);
video_packet = NULL;
switch_mutex_lock(context->mutex);
status = switch_queue_trypop(context->video_queue, (void**)&video_packet);
switch_mutex_unlock(context->mutex);
if (status != SWITCH_STATUS_SUCCESS || !video_packet) break;
size = *(uint32_t *)video_packet;
rtp = (switch_rtp_hdr_t *)((uint8_t *)video_packet + sizeof(uint32_t));
size = video_packet->size;
rtp = (switch_rtp_hdr_t *)(video_packet->data);
rtp_frame.packet = rtp;
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;
char *argv[10];
char fmtptmp[128];
char *fmtp_dup = NULL;
encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
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);
}
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++) {
char *data = argv[x];
char *arg;
while (*data && *data == ' ') {
data++;
}
if ((arg = strchr(data, '='))) {
*arg++ = '\0';
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")) {
int y, m_argc;
char *m_argv[SWITCH_AMR_MODES-1];
m_argc = switch_separate_string(arg, ',', m_argv, (sizeof(m_argv) / sizeof(m_argv[0])));
for (y = 0; y < m_argc; y++) {
context->enc_modes |= (1 << atoi(m_argv[y]));
}
}
}
}
free(fmtp_dup);
}
if (context->enc_modes) {
@ -475,13 +486,15 @@ static switch_status_t switch_amr_decode(switch_codec_t *codec,
return SWITCH_STATUS_FALSE;
#else
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];
if (!context) {
if (!context || encoded_data_len > SWITCH_AMR_OUT_MAX_SIZE) {
return SWITCH_STATUS_FALSE;
}
memcpy(buf, encoded_data, encoded_data_len);
if (globals.debug) {
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)
{
int framesz, index, ft;
int framesz, index;
uint8_t shift_tocs[2] = {0x00, 0x00};
uint8_t *shift_buf;
memcpy(shift_tocs, encoded_buf, 2);
/* shift for BE */
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 for BE */
switch_amr_array_lshift(2, shift_buf, encoded_len - 1);
/* get frame size */
index = ((shift_tocs[0] >> 3) & 0x0f);
if (index > 10 && index != 0xe && index != 0xf) {
return SWITCH_FALSE;
}
framesz = switch_amrwb_frame_sizes[index];
tmp[0] = shift_tocs[0]; /* save TOC */
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) {
codec->fmtp_out = switch_core_strdup(codec->memory_pool, codec->fmtp_in);
}
return SWITCH_STATUS_SUCCESS;
#else
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;
char *argv[10];
char fmtptmp[128];
char *fmtp_dup = NULL;
encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
if (!(encoding || decoding) || (!(context = switch_core_alloc(codec->memory_pool, sizeof(struct amrwb_context))))) {
return SWITCH_STATUS_FALSE;
} else {
@ -222,13 +225,19 @@ static switch_status_t switch_amrwb_init(switch_codec_t *codec, switch_codec_fla
}
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++) {
char *data = argv[x];
char *arg;
while (*data && *data == ' ') {
data++;
}
if ((arg = strchr(data, '='))) {
*arg++ = '\0';
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")) {
int y, m_argc;
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])));
for (y = 0; y < m_argc; y++) {
context->enc_modes |= (1 << 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) {
@ -285,6 +298,7 @@ static switch_status_t switch_amrwb_init(switch_codec_t *codec, switch_codec_fla
/* re-create mode-set */
fmtptmp_pos = switch_snprintf(fmtptmp, sizeof(fmtptmp), "mode-set=");
for (i = 0; SWITCH_AMRWB_MODES-1 > i; ++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);
@ -301,12 +315,13 @@ static switch_status_t switch_amrwb_init(switch_codec_t *codec, switch_codec_fla
}
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);
} 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);
}
codec->fmtp_out = switch_core_strdup(codec->memory_pool, fmtptmp);
context->encoder_state = NULL;
@ -401,13 +416,15 @@ static switch_status_t switch_amrwb_decode(switch_codec_t *codec,
return SWITCH_STATUS_FALSE;
#else
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];
if (!context) {
if (!context || encoded_data_len > SWITCH_AMRWB_OUT_MAX_SIZE) {
return SWITCH_STATUS_FALSE;
}
memcpy(buf, encoded_data, encoded_data_len);
if (globals.debug) {
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) {
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");
return SWITCH_STATUS_NOOP;
return SWITCH_STATUS_FALSE;
}
*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];
if ("server" == key || "host" == key) {
_host = value;
_host = std::move(value);
} else if ("uid" == key || "user" == key || "username" == key) {
_user = value;
_user = std::move(value);
} else if ("pwd" == key || "passwd" == key || "password" == key) {
_passwd = value;
_passwd = std::move(value);
} else if ("database" == key || "db" == key) {
_db = value;
_db = std::move(value);
} else if ("port" == key) {
_port = std::stoi(value);
} 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);
/* 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. */
switch_yield(500 + (rand() & 511));
switch_yield(500 + (switch_rand() & 511));
goto again;
}

View File

@ -113,7 +113,7 @@ static int db_is_up(switch_pgsql_handle_t *handle)
char *err_str = NULL;
int max_tries = DEFAULT_PGSQL_RETRIES;
int code = 0;
int recon = 0;
switch_status_t recon = SWITCH_STATUS_FALSE;
switch_byte_t sanity = 255;
if (handle) {
@ -128,6 +128,7 @@ top:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No DB Handle\n");
goto done;
}
if (!handle->con) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No DB Connection\n");
goto done;
@ -141,6 +142,7 @@ top:
switch_yield(1);
continue;
}
break;
}
@ -158,6 +160,7 @@ reset:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "PQstatus returned bad connection -- reconnection failed!\n");
goto error;
}
handle->state = SWITCH_PGSQL_STATE_CONNECTED;
handle->sock = PQsocket(handle->con);
}
@ -193,6 +196,7 @@ error:
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "The connection could not be re-established");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "The connection could not be re-established\n");
}
if (!max_tries) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "Giving up!");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Giving up!\n");

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_choose_port(session, SWITCH_MEDIA_TYPE_AUDIO, 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);
}

View File

@ -38,7 +38,8 @@ test_sipp_based_tests_CFLAGS = $(AM_CFLAGS) $(SOFIA_SIP_CFLAGS) -DSWITCH_TEST_BA
test_sipp_based_tests_LDFLAGS = $(AM_LDFLAGS) -avoid-version -no-undefined $(freeswitch_LDFLAGS) $(switch_builddir)/libfreeswitch.la $(CORE_LIBS) $(APR_LIBS)
test_sipp_based_tests_LDADD = libsofiamod.la $(SOFIA_SIP_LIBS)
TESTS = test/test_sofia_funcs.sh test/test_nuafail test/test_run_sipp.sh
TESTS = test/test_sofia_funcs.sh test/test_nuafail
#TESTS += test/test_run_sipp.sh
if ISMAC
mod_sofia_la_LDFLAGS += -framework CoreFoundation -framework SystemConfiguration

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)) {
sofia_set_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);
const char *val = NULL;
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_channel_get_variable(tech_pvt->channel, "sip_reason"))) {
switch_snprintf(reason, sizeof(reason), "%s", val);
reason = switch_core_session_sprintf(session, "%s", val);
} else {
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_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) {
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 {
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);
tech_pvt->mparams.local_sdp_str = NULL;
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) {
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 {
switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0);
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);
}
@ -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);
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_mutex_lock(tech_pvt->sofia_mutex);
//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;
}
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) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
}
@ -1339,6 +1339,8 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
if (msg->message_id == SWITCH_MESSAGE_INDICATE_SIGNAL_DATA) {
sofia_dispatch_event_t *de = (sofia_dispatch_event_t *) msg->pointer_arg;
switch_core_session_lock_codec_write(session);
switch_mutex_lock(tech_pvt->sofia_mutex);
if (switch_core_session_in_thread(session)) {
de->session = session;
@ -1346,8 +1348,8 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
sofia_process_dispatch_event(&de);
switch_mutex_unlock(tech_pvt->sofia_mutex);
switch_core_session_unlock_codec_write(session);
goto end;
}
@ -1363,6 +1365,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
/* ones that do not need to lock sofia mutex */
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY:
case SWITCH_MESSAGE_RESAMPLE_EVENT:
goto end;
case SWITCH_MESSAGE_INDICATE_KEEPALIVE:
{
if (msg->numeric_arg) {
@ -1523,6 +1528,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
}
/* ones that do need to lock sofia mutex */
switch_core_session_lock_codec_write(session);
switch_mutex_lock(tech_pvt->sofia_mutex);
if (switch_channel_down(channel) || sofia_test_flag(tech_pvt, TFLAG_BYE)) {
@ -1557,7 +1563,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
tech_pvt->proxy_refer_uuid = (char *)msg->string_array_arg[0];
} else if (!switch_channel_var_true(tech_pvt->channel, "sip_refer_continue_after_reply")) {
switch_mutex_unlock(tech_pvt->sofia_mutex);
switch_core_session_unlock_codec_write(session);
sofia_wait_for_reply(tech_pvt, 9999, 10);
switch_core_session_lock_codec_write(session);
switch_mutex_lock(tech_pvt->sofia_mutex);
if ((var = switch_channel_get_variable(tech_pvt->channel, "sip_refer_reply"))) {
@ -1598,7 +1606,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);
port = switch_channel_get_variable(channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE);
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)) {
@ -1783,7 +1791,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) {
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");
status = SWITCH_STATUS_FALSE;
goto end_lock;
@ -1793,7 +1801,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_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
@ -1802,7 +1810,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
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 (send_invite) {
@ -2256,7 +2264,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_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)) {
nua_respond(tech_pvt->nh, SIP_200_OK,
@ -2391,6 +2399,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
/* Unlock the session signal to allow the ack to make it in */
// Maybe we should timeout?
switch_mutex_unlock(tech_pvt->sofia_mutex);
switch_core_session_unlock_codec_write(session);
while (switch_channel_ready(channel) && !sofia_test_flag(tech_pvt, TFLAG_3PCC_HAS_ACK)) {
switch_ivr_parse_all_events(session);
@ -2398,6 +2407,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
}
/* Regain lock on sofia */
switch_core_session_lock_codec_write(session);
switch_mutex_lock(tech_pvt->sofia_mutex);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY, Done waiting for ACK\n");
@ -2584,7 +2594,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
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,
"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");
@ -2599,7 +2609,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
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) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
}
@ -2706,6 +2716,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
//}
switch_mutex_unlock(tech_pvt->sofia_mutex);
switch_core_session_unlock_codec_write(session);
end:

View File

@ -776,7 +776,7 @@ struct sofia_profile {
int watchdog_enabled;
switch_mutex_t *gw_mutex;
uint32_t queued_events;
uint32_t last_cseq;
switch_uint31_t last_cseq;
int tls_only;
int tls_verify_date;
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;
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)) {
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);
}
//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_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 {
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");
nua_respond(nh, SIP_488_NOT_ACCEPTABLE,
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);
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) {
@ -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());
}
} 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");
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;
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) {
@ -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);
} else {
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_prepare_codecs(session, 1);
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);
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);
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));
} 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));
}
@ -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);
match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_RESPONSE);
match = sofia_media_negotiate_sdp(session, r_sdp, SDP_ANSWER);
if (match) {
if (switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0) != SWITCH_STATUS_SUCCESS) {
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) {
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);
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_core_session_rwunlock(other_session);
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)) {
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);
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) {
@ -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)){
nua_respond(tech_pvt->nh, SIP_200_OK,
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);
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;
}
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) {
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 (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)) {
@ -8507,13 +8508,13 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
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 (switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0) != SWITCH_STATUS_SUCCESS) {
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_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 (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 {
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;
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);
@ -10466,7 +10467,7 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia
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)) {
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);

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_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);
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;
switch_mutex_lock(mod_sofia_globals.mutex);
tm = *(localtime(&now));
@ -2125,7 +2125,7 @@ static uint32_t check_presence_epoch(void)
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_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);
@ -2136,17 +2136,17 @@ static uint32_t check_presence_epoch(void)
uint32_t sofia_presence_get_cseq(sofia_profile_t *profile)
{
uint32_t callsequence;
switch_uint31_t callsequence;
int diff = 0;
switch_mutex_lock(profile->ireg_mutex);
callsequence = check_presence_epoch();
if (profile->last_cseq) {
diff = callsequence - profile->last_cseq;
if (profile->last_cseq.value) {
diff = (int)callsequence.value - (int)profile->last_cseq.value;
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);
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_REINVITE);
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_RECOVERING);
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);
@ -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);
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");
return SWITCH_STATUS_FALSE;
}
@ -2653,7 +2653,7 @@ static switch_status_t verto_media(switch_core_session_t *session)
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) {
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, "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_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")) {
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)) {
pass_sdp(tech_pvt);
} 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");
cJSON_AddItemToObject(obj, "message", cJSON_CreateString("CODEC ERROR"));
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_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)) {
switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
if (switch_core_media_negotiate_sdp(tech_pvt->session, tech_pvt->r_sdp, &p, SDP_OFFER)) {
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) {
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_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)) {
//switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
if (switch_core_media_negotiate_sdp(tech_pvt->session, tech_pvt->r_sdp, &p, SDP_ANSWER)) {
//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) {
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->jsock_uuid = switch_core_session_strdup(session, jsock->uuid_str);
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);
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 */
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();
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_mutex_lock(globals.listener_mutex);
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);
qstatus = switch_queue_trypush(l->log_queue, dnode);
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;
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 */

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