1
0
mirror of https://github.com/signalwire/freeswitch.git synced 2025-04-18 17:41:53 +00:00

Merge branch 'master' into smgmaster

This commit is contained in:
Moises Silva 2011-01-19 10:19:31 -05:00
commit 1045117d9c
314 changed files with 6552 additions and 1565 deletions
Makefile.am
build
conf
debian
freeswitch-sounds-en-us-callie.specfreeswitch.spec
libs
scripts
src

@ -251,7 +251,8 @@ libfreeswitch_la_SOURCES = \
libs/miniupnpc/upnperrors.c \
libs/libnatpmp/natpmp.c \
libs/libnatpmp/getgateway.c\
libs/spandsp/src/plc.c
libs/spandsp/src/plc.c \
libs/spandsp/src/bit_operations.c
if ENABLE_CPP
libfreeswitch_la_SOURCES += src/switch_cpp.cpp

@ -35,6 +35,7 @@ applications/mod_valet_parking
#applications/mod_snapshot
#applications/mod_snipe_hunt
#applications/mod_callcenter
#applications/mod_fsk
codecs/mod_g723_1
codecs/mod_amr
#codecs/mod_amrwb

@ -1,3 +1,3 @@
en-us-callie 1.0.13
en-us-callie 1.0.14
ru-RU-elena 1.0.12

@ -21,7 +21,10 @@
digest authenticated.
-->
<list name="domains" default="deny">
<!-- domain= is special it scans the domain from the directory to build the ACL -->
<node type="allow" domain="$${domain}"/>
<!-- use cidr= if you wish to allow ip ranges to this domains acl. -->
<!-- <node type="allow" cidr="192.168.0.0/24"/> -->
</list>
</network-lists>

@ -56,6 +56,7 @@
<load module="mod_fsv"/>
<load module="mod_cluechoo"/>
<load module="mod_valet_parking"/>
<!--<load module="mod_fsk"/>-->
<!--<load module="mod_spy"/>-->
<!-- SNOM Module -->

@ -16,7 +16,7 @@
</cli-keybindings>
<default-ptimes>
<!-- set this to overide the 20ms assumption of various codecs in the sdp with no ptime defined -->
<!-- set this to override the 20ms assumption of various codecs in the sdp with no ptime defined -->
<!--<codec name="G729" ptime="40"/>-->
</default-ptimes>

@ -114,6 +114,8 @@
<!-- 'true' means every time 'first-only' means on the first register -->
<!--<param name="send-message-query-on-register" value="true"/>-->
<!-- 'true' means every time 'first-only' means on the first register -->
<!--<param name="send-presence-on-register" value="first-only"/> -->
<!-- Caller-ID type (choose one, can be overridden by inbound call type and/or sip_cid_type channel variable -->
@ -337,6 +339,9 @@
A completed transaction is kept around for the duration of T4 in order to catch late responses.
The T4 is the maximum duration for the messages to stay in the network and the duration of SIP timer K. -->
<!-- <param name="timer-T4" value="4000" /> -->
<!-- Turn on a jitterbuffer for every call -->
<!-- <param name="auto-jitterbuffer-msec" value="60"/> -->
</settings>
</profile>

@ -9,7 +9,7 @@
# Description: An advanced platform for voice services
### END INIT INFO
# Author: Anthony Minesalle III <anthmct@yahoo.com>
# Author: Anthony Minesalle II <anthm@freeswitch.org>
#
# Do NOT "set -e"

@ -0,0 +1,339 @@
##############################################################################
# Copyright and license
##############################################################################
#
# Spec file for package freeswitch-sounds-en-us-callie (version 1.0.12-8)
#
# Copyright (c) 2009 Patrick Laimbock
# Some fixes and additions (c) 2011 Michal Bielicki
# This file and all modifications and additions to the pristine
# package are under the same license as the package itself.
#
##############################################################################
# Determine distribution
##############################################################################
%define is_rhel5 %(test -f /etc/redhat-release && egrep -q 'release 5' /etc/redhat-release && echo 1 || echo 0)
##############################################################################
# Set variables
##############################################################################
%define version 1.0.14
%define release 1
%define fsname freeswitch
# you could add a version number to be more strict
%define prefix /opt/freeswitch
%define _prefix %{prefix}
##############################################################################
# General
##############################################################################
Summary: FreeSWITCH en-us Callie prompts
Name: freeswitch-sounds-en-us-callie
Version: %{version}
Release: %{release}%{?dist}
License: MPL
Group: Applications/Communications
Packager: Patrick Laimbock <vc-rpms@voipconsulting.nl>
URL: http://www.freeswitch.org
Source0:http://files.freeswitch.org/%{name}-48000-%{version}.tar.gz
BuildArch: noarch
BuildRequires: sox
Requires: freeswitch
Requires: freeswitch-sounds-en-us-callie-48000
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
%description
FreeSWITCH 48kHz en-us Callie prompts plus, during the installation,
it will also install locally generated 8KHz, 16KHz and 32KHz prompts
%package -n freeswitch-sounds-en-us-callie-8000
Summary: FreeSWITCH 8kHz en-us Callie prompts
Group: Applications/Communications
BuildArch: noarch
Requires: %{fsname}
%description -n freeswitch-sounds-en-us-callie-8000
FreeSWITCH 8kHz en-us Callie prompts
%package -n freeswitch-sounds-en-us-callie-16000
Summary: FreeSWITCH 16kHz en-us Callie prompts
Group: Applications/Communications
BuildArch: noarch
Requires: %{fsname}
%description -n freeswitch-sounds-en-us-callie-16000
FreeSWITCH 16kHz en-us Callie prompts
%package -n freeswitch-sounds-en-us-callie-32000
Summary: FreeSWITCH 32kHz en-us Callie prompts
Group: Applications/Communications
BuildArch: noarch
Requires: %{fsname}
%description -n freeswitch-sounds-en-us-callie-32000
FreeSWITCH 32kHz en-us Callie prompts
%package -n freeswitch-sounds-en-us-callie-48000
Summary: FreeSWITCH 48kHz en-us Callie prompts
Group: Applications/Communications
BuildArch: noarch
Requires: %{fsname}
%description -n freeswitch-sounds-en-us-callie-48000
FreeSWITCH 48kHz en-us Callie prompts
%package -n freeswitch-sounds-en-us-callie-all
Summary: FreeSWITCH en-us Callie prompts
Group: Applications/Communications
BuildArch: noarch
Requires: %{fsname}
Requires: freeswitch-sounds-en-us-callie-8000 = %{version}
Requires: freeswitch-sounds-en-us-callie-16000 = %{version}
Requires: freeswitch-sounds-en-us-callie-32000 = %{version}
Requires: freeswitch-sounds-en-us-callie-48000 = %{version}
%description -n freeswitch-sounds-en-us-callie-all
FreeSWITCH Callie prompts package that pulls in the 8KHz, 16KHz,
32KHz and 48KHz RPMs
##############################################################################
# Prep
##############################################################################
%prep
%setup -b0 -q -n en
mkdir -p ./usr/callie
# create buildsounds-callie.sh script in working dir
echo '#!/bin/bash
sounds_location=$1
for rate in 32000 16000 8000
do
for i in ascii base256 conference currency digits directory ivr misc phonetic-ascii time voicemail zrtp
do
mkdir -p $sounds_location/$i/$rate
for f in `find $sounds_location/$i/48000 -name \*.wav`
do
echo "generating" $sounds_location/$i/$rate/`basename $f`
sox $f -r $rate $sounds_location/$i/$rate/`basename $f`
done
done
done' > ./us/callie/buildsounds-callie.sh
%{__chmod} 0750 ./us/callie/buildsounds-callie.sh
##############################################################################
# Build
##############################################################################
%build
# nothing to do here
##############################################################################
# Install
##############################################################################
%install
[ "%{buildroot}" != '/' ] && rm -rf %{buildroot}
# create the sounds directories
%{__install} -d -m 0750 %{buildroot}%{_prefix}/sounds/en/us/callie
pushd us/callie
# first install the 48KHz sounds
%{__cp} -prv ./* %{buildroot}%{_prefix}/sounds/en/us/callie
# now resample the 48KHz ones to 8KHz, 16KHz and 32KHz
./buildsounds-callie.sh %{buildroot}%{_prefix}/sounds/en/us/callie
popd
##############################################################################
# Clean
##############################################################################
%clean
[ "%{buildroot}" != '/' ] && rm -rf %{buildroot}
##############################################################################
# Post
##############################################################################
%post
# generate the 8KHz, 16KHz and 32KHz prompts from the 48KHz ones
cd %{_prefix}/sounds/en/us/callie
./buildsounds-callie.sh %{_prefix}/sounds/en/us/callie
##############################################################################
# Postun
##############################################################################
%postun
# you could check if there are sound files in 8000/ or
# 16000/ or 32000/ and remove them *only* if the files
# do not belong to an rpm
##############################################################################
# Files
##############################################################################
%files
%defattr(-,root,root)
%attr(0750,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/buildsounds-callie.sh
%files -n freeswitch-sounds-en-us-callie-8000
%defattr(-,root,root,-)
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/ascii/8000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/base256/8000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/conference/8000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/currency/8000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/digits/8000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/directory/8000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/ivr/8000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/misc/8000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/phonetic-ascii/8000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/time/8000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/voicemail/8000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/zrtp/8000
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/ascii/8000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/base256/8000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/conference/8000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/currency/8000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/digits/8000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/directory/8000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/ivr/8000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/misc/8000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/phonetic-ascii/8000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/time/8000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/voicemail/8000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/zrtp/8000/*.wav
%files -n freeswitch-sounds-en-us-callie-16000
%defattr(-,root,root,-)
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/ascii/16000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/base256/16000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/conference/16000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/currency/16000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/digits/16000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/directory/16000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/ivr/16000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/misc/16000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/phonetic-ascii/16000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/time/16000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/voicemail/16000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/zrtp/16000
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/ascii/16000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/base256/16000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/conference/16000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/currency/16000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/digits/16000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/directory/16000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/ivr/16000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/misc/16000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/phonetic-ascii/16000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/time/16000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/voicemail/16000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/zrtp/16000/*.wav
%files -n freeswitch-sounds-en-us-callie-32000
%defattr(-,root,root,-)
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/ascii/32000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/base256/32000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/conference/32000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/currency/32000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/digits/32000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/directory/32000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/ivr/32000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/misc/32000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/phonetic-ascii/32000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/time/32000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/voicemail/32000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/zrtp/32000
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/ascii/32000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/base256/32000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/conference/32000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/currency/32000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/digits/32000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/directory/32000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/ivr/32000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/misc/32000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/phonetic-ascii/32000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/time/32000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/voicemail/32000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/zrtp/32000/*.wav
%files -n freeswitch-sounds-en-us-callie-48000
%defattr(-,root,root,-)
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/ascii/48000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/base256/48000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/conference/48000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/currency/48000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/digits/48000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/directory/48000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/ivr/48000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/misc/48000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/phonetic-ascii/48000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/time/48000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/voicemail/48000
%attr(0750,freeswitch,daemon) %dir %{_prefix}/sounds/en/us/callie/zrtp/48000
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/ascii/48000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/base256/48000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/conference/48000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/currency/48000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/digits/48000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/directory/48000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/ivr/48000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/misc/48000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/phonetic-ascii/48000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/time/48000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/voicemail/48000/*.wav
%attr(0640,freeswitch,daemon) %{_prefix}/sounds/en/us/callie/zrtp/48000/*.wav
%files -n freeswitch-sounds-en-us-callie-all
##############################################################################
# Changelog
##############################################################################
%changelog
* Tue Jan 18 2011 Michal Bielicki <michal.bielicki@seventhsignal.de> - 1.0.14-1
- bump up version
- include script into freeswitch core
- include specfile into freeswitch core
- runtime does not require sox, only building
* Thu Dec 17 2009 Patrick Laimbock <vc-rpms@voipconsulting.nl> - 1.0.12-8
- update perms and user/group to sync with the old situation
* Wed Dec 16 2009 Patrick Laimbock <vc-rpms@voipconsulting.nl> - 1.0.12-7
- make main package require freeswitch-sounds-en-us-callie-48000 and
- generate the 8KHz, 16KHz and 32KHz sounds from there
- add license to spec file
* Wed Dec 16 2009 Patrick Laimbock <vc-rpms@voipconsulting.nl> - 1.0.12-5
- put 48KHz in a separate package and let the main package Require 48KHz
- and then use the script to generate the 8KHz, 16KHz and 32KHz sounds
* Wed Dec 16 2009 Patrick Laimbock <vc-rpms@voipconsulting.nl> - 1.0.12-4
- add freeswitch-sounds-en-us-callie-all package that pulls in the 8KHz,
- 16KHz, 32KHz and 48KHz RPM packages
* Tue Dec 15 2009 Patrick Laimbock <vc-rpms@voipconsulting.nl> - 1.0.12-3
- override subpackage name with -n so it no longer builds an empty main RPM
- rework spec file
- add sox as a requirement
- run buildsounds-callie.sh in post to generate 8KHz, 16KHz and 32KHz prompts
* Tue Dec 15 2009 Patrick Laimbock <vc-rpms@voipconsulting.nl> - 1.0.12-2
- can't override Name in subpackage so put all versions in RPM subpackages
- with an empty main RPM package
* Tue Dec 15 2009 Patrick Laimbock <vc-rpms@voipconsulting.nl> - 1.0.12-1
- create spec file with the following requirement:
- source only contains the 48KHz sound prompts
- during build the 48KHz sound prompts are resampled to 8KHz, 16KHz and 32KHz
- the 8KHz, 16KHz, 32KHz and 48KHz sound prompts are packaged separately

@ -53,7 +53,7 @@ Vendor: http://www.freeswitch.org/
# Source files and where to get them
#
######################################################################################################################
Source0: http://files.freeswitch.org/%{name}-%{version}.tar.bz2
Source0: http://files.freeswitch.org/%{name}-%{version}.tar.bz2
Source1: http://files.freeswitch.org/downloads/libs/celt-0.7.1.tar.gz
Source2: http://files.freeswitch.org/downloads/libs/flite-1.3.99-latest.tar.gz
Source3: http://files.freeswitch.org/downloads/libs/lame-3.97.tar.gz
@ -89,8 +89,13 @@ BuildRequires: libtool >= 1.5.17
BuildRequires: ncurses-devel
BuildRequires: openssl-devel
BuildRequires: perl
%if 0%{?fedora_version} >= 8
BuildRequires: perl-ExtUtils-Embed
%endif
BuildRequires: pkgconfig
%if %{_vendor} == redhat && 0%{?fedora} <= 6
BuildRequires: termcap
%endif
BuildRequires: unixODBC-devel
BuildRequires: gdbm-devel
BuildRequires: db4-devel
@ -613,7 +618,6 @@ fi
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/*.ttml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/*.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/extensions.conf
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/m3ua.conf
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/mime.types
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/acl.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/alsa.conf.xml
@ -894,7 +898,7 @@ fi
%files python
%defattr(-,freeswitch,daemon)
%{prefix}/mod/mod_python*.so*
%attr(0644, root, bin) /usr/lib/python2.4/site-packages/freeswitch.py*
%attr(0644, root, bin) /usr/lib/python*/site-packages/freeswitch.py*
%dir %attr(0750, freeswitch, daemon) %{prefix}/conf/autoload_configs
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/python.conf.xml
@ -952,6 +956,8 @@ fi
#
######################################################################################################################
%changelog
* Tue Jan 18 2011 - michal.bielicki@seventhsignal.de
- Fedora adjustments
* Fri Oct 15 2010 - michal.bielicki@seventhsignal.de
- added mod_curl
* Sat Oct 09 2010 - michal.bielicki@seventhsignal.de

1
libs/.gitignore vendored

@ -1001,6 +1001,7 @@
/unimrcp/build/acmacros/lt~obsolete.m4
/*.tar.gz
/celt-0.7.1/
/celt-0.10.0/
/flite-1.3.99/
/freeradius-client-1.1.6/
/iksemel/test/tst-dom

@ -0,0 +1,195 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>ESL</ProjectName>
<ProjectGuid>{FEA2D0AE-6713-4E41-A473-A143849BC7FF}</ProjectGuid>
<RootNamespace>ESL</RootNamespace>
<Keyword>ManagedCProj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<CLRSupport>true</CLRSupport>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<CLRSupport>true</CLRSupport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<CLRSupport>true</CLRSupport>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<CLRSupport>true</CLRSupport>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\src\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>esl.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\..\libs\esl\src\$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AssemblyDebug>true</AssemblyDebug>
<TargetMachine>NotSet</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\src\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>esl.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\..\libs\esl\src\$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\src\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>esl.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\..\libs\esl\src\$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AssemblyDebug>true</AssemblyDebug>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>..\src\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>esl.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\..\libs\esl\src\$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Reference Include="System">
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
</Reference>
<Reference Include="System.Data">
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
</Reference>
<Reference Include="System.Xml">
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
</Reference>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\esl_oop.cpp" />
<ClCompile Include="esl_wrap.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\include\esl_oop.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\esl_oop.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="esl_wrap.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\include\esl_oop.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{DEE5837B-E01D-4223-B351-EDF9418F3F8E}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ManagedEsl</RootNamespace>
<AssemblyName>ManagedEsl</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation />
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ESL.cs" />
<Compile Include="ESLconnection.cs" />
<Compile Include="ESLevent.cs" />
<Compile Include="ESLPINVOKE.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SWIGTYPE_p_esl_event_t.cs" />
<Compile Include="SWIGTYPE_p_esl_priority_t.cs" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{2321D01A-D64B-4461-9837-FACF38652212}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ManagedEslTest</RootNamespace>
<AssemblyName>ManagedEslTest</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation />
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ManagedEsl.csproj">
<Project>{DEE5837B-E01D-4223-B351-EDF9418F3F8E}</Project>
<Name>ManagedEsl</Name>
<Private>True</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

@ -0,0 +1,74 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ESL", "ESL.2010.vcxproj", "{FEA2D0AE-6713-4E41-A473-A143849BC7FF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ManagedEsl.2010", "ManagedEsl.2010.csproj", "{DEE5837B-E01D-4223-B351-EDF9418F3F8E}"
ProjectSection(ProjectDependencies) = postProject
{FEA2D0AE-6713-4E41-A473-A143849BC7FF} = {FEA2D0AE-6713-4E41-A473-A143849BC7FF}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ManagedEslTest.2010", "ManagedEslTest\ManagedEslTest.2010.csproj", "{2321D01A-D64B-4461-9837-FACF38652212}"
ProjectSection(ProjectDependencies) = postProject
{FEA2D0AE-6713-4E41-A473-A143849BC7FF} = {FEA2D0AE-6713-4E41-A473-A143849BC7FF}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|Mixed Platforms = Debug|Mixed Platforms
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU
Release|Mixed Platforms = Release|Mixed Platforms
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FEA2D0AE-6713-4E41-A473-A143849BC7FF}.Debug|Any CPU.ActiveCfg = Debug|Win32
{FEA2D0AE-6713-4E41-A473-A143849BC7FF}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{FEA2D0AE-6713-4E41-A473-A143849BC7FF}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{FEA2D0AE-6713-4E41-A473-A143849BC7FF}.Debug|Win32.ActiveCfg = Debug|Win32
{FEA2D0AE-6713-4E41-A473-A143849BC7FF}.Debug|Win32.Build.0 = Debug|Win32
{FEA2D0AE-6713-4E41-A473-A143849BC7FF}.Debug|x64.ActiveCfg = Debug|x64
{FEA2D0AE-6713-4E41-A473-A143849BC7FF}.Debug|x64.Build.0 = Debug|x64
{FEA2D0AE-6713-4E41-A473-A143849BC7FF}.Release|Any CPU.ActiveCfg = Release|Win32
{FEA2D0AE-6713-4E41-A473-A143849BC7FF}.Release|Mixed Platforms.ActiveCfg = Release|Win32
{FEA2D0AE-6713-4E41-A473-A143849BC7FF}.Release|Mixed Platforms.Build.0 = Release|Win32
{FEA2D0AE-6713-4E41-A473-A143849BC7FF}.Release|Win32.ActiveCfg = Release|Win32
{FEA2D0AE-6713-4E41-A473-A143849BC7FF}.Release|Win32.Build.0 = Release|Win32
{FEA2D0AE-6713-4E41-A473-A143849BC7FF}.Release|x64.ActiveCfg = Release|x64
{FEA2D0AE-6713-4E41-A473-A143849BC7FF}.Release|x64.Build.0 = Release|x64
{DEE5837B-E01D-4223-B351-EDF9418F3F8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DEE5837B-E01D-4223-B351-EDF9418F3F8E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DEE5837B-E01D-4223-B351-EDF9418F3F8E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{DEE5837B-E01D-4223-B351-EDF9418F3F8E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{DEE5837B-E01D-4223-B351-EDF9418F3F8E}.Debug|Win32.ActiveCfg = Debug|Any CPU
{DEE5837B-E01D-4223-B351-EDF9418F3F8E}.Debug|x64.ActiveCfg = Debug|Any CPU
{DEE5837B-E01D-4223-B351-EDF9418F3F8E}.Debug|x64.Build.0 = Debug|Any CPU
{DEE5837B-E01D-4223-B351-EDF9418F3F8E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DEE5837B-E01D-4223-B351-EDF9418F3F8E}.Release|Any CPU.Build.0 = Release|Any CPU
{DEE5837B-E01D-4223-B351-EDF9418F3F8E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{DEE5837B-E01D-4223-B351-EDF9418F3F8E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{DEE5837B-E01D-4223-B351-EDF9418F3F8E}.Release|Win32.ActiveCfg = Release|Any CPU
{DEE5837B-E01D-4223-B351-EDF9418F3F8E}.Release|x64.ActiveCfg = Release|Any CPU
{DEE5837B-E01D-4223-B351-EDF9418F3F8E}.Release|x64.Build.0 = Release|Any CPU
{2321D01A-D64B-4461-9837-FACF38652212}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2321D01A-D64B-4461-9837-FACF38652212}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2321D01A-D64B-4461-9837-FACF38652212}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{2321D01A-D64B-4461-9837-FACF38652212}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{2321D01A-D64B-4461-9837-FACF38652212}.Debug|Win32.ActiveCfg = Debug|Any CPU
{2321D01A-D64B-4461-9837-FACF38652212}.Debug|x64.ActiveCfg = Debug|Any CPU
{2321D01A-D64B-4461-9837-FACF38652212}.Debug|x64.Build.0 = Debug|Any CPU
{2321D01A-D64B-4461-9837-FACF38652212}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2321D01A-D64B-4461-9837-FACF38652212}.Release|Any CPU.Build.0 = Release|Any CPU
{2321D01A-D64B-4461-9837-FACF38652212}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{2321D01A-D64B-4461-9837-FACF38652212}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{2321D01A-D64B-4461-9837-FACF38652212}.Release|Win32.ActiveCfg = Release|Any CPU
{2321D01A-D64B-4461-9837-FACF38652212}.Release|x64.ActiveCfg = Release|Any CPU
{2321D01A-D64B-4461-9837-FACF38652212}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

@ -1094,9 +1094,9 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
esl_log(ESL_LOG_DEBUG, "RECV INNER HEADER [%s] = [%s]\n", hname, hval);
if (!strcasecmp(hname, "event-name")) {
esl_event_del_header(handle->last_ievent, "event-name");
esl_name_event(hval, &handle->last_ievent->event_id);
}
esl_event_add_header_string(handle->last_ievent, ESL_STACK_BOTTOM, hname, hval);
esl_name_event(hval, &handle->last_ievent->event_id);
}
beg = c + 1;

@ -82,7 +82,7 @@ ESL_DECLARE(esl_status_t) esl_buffer_create(esl_buffer_t **buffer, esl_size_t bl
ESL_DECLARE(esl_size_t) esl_buffer_len(esl_buffer_t *buffer)
{
assert(buffer != NULL);
esl_assert(buffer != NULL);
return buffer->datalen;
@ -91,8 +91,7 @@ ESL_DECLARE(esl_size_t) esl_buffer_len(esl_buffer_t *buffer)
ESL_DECLARE(esl_size_t) esl_buffer_freespace(esl_buffer_t *buffer)
{
assert(buffer != NULL);
esl_assert(buffer != NULL);
if (buffer->max_len) {
return (esl_size_t) (buffer->max_len - buffer->used);
@ -103,7 +102,7 @@ ESL_DECLARE(esl_size_t) esl_buffer_freespace(esl_buffer_t *buffer)
ESL_DECLARE(esl_size_t) esl_buffer_inuse(esl_buffer_t *buffer)
{
assert(buffer != NULL);
esl_assert(buffer != NULL);
return buffer->used;
}
@ -112,7 +111,7 @@ ESL_DECLARE(esl_size_t) esl_buffer_seek(esl_buffer_t *buffer, esl_size_t datalen
{
esl_size_t reading = 0;
assert(buffer != NULL);
esl_assert(buffer != NULL);
if (buffer->used < 1) {
buffer->used = 0;
@ -133,7 +132,7 @@ ESL_DECLARE(esl_size_t) esl_buffer_toss(esl_buffer_t *buffer, esl_size_t datalen
{
esl_size_t reading = 0;
assert(buffer != NULL);
esl_assert(buffer != NULL);
if (buffer->used < 1) {
buffer->used = 0;
@ -174,8 +173,8 @@ ESL_DECLARE(esl_size_t) esl_buffer_read(esl_buffer_t *buffer, void *data, esl_si
{
esl_size_t reading = 0;
assert(buffer != NULL);
assert(data != NULL);
esl_assert(buffer != NULL);
esl_assert(data != NULL);
if (buffer->used < 1) {
@ -201,7 +200,7 @@ ESL_DECLARE(esl_size_t) esl_buffer_packet_count(esl_buffer_t *buffer)
char *pe, *p, *e, *head = (char *) buffer->head;
esl_size_t x = 0;
assert(buffer != NULL);
esl_assert(buffer != NULL);
e = (head + buffer->used);
@ -224,8 +223,8 @@ ESL_DECLARE(esl_size_t) esl_buffer_read_packet(esl_buffer_t *buffer, void *data,
char *pe, *p, *e, *head = (char *) buffer->head;
esl_size_t datalen = 0;
assert(buffer != NULL);
assert(data != NULL);
esl_assert(buffer != NULL);
esl_assert(data != NULL);
e = (head + buffer->used);
@ -251,9 +250,9 @@ ESL_DECLARE(esl_size_t) esl_buffer_write(esl_buffer_t *buffer, const void *data,
{
esl_size_t freespace, actual_freespace;
assert(buffer != NULL);
assert(data != NULL);
assert(buffer->data != NULL);
esl_assert(buffer != NULL);
esl_assert(data != NULL);
esl_assert(buffer->data != NULL);
if (!datalen) {
return buffer->used;
@ -312,8 +311,8 @@ ESL_DECLARE(esl_size_t) esl_buffer_write(esl_buffer_t *buffer, const void *data,
ESL_DECLARE(void) esl_buffer_zero(esl_buffer_t *buffer)
{
assert(buffer != NULL);
assert(buffer->data != NULL);
esl_assert(buffer != NULL);
esl_assert(buffer->data != NULL);
buffer->used = 0;
buffer->actually_used = 0;

@ -94,6 +94,7 @@ library_include_HEADERS = \
$(SRC)/include/ftdm_declare.h \
$(SRC)/include/ftdm_threadmutex.h \
$(SRC)/include/ftdm_os.h \
$(SRC)/include/ftdm_call_utils.h \
$(SRC)/include/ftdm_dso.h
lib_LTLIBRARIES = libfreetdm.la

@ -5,5 +5,9 @@
then ftdm_event_t would be renamed to ftdm_oob_event_t and the enum_id renamed to type, then ftdm_span_next_event()
will only return OOB events
- query span hw status (connected/disconnected) on startup
- Deprecate last_error members.
It requires a lot of discipline to set the last_error string for every failure.
It does not add much value to the user either, most of the errors are criptic and
cannot be shown to end users, we already provide extensive logging for problem
troubleshooting.

@ -1,4 +1,4 @@
#!/bin/bash
#!/bin/sh
autoheader
libtoolize --force --copy
aclocal

@ -0,0 +1,14 @@
APIs that result in an event when the API returns FTDM_SUCCESS
ftdm_channel_call_answer()
ftdm_channel_call_indicate()
FTDM_SIGEVENT_INDICATION_COMPLETED
*note that FTDM_SIGEVENT_INDICATION_COMPLETED has associated data to indicate the result of the indication
*note this event is only delivered on non-blocking channels
ftdm_call_place
FTDM_SIGEVENT_DIALING
ftdm_channel_call_hangup
FTDM_SIGEVENT_RELEASED

@ -0,0 +1,25 @@
Glare is a PITA.
Although configuration of ISDN links can be done to minimize glare, we also must have a clear policy
on how the FreeTDM API is supposed to behave on glare across signaling modules.
There is a well-known race in the FreeTDM API since the beginning. When a user wants to place a call with
the old APIs:
1. ftdm_channel_open_xx (to hunt the channel by group, span or select a channel individually)
2. ftdm_channel_call_place() to place the actual call.
Since the user has no access to channel locking, between opening a channel and placing a call, an incoming call could be
received. Therefore things can get complicated and that is why you should STOP USING those 2 deprecated functions.
The replacement is ftdm_call_place().
ftdm_call_place receives the information required to hunt the channel and place the call.
If glare is detected after placing the call and the signaling stack decides to drop the local call, a regular
SIGEVENT_STOP will be sent with the hangup cause FTDM_CAUSE_REQUESTED_CHAN_UNAVAIL.
ftdm_call_place may return FTDM_BREAK if glare is detected while placing the call, in such cases you can try
calling ftdm_call_place again to hunt another channel.

@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@ -17,13 +17,13 @@
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
* Moises Silva <moy@sangoma.com>
* David Yat Sin <dyatsin@sangoma.com>
*
@ -1073,6 +1073,66 @@ static const char* channel_get_variable(switch_core_session_t *session, switch_e
return NULL;
}
typedef struct {
switch_event_t *var_event;
switch_core_session_t *new_session;
private_t *tech_pvt;
switch_caller_profile_t *caller_profile;
} hunt_data_t;
static ftdm_status_t on_channel_found(ftdm_channel_t *fchan, ftdm_caller_data_t *caller_data)
{
uint32_t span_id, chan_id;
const char *var;
char *sess_uuid;
char name[128];
ftdm_status_t status;
hunt_data_t *hdata = caller_data->priv;
switch_channel_t *channel = switch_core_session_get_channel(hdata->new_session);
if ((var = switch_event_get_header(hdata->var_event, "freetdm_pre_buffer_size"))) {
int tmp = atoi(var);
if (tmp > -1) {
ftdm_channel_command(fchan, FTDM_COMMAND_SET_PRE_BUFFER_SIZE, &tmp);
}
}
span_id = ftdm_channel_get_span_id(fchan);
chan_id = ftdm_channel_get_id(fchan);
tech_init(hdata->tech_pvt, hdata->new_session, fchan);
snprintf(name, sizeof(name), "FreeTDM/%u:%u/%s", span_id, chan_id, caller_data->dnis.digits);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connect outbound channel %s\n", name);
switch_channel_set_name(channel, name);
switch_channel_set_variable(channel, "freetdm_span_name", ftdm_channel_get_span_name(fchan));
switch_channel_set_variable_printf(channel, "freetdm_span_number", "%d", span_id);
switch_channel_set_variable_printf(channel, "freetdm_chan_number", "%d", chan_id);
switch_channel_set_caller_profile(channel, hdata->caller_profile);
hdata->tech_pvt->caller_profile = hdata->caller_profile;
switch_channel_set_state(channel, CS_INIT);
sess_uuid = switch_core_session_get_uuid(hdata->new_session);
status = ftdm_channel_add_token(fchan, sess_uuid, ftdm_channel_get_token_count(fchan));
switch_assert(status == FTDM_SUCCESS);
if (SPAN_CONFIG[span_id].limit_calls) {
char spanresource[512];
snprintf(spanresource, sizeof(spanresource), "span_%s_%s", ftdm_channel_get_span_name(fchan),
caller_data->dnis.digits);
ftdm_log(FTDM_LOG_DEBUG, "Adding rate limit resource on channel %d:%d (%s/%s/%d/%d)\n",
span_id, chan_id, FREETDM_LIMIT_REALM,
spanresource, SPAN_CONFIG[span_id].limit_calls, SPAN_CONFIG[span_id].limit_seconds);
if (switch_limit_incr("hash", hdata->new_session, FREETDM_LIMIT_REALM, spanresource,
SPAN_CONFIG[span_id].limit_calls, SPAN_CONFIG[span_id].limit_seconds) != SWITCH_STATUS_SUCCESS) {
return FTDM_BREAK;
}
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Attached session %s to channel %d:%d\n", sess_uuid, span_id, chan_id);
return FTDM_SUCCESS;
}
/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines
that allocate memory or you will have 1 channel with memory allocated from another channel's pool!
*/
@ -1081,13 +1141,11 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
switch_core_session_t **new_session, switch_memory_pool_t **pool,
switch_originate_flag_t flags, switch_call_cause_t *cancel_cause)
{
hunt_data_t hunt_data;
const char *dest = NULL;
char *data = NULL;
int span_id = -1, group_id = -1, chan_id = 0;
ftdm_channel_t *ftdmchan = NULL;
switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
char name[128];
ftdm_status_t status;
int direction = FTDM_TOP_DOWN;
ftdm_caller_data_t caller_data = {{ 0 }};
@ -1097,6 +1155,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
int argc = 0;
const char *var;
const char *dest_num = NULL, *callerid_num = NULL;
ftdm_hunting_scheme_t hunting;
if (!outbound_profile) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing caller profile\n");
@ -1125,7 +1184,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
if ((argc = switch_separate_string(data, '/', argv, (sizeof(argv) / sizeof(argv[0])))) < 2) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid dial string\n");
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
}
if (switch_is_number(argv[0])) {
@ -1255,11 +1314,11 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
}
if (switch_test_flag(outbound_profile, SWITCH_CPF_SCREEN)) {
caller_data.screen = 1;
caller_data.screen = FTDM_SCREENING_VERIFIED_PASSED;
}
if (switch_test_flag(outbound_profile, SWITCH_CPF_HIDE_NUMBER)) {
caller_data.pres = 1;
caller_data.pres = FTDM_PRES_RESTRICTED;
}
if ((var = channel_get_variable(session, var_event, "freetdm_bearer_capability"))) {
@ -1309,30 +1368,21 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
ftdm_set_string(caller_data.cid_name, outbound_profile->caller_id_name);
ftdm_set_string(caller_data.cid_num.digits, switch_str_nil(outbound_profile->caller_id_number));
memset(&hunting, 0, sizeof(hunting));
if (group_id >= 0) {
status = ftdm_channel_open_by_group(group_id, direction, &caller_data, &ftdmchan);
hunting.mode = FTDM_HUNT_GROUP;
hunting.mode_data.group.group_id = group_id;
hunting.mode_data.group.direction = direction;
} else if (chan_id) {
status = ftdm_channel_open(span_id, chan_id, &ftdmchan);
hunting.mode = FTDM_HUNT_CHAN;
hunting.mode_data.chan.span_id = span_id;
hunting.mode_data.chan.chan_id = chan_id;
} else {
status = ftdm_channel_open_by_span(span_id, direction, &caller_data, &ftdmchan);
hunting.mode = FTDM_HUNT_SPAN;
hunting.mode_data.span.span_id = span_id;
hunting.mode_data.span.direction = direction;
}
if (status != FTDM_SUCCESS) {
if (caller_data.hangup_cause == SWITCH_CAUSE_NONE) {
caller_data.hangup_cause = SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION;
}
return caller_data.hangup_cause;
}
if ((var = switch_event_get_header(var_event, "freetdm_pre_buffer_size"))) {
int tmp = atoi(var);
if (tmp > -1) {
ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_PRE_BUFFER_SIZE, &tmp);
}
}
span_id = ftdm_channel_get_span_id(ftdmchan);
chan_id = ftdm_channel_get_id(ftdmchan);
for (h = var_event->headers; h; h = h->next) {
if (!strncasecmp(h->name, FREETDM_VAR_PREFIX, FREETDM_VAR_PREFIX_LEN)) {
@ -1343,57 +1393,31 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
}
}
}
if ((*new_session = switch_core_session_request(freetdm_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool)) != 0) {
private_t *tech_pvt;
switch_caller_profile_t *caller_profile;
switch_channel_t *channel = switch_core_session_get_channel(*new_session);
switch_core_session_add_stream(*new_session, NULL);
if ((tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t))) != 0) {
tech_init(tech_pvt, *new_session, ftdmchan);
} else {
if (!(tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t)))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n");
switch_core_session_destroy(new_session);
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
goto fail;
}
snprintf(name, sizeof(name), "FreeTDM/%u:%u/%s", span_id, chan_id, dest);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connect outbound channel %s\n", name);
switch_channel_set_name(channel, name);
switch_channel_set_variable(channel, "freetdm_span_name", ftdm_channel_get_span_name(ftdmchan));
switch_channel_set_variable_printf(channel, "freetdm_span_number", "%d", span_id);
switch_channel_set_variable_printf(channel, "freetdm_chan_number", "%d", chan_id);
ftdm_channel_set_caller_data(ftdmchan, &caller_data);
caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
caller_profile->destination_number = switch_core_strdup(caller_profile->pool, switch_str_nil(dest_num));
caller_profile->caller_id_number = switch_core_strdup(caller_profile->pool, switch_str_nil(callerid_num));
switch_channel_set_caller_profile(channel, caller_profile);
tech_pvt->caller_profile = caller_profile;
switch_channel_set_state(channel, CS_INIT);
if (ftdm_channel_add_token(ftdmchan, switch_core_session_get_uuid(*new_session), ftdm_channel_get_token_count(ftdmchan)) != FTDM_SUCCESS) {
switch_core_session_destroy(new_session);
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
goto fail;
}
hunting.result_cb = on_channel_found;
hunt_data.var_event = var_event;
hunt_data.new_session = *new_session;
hunt_data.caller_profile = caller_profile;
hunt_data.tech_pvt = tech_pvt;
caller_data.priv = &hunt_data;
if (SPAN_CONFIG[span_id].limit_calls) {
char spanresource[512];
snprintf(spanresource, sizeof(spanresource), "span_%s_%s", ftdm_channel_get_span_name(ftdmchan), caller_data.dnis.digits);
ftdm_log(FTDM_LOG_DEBUG, "Adding rate limit resource on channel %d:%d (%s/%s/%d/%d)\n", span_id, chan_id, FREETDM_LIMIT_REALM,
spanresource, SPAN_CONFIG[span_id].limit_calls, SPAN_CONFIG[span_id].limit_seconds);
if (switch_limit_incr("hash", *new_session, FREETDM_LIMIT_REALM, spanresource, SPAN_CONFIG[span_id].limit_calls, SPAN_CONFIG[span_id].limit_seconds) != SWITCH_STATUS_SUCCESS) {
switch_core_session_destroy(new_session);
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
goto fail;
}
}
if ((status = ftdm_channel_call_place(ftdmchan)) != FTDM_SUCCESS) {
if ((status = ftdm_call_place(&caller_data, &hunting)) != FTDM_SUCCESS) {
if (tech_pvt->read_codec.implementation) {
switch_core_codec_destroy(&tech_pvt->read_codec);
}
@ -1402,28 +1426,22 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
switch_core_codec_destroy(&tech_pvt->write_codec);
}
switch_core_session_destroy(new_session);
if (status == FTDM_BREAK) { /* glare, we don't want to touch the channel since is being used for incoming call now */
if (status == FTDM_BREAK || status == FTDM_EBUSY) {
cause = SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION;
ftdmchan = NULL;
} else {
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
}
goto fail;
goto fail;
}
ftdm_channel_init(ftdmchan);
ftdm_channel_init(caller_data.fchan);
return SWITCH_CAUSE_SUCCESS;
}
fail:
if (ftdmchan) {
ftdm_channel_call_hangup_with_cause(ftdmchan, FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE);
}
return cause;
}
static void ftdm_enable_channel_dtmf(ftdm_channel_t *fchan, switch_channel_t *channel)
@ -1645,6 +1663,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_common_signal)
case FTDM_SIGEVENT_RELEASED:
case FTDM_SIGEVENT_INDICATION_COMPLETED:
case FTDM_SIGEVENT_DIALING:
{
/* Swallow these events */
return FTDM_BREAK;
@ -3744,9 +3763,7 @@ SWITCH_STANDARD_API(ft_function)
flags = "call swap";
}
fchan = ftdm_span_get_channel(SPAN_CONFIG[j].span, 1);
if (fchan) {
ftdm_channel_get_alarms(fchan, &alarmbits);
}
ftdm_channel_get_alarms(fchan, &alarmbits);
if ((FTDM_SUCCESS == ftdm_span_get_sig_status(SPAN_CONFIG[j].span, &sigstatus))) {
stream->write_function(stream,
@ -4177,6 +4194,19 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load)
freetdm_endpoint_interface->state_handler = &freetdm_state_handlers;
SWITCH_ADD_API(commands_api_interface, "ftdm", "FreeTDM commands", ft_function, FT_SYNTAX);
switch_console_set_complete("add ftdm start");
switch_console_set_complete("add ftdm stop");
switch_console_set_complete("add ftdm retart");
switch_console_set_complete("add ftdm dump");
switch_console_set_complete("add ftdm sigstatus get");
switch_console_set_complete("add ftdm sigstatus set");
switch_console_set_complete("add ftdm trace");
switch_console_set_complete("add ftdm notrace");
switch_console_set_complete("add ftdm q931_pcap");
switch_console_set_complete("add ftdm gains");
switch_console_set_complete("add ftdm dtmf on");
switch_console_set_complete("add ftdm dtmf off");
SWITCH_ADD_APP(app_interface, "disable_ec", "Disable Echo Canceller", "Disable Echo Canceller", disable_ec_function, "", SAF_NONE);
SWITCH_ADD_APP(app_interface, "disable_dtmf", "Disable DTMF Detection", "Disable DTMF Detection", disable_dtmf_function, "", SAF_NONE);

@ -278,7 +278,10 @@ FTDM_ENUM_NAMES(SIGNALING_STATUS_NAMES, SIGSTATUS_STRINGS)
FTDM_STR2ENUM(ftdm_str2ftdm_signaling_status, ftdm_signaling_status2str, ftdm_signaling_status_t, SIGNALING_STATUS_NAMES, FTDM_SIG_STATE_INVALID)
FTDM_ENUM_NAMES(TRACE_DIR_NAMES, TRACE_DIR_STRINGS)
FTDM_STR2ENUM(ftdm_str2ftdm_trace_dir, ftdm_trace_dir2str, ftdm_trace_dir_t, TRACE_DIR_NAMES, FTDM_TRACE_INVALID)
FTDM_STR2ENUM(ftdm_str2ftdm_trace_dir, ftdm_trace_dir2str, ftdm_trace_dir_t, TRACE_DIR_NAMES, FTDM_TRACE_DIR_INVALID)
FTDM_ENUM_NAMES(TRACE_TYPE_NAMES, TRACE_TYPE_STRINGS)
FTDM_STR2ENUM(ftdm_str2ftdm_trace_type, ftdm_trace_type2str, ftdm_trace_type_t, TRACE_TYPE_NAMES, FTDM_TRACE_TYPE_INVALID)
FTDM_ENUM_NAMES(TON_NAMES, TON_STRINGS)
FTDM_STR2ENUM(ftdm_str2ftdm_ton, ftdm_ton2str, ftdm_ton_t, TON_NAMES, FTDM_TON_INVALID)
@ -401,39 +404,39 @@ static __inline__ void ftdm_std_free(void *pool, void *ptr)
free(ptr);
}
static void ftdm_set_echocancel_call_begin(ftdm_channel_t *chan)
FT_DECLARE(void) ftdm_set_echocancel_call_begin(ftdm_channel_t *chan)
{
ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
if (ftdm_channel_test_feature(chan, FTDM_CHANNEL_FEATURE_HWEC)) {
if (ftdm_channel_test_feature(chan, FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE)) {
/* If the ec is disabled on idle, we need to enable it unless is a digital call */
if (caller_data->bearer_capability != FTDM_BEARER_CAP_64K_UNRESTRICTED) {
ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Enabling ec for call in channel state %s\n", ftdm_channel_state2str(chan->state));
ftdm_channel_command(chan, FTDM_COMMAND_ENABLE_ECHOCANCEL, NULL);
}
} else {
/* If the ec is enabled on idle, we do nothing unless is a digital call that needs it disabled */
if (caller_data->bearer_capability == FTDM_BEARER_CAP_64K_UNRESTRICTED) {
ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Disabling ec for digital call in channel state %s\n", ftdm_channel_state2str(chan->state));
ftdm_channel_command(chan, FTDM_COMMAND_DISABLE_ECHOCANCEL, NULL);
}
}
}
}
static void ftdm_set_echocancel_call_end(ftdm_channel_t *chan)
FT_DECLARE(void) ftdm_set_echocancel_call_end(ftdm_channel_t *chan)
{
ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
if (ftdm_channel_test_feature(chan, FTDM_CHANNEL_FEATURE_HWEC)) {
if (ftdm_channel_test_feature(chan, FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE)) {
if (caller_data->bearer_capability != FTDM_BEARER_CAP_64K_UNRESTRICTED) {
ftdm_channel_command(chan, FTDM_COMMAND_DISABLE_ECHOCANCEL, NULL);
}
ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Disabling ec on call end in channel state %s\n", ftdm_channel_state2str(chan->state));
ftdm_channel_command(chan, FTDM_COMMAND_DISABLE_ECHOCANCEL, NULL);
} else {
if (caller_data->bearer_capability == FTDM_BEARER_CAP_64K_UNRESTRICTED) {
ftdm_channel_command(chan, FTDM_COMMAND_ENABLE_ECHOCANCEL, NULL);
}
ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Enabling ec back on call end in channel state %s\n", ftdm_channel_state2str(chan->state));
ftdm_channel_command(chan, FTDM_COMMAND_ENABLE_ECHOCANCEL, NULL);
}
}
}
FT_DECLARE_DATA ftdm_memory_handler_t g_ftdm_mem_handler =
{
/*.pool =*/ NULL,
@ -631,6 +634,10 @@ static ftdm_status_t ftdm_span_destroy(ftdm_span_t *span)
ftdm_mutex_lock(span->mutex);
/* stop the signaling */
/* This is a forced stopped */
ftdm_clear_flag(span, FTDM_SPAN_NON_STOPPABLE);
ftdm_span_stop(span);
/* destroy the channels */
@ -675,43 +682,54 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_get_alarms(ftdm_channel_t *ftdmchan, ftdm
{
ftdm_status_t status = FTDM_FAIL;
ftdm_assert_return(alarmbits != NULL, FTDM_FAIL, "null argument\n");
ftdm_assert_return(alarmbits != NULL, FTDM_EINVAL, "null alarmbits argument\n");
ftdm_assert_return(ftdmchan != NULL, FTDM_EINVAL, "null channel argument\n");
ftdm_assert_return(ftdmchan->span != NULL, FTDM_EINVAL, "null span\n");
ftdm_assert_return(ftdmchan->span->fio != NULL, FTDM_EINVAL, "null io\n");
*alarmbits = FTDM_ALARM_NONE;
if (!ftdmchan->span->fio->get_alarms) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "No get_alarms interface for this channel\n");
return FTDM_ENOSYS;
}
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CONFIGURED)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Cannot get alarms from an unconfigured channel\n");
return FTDM_EINVAL;
}
ftdm_channel_lock(ftdmchan);
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CONFIGURED)) {
if (ftdmchan->span->fio->get_alarms) {
if ((status = ftdmchan->span->fio->get_alarms(ftdmchan)) == FTDM_SUCCESS) {
*ftdmchan->last_error = '\0';
*alarmbits = ftdmchan->alarm_flags;
if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_RED)) {
snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "RED/");
}
if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_YELLOW)) {
snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "YELLOW/");
}
if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_RAI)) {
snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "RAI/");
}
if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_BLUE)) {
snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "BLUE/");
}
if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_AIS)) {
snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "AIS/");
}
if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_GENERAL)) {
snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "GENERAL");
}
*(ftdmchan->last_error + strlen(ftdmchan->last_error) - 1) = '\0';
}
} else {
status = FTDM_NOTIMPL;
}
if ((status = ftdmchan->span->fio->get_alarms(ftdmchan)) != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failed to get alarms from channel\n");
goto done;
}
*ftdmchan->last_error = '\0';
*alarmbits = ftdmchan->alarm_flags;
if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_RED)) {
snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "RED/");
}
if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_YELLOW)) {
snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "YELLOW/");
}
if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_RAI)) {
snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "RAI/");
}
if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_BLUE)) {
snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "BLUE/");
}
if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_AIS)) {
snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "AIS/");
}
if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_GENERAL)) {
snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "GENERAL");
}
*(ftdmchan->last_error + strlen(ftdmchan->last_error) - 1) = '\0';
done:
ftdm_channel_unlock(ftdmchan);
return status;
@ -736,6 +754,11 @@ FT_DECLARE(ftdm_status_t) ftdm_span_stop(ftdm_span_t *span)
ftdm_status_t status = FTDM_SUCCESS;
ftdm_mutex_lock(span->mutex);
if (ftdm_test_flag(span, FTDM_SPAN_NON_STOPPABLE)) {
status = FTDM_NOTIMPL;
goto done;
}
if (!ftdm_test_flag(span, FTDM_SPAN_STARTED)) {
status = FTDM_EINVAL;
@ -1422,8 +1445,9 @@ static __inline__ int request_voice_channel(ftdm_channel_t *check, ftdm_channel_
* sometimes with the group or span lock held and were
* blocking anyone hunting for channels available and
* I believe teh channel_request() function may take
* a bit of time
* */
* a bit of time. However channel_request is a callback
* used by boost and may be only a few other old sig mods
* and it should be deprecated */
ftdm_mutex_unlock(check->mutex);
ftdm_set_caller_data(check->span, caller_data);
status = check->span->channel_request(check->span, check->chan_id,
@ -1436,7 +1460,9 @@ static __inline__ int request_voice_channel(ftdm_channel_t *check, ftdm_channel_
if (status == FTDM_SUCCESS) {
*ftdmchan = check;
ftdm_set_flag(check, FTDM_CHANNEL_OUTBOUND);
#if 0
ftdm_mutex_unlock(check->mutex);
#endif
return 1;
}
}
@ -1488,9 +1514,9 @@ static ftdm_status_t __inline__ get_best_rated(ftdm_channel_t **fchan, ftdm_chan
}
*fchan = best_rated;
ftdm_set_flag(best_rated, FTDM_CHANNEL_OUTBOUND);
#if 0
ftdm_mutex_unlock(best_rated->mutex);
#endif
return FTDM_SUCCESS;
}
@ -1520,7 +1546,7 @@ FT_DECLARE(int) ftdm_channel_get_availability(ftdm_channel_t *ftdmchan)
return availability;
}
FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_group(uint32_t group_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan)
static ftdm_status_t _ftdm_channel_open_by_group(uint32_t group_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan)
{
ftdm_status_t status = FTDM_FAIL;
ftdm_channel_t *check = NULL;
@ -1601,6 +1627,16 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_group(uint32_t group_id, ftdm_dir
return status;
}
FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_group(uint32_t group_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan)
{
ftdm_status_t status;
status = _ftdm_channel_open_by_group(group_id, direction, caller_data, ftdmchan);
if (status == FTDM_SUCCESS) {
ftdm_channel_t *fchan = *ftdmchan;
ftdm_channel_unlock(fchan);
}
return status;
}
FT_DECLARE(ftdm_status_t) ftdm_span_channel_use_count(ftdm_span_t *span, uint32_t *count)
{
@ -1623,7 +1659,8 @@ FT_DECLARE(ftdm_status_t) ftdm_span_channel_use_count(ftdm_span_t *span, uint32_
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan)
/* Hunt a channel by span, if successful the channel is returned locked */
static ftdm_status_t _ftdm_channel_open_by_span(uint32_t span_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan)
{
ftdm_status_t status = FTDM_FAIL;
ftdm_channel_t *check = NULL;
@ -1721,6 +1758,17 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direc
return status;
}
FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan)
{
ftdm_status_t status;
status = _ftdm_channel_open_by_span(span_id, direction, caller_data, ftdmchan);
if (status == FTDM_SUCCESS) {
ftdm_channel_t *fchan = *ftdmchan;
ftdm_channel_unlock(fchan);
}
return status;
}
FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan)
{
ftdm_status_t status = FTDM_FAIL;
@ -1771,7 +1819,7 @@ done:
return status;
}
FT_DECLARE(ftdm_status_t) ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan)
static ftdm_status_t _ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan)
{
ftdm_channel_t *check = NULL;
ftdm_span_t *span = NULL;
@ -1852,6 +1900,10 @@ openchan:
ftdm_set_flag(check, FTDM_CHANNEL_INUSE);
ftdm_set_flag(check, FTDM_CHANNEL_OUTBOUND);
*ftdmchan = check;
#if 1
/* we've got the channel, do not unlock it */
goto done;
#endif
unlockchan:
ftdm_mutex_unlock(check->mutex);
@ -1865,6 +1917,17 @@ done:
return status;
}
FT_DECLARE(ftdm_status_t) ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan)
{
ftdm_status_t status;
status = _ftdm_channel_open(span_id, chan_id, ftdmchan);
if (status == FTDM_SUCCESS) {
ftdm_channel_t *fchan = *ftdmchan;
ftdm_channel_unlock(fchan);
}
return status;
}
FT_DECLARE(uint32_t) ftdm_channel_get_id(const ftdm_channel_t *ftdmchan)
{
return ftdmchan->chan_id;
@ -2029,6 +2092,11 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_unhold(const char *file, const char
FT_DECLARE(void) ftdm_ack_indication(ftdm_channel_t *fchan, ftdm_channel_indication_t indication, ftdm_status_t status)
{
ftdm_sigmsg_t msg;
if (!ftdm_test_flag(fchan, FTDM_CHANNEL_IND_ACK_PENDING)) {
return;
}
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Acknowledging indication %s in state %s (rc = %d)\n",
ftdm_channel_indication2str(indication), ftdm_channel_state2str(fchan->state), status);
ftdm_clear_flag(fchan, FTDM_CHANNEL_IND_ACK_PENDING);
@ -2040,25 +2108,11 @@ FT_DECLARE(void) ftdm_ack_indication(ftdm_channel_t *fchan, ftdm_channel_indicat
ftdm_span_send_signal(fchan->span, &msg);
}
/*! \brief Answer call without locking the channel. The caller must have locked first
* \note This function was added because ftdm_channel_call_indicate needs to answer the call
* when its already locking the channel, ftdm_channel_set_state cannot be called with the same
* lock locked once or more (recursive lock) and wait for the result */
/*! Answer call without locking the channel. The caller must have locked first */
static ftdm_status_t _ftdm_channel_call_answer_nl(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan)
{
ftdm_status_t status = FTDM_SUCCESS;
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
status = FTDM_EINVAL;
goto done;
}
if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call is already TERMINATING\n");
status = FTDM_ECANCELED;
goto done;
}
if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_SKIP_STATES)) {
/* We will fail RFC's if we not skip states, but some modules apart from ftmod_sangoma_isdn
* expect the call to always to go PROGRESS and PROGRESS MEDIA state before going to UP, so
@ -2108,23 +2162,20 @@ done:
FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan)
{
ftdm_status_t status = FTDM_SUCCESS;
ftdm_status_t status;
ftdm_channel_lock(ftdmchan);
/* we leave the locking up to ftdm_channel_call_indicate, DO NOT lock here since ftdm_channel_call_indicate expects
* the lock recursivity to be 1 */
status = _ftdm_channel_call_indicate(file, func, line, ftdmchan, FTDM_CHANNEL_INDICATE_ANSWER);
status = _ftdm_channel_call_answer_nl(file, func, line, ftdmchan);
ftdm_channel_unlock(ftdmchan);
return status;
}
/* lock must be acquired by the caller! */
static ftdm_status_t _ftdm_channel_call_hangup_nl(ftdm_channel_t *chan, const char *file, const char *func, int line)
static ftdm_status_t _ftdm_channel_call_hangup_nl(const char *file, const char *func, int line, ftdm_channel_t *chan)
{
ftdm_status_t status = FTDM_SUCCESS;
ftdm_set_flag(chan, FTDM_CHANNEL_USER_HANGUP);
ftdm_set_echocancel_call_end(chan);
if (chan->state != FTDM_CHANNEL_STATE_DOWN) {
@ -2135,6 +2186,11 @@ static ftdm_status_t _ftdm_channel_call_hangup_nl(ftdm_channel_t *chan, const ch
if (chan->hangup_timer) {
ftdm_sched_cancel_timer(globals.timingsched, chan->hangup_timer);
}
ftdm_set_flag(chan, FTDM_CHANNEL_USER_HANGUP);
/* if a state change requested by the user was pending, a hangup certainly cancels that request */
if (ftdm_test_flag(chan, FTDM_CHANNEL_STATE_CHANGE)) {
ftdm_channel_cancel_state(file, func, line, chan);
}
status = ftdm_channel_set_state(file, func, line, chan, FTDM_CHANNEL_STATE_HANGUP, 1);
} else {
/* the signaling stack did not touch the state,
@ -2158,7 +2214,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup_with_cause(const char *file,
ftdmchan->caller_data.hangup_cause = cause;
status = _ftdm_channel_call_hangup_nl(ftdmchan, file, func, line);
status = _ftdm_channel_call_hangup_nl(file, func, line, ftdmchan);
ftdm_channel_unlock(ftdmchan);
return status;
@ -2172,7 +2228,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup(const char *file, const char
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING;
status = _ftdm_channel_call_hangup_nl(ftdmchan, file, func, line);
status = _ftdm_channel_call_hangup_nl(file, func, line, ftdmchan);
ftdm_channel_unlock(ftdmchan);
return status;
@ -2238,13 +2294,13 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch
ftdm_assert_return(ftdmchan, FTDM_FAIL, "Null channel\n");
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Indicating %s in state %s\n",
ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, "Indicating %s in state %s\n",
ftdm_channel_indication2str(indication), ftdm_channel_state2str(ftdmchan->state));
ftdm_channel_lock(ftdmchan);
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IND_ACK_PENDING)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot indicate %s in channel with indication %s still pending in state %s\n",
ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "Cannot indicate %s in channel with indication %s still pending in state %s\n",
ftdm_channel_indication2str(indication),
ftdm_channel_indication2str(ftdmchan->indication),
ftdm_channel_state2str(ftdmchan->state));
@ -2253,17 +2309,19 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch
}
ftdmchan->indication = indication;
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_IND_ACK_PENDING);
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NONBLOCK)) {
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_IND_ACK_PENDING);
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot indicate %s in outgoing channel in state %s\n",
ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "Cannot indicate %s in outgoing channel in state %s\n",
ftdm_channel_indication2str(indication), ftdm_channel_state2str(ftdmchan->state));
status = FTDM_EINVAL;
goto done;
}
if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Ignoring indication %s because the call is in %s state\n",
ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, "Ignoring indication %s because the call is in %s state\n",
ftdm_channel_indication2str(indication), ftdm_channel_state2str(ftdmchan->state));
status = FTDM_ECANCELED;
goto done;
@ -2279,7 +2337,8 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch
status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_BUSY, 1);
break;
case FTDM_CHANNEL_INDICATE_PROCEED:
if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_PROCEED_STATE)) {
if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_PROCEED_STATE) ||
ftdmchan->state == FTDM_CHANNEL_STATE_PROCEED) {
ftdm_ack_indication(ftdmchan, indication, status);
goto done;
}
@ -2299,14 +2358,13 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch
/* set state unlocks the channel so we need to re-confirm that the channel hasn't gone to hell */
if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring progress media because the call is terminating\n");
ftdm_log_chan_ex_msg(ftdmchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, "Ignoring progress media because the call is terminating\n");
goto done;
}
}
status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1);
break;
case FTDM_CHANNEL_INDICATE_ANSWER:
/* _ftdm_channel_call_answer takes care of the indication ack */
status = _ftdm_channel_call_answer_nl(file, func, line, ftdmchan);
break;
default:
@ -2352,61 +2410,151 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_reset(const char *file, const char *func
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan)
static ftdm_status_t _ftdm_channel_call_place_nl(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan)
{
ftdm_status_t status = FTDM_FAIL;
ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel");
ftdm_assert_return(ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND), FTDM_FAIL, "Call place, but outbound flag not set\n");
ftdm_set_echocancel_call_begin(ftdmchan);
ftdm_channel_lock(ftdmchan);
if (ftdmchan->span->outgoing_call) {
status = ftdmchan->span->outgoing_call(ftdmchan);
} else {
status = FTDM_NOTIMPL;
ftdm_log(FTDM_LOG_ERROR, "outgoing_call method not implemented in this span!\n");
if (!ftdmchan->span->outgoing_call) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "outgoing_call method not implemented in this span!\n");
status = FTDM_ENOSYS;
goto done;
}
if (status == FTDM_SUCCESS) {
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED);
ftdm_call_set_call_id(ftdmchan, &ftdmchan->caller_data);
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Cannot place call in channel that is not open!\n");
goto done;
}
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Cannot place call in non outbound channel in state %s!\n", ftdm_channel_state2str(ftdmchan->state));
goto done;
}
if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Cannot place call in channel in state %s!\n", ftdm_channel_state2str(ftdmchan->state));
goto done;
}
status = ftdmchan->span->outgoing_call(ftdmchan);
if (status == FTDM_BREAK) {
/* the signaling module detected glare on time */
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Glare detected, you should hunt in another channel!\n");
goto done;
}
if (status != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failed to place call!\n");
goto done;
}
/* in case of success, *before* unlocking the channel, we must set the call started flag and the call id
* that is a guarantee that signaling modules expect from us */
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED);
ftdm_call_set_call_id(ftdmchan, &ftdmchan->caller_data);
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NONBLOCK)) {
/* be aware this waiting unlocks the channel and locks it back when done */
ftdm_wait_for_flag_cleared(ftdmchan, FTDM_CHANNEL_STATE_CHANGE, 100);
}
ftdm_channel_unlock(ftdmchan);
done:
#ifdef __WINDOWS__
UNREFERENCED_PARAMETER(file);
UNREFERENCED_PARAMETER(func);
UNREFERENCED_PARAMETER(line);
#endif
return status;
}
FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan)
{
ftdm_status_t status;
ftdm_channel_lock(ftdmchan);
status = _ftdm_channel_call_place_nl(file, func, line, ftdmchan);
ftdm_channel_unlock(ftdmchan);
return status;
}
FT_DECLARE(ftdm_status_t) _ftdm_call_place(const char *file, const char *func, int line,
ftdm_caller_data_t *caller_data, ftdm_hunting_scheme_t *hunting)
{
ftdm_status_t status = FTDM_SUCCESS;
ftdm_channel_t *fchan = NULL;
ftdm_assert_return(caller_data, FTDM_EINVAL, "Invalid caller data\n");
ftdm_assert_return(hunting, FTDM_EINVAL, "Invalid hunting scheme\n");
if (hunting->mode == FTDM_HUNT_SPAN) {
status = _ftdm_channel_open_by_span(hunting->mode_data.span.span_id,
hunting->mode_data.span.direction, caller_data, &fchan);
} else if (hunting->mode == FTDM_HUNT_GROUP) {
status = _ftdm_channel_open_by_group(hunting->mode_data.group.group_id,
hunting->mode_data.group.direction, caller_data, &fchan);
} else if (hunting->mode == FTDM_HUNT_CHAN) {
status = _ftdm_channel_open(hunting->mode_data.chan.span_id, hunting->mode_data.chan.chan_id, &fchan);
} else {
ftdm_log(FTDM_LOG_ERROR, "Cannot make outbound call with invalid hunting mode %d\n", hunting->mode);
return FTDM_EINVAL;
}
if (status != FTDM_SUCCESS) {
return FTDM_EBUSY;
}
/* we have a locked channel and are not afraid of using it! */
status = hunting->result_cb(fchan, caller_data);
if (status != FTDM_SUCCESS) {
status = FTDM_ECANCELED;
goto done;
}
ftdm_channel_set_caller_data(fchan, caller_data);
status = _ftdm_channel_call_place_nl(file, func, line, fchan);
if (status != FTDM_SUCCESS) {
_ftdm_channel_call_hangup_nl(file, func, line, fchan);
goto done;
}
caller_data->fchan = fchan;
done:
ftdm_channel_unlock(fchan);
return status;
}
FT_DECLARE(ftdm_status_t) ftdm_channel_set_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t sigstatus)
FT_DECLARE(ftdm_status_t) ftdm_channel_set_sig_status(ftdm_channel_t *fchan, ftdm_signaling_status_t sigstatus)
{
ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel\n");
ftdm_assert_return(ftdmchan->span != NULL, FTDM_FAIL, "Null span\n");
ftdm_status_t res;
ftdm_assert_return(fchan != NULL, FTDM_FAIL, "Null channel\n");
ftdm_assert_return(fchan->span != NULL, FTDM_FAIL, "Null span\n");
ftdm_assert_return(fchan->span->set_channel_sig_status != NULL, FTDM_ENOSYS, "Not implemented\n");
ftdm_channel_lock(fchan);
if (ftdm_test_flag(fchan, FTDM_CHANNEL_IN_ALARM)) {
ftdm_log_chan_msg(fchan, FTDM_LOG_WARNING, "You can not set the signaling status of an alarmed channel\n");
res = FTDM_EINVAL;
goto done;
}
if (sigstatus == FTDM_SIG_STATE_DOWN) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "The user is not allowed to set the signaling status to DOWN, valid states are UP or SUSPENDED\n");
return FTDM_FAIL;
ftdm_log_chan_msg(fchan, FTDM_LOG_WARNING, "You can not set the signaling status to DOWN, valid states are UP or SUSPENDED\n");
res = FTDM_EINVAL;
goto done;
}
if (ftdmchan->span->set_channel_sig_status) {
ftdm_status_t res;
ftdm_channel_lock(ftdmchan);
res = ftdmchan->span->set_channel_sig_status(ftdmchan, sigstatus);
ftdm_channel_unlock(ftdmchan);
return res;
} else {
ftdm_log(FTDM_LOG_ERROR, "set_channel_sig_status method not implemented!\n");
return FTDM_FAIL;
}
res = fchan->span->set_channel_sig_status(fchan, sigstatus);
done:
ftdm_channel_unlock(fchan);
return res;
}
FT_DECLARE(ftdm_status_t) ftdm_channel_get_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t *sigstatus)
@ -2576,10 +2724,9 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_close(ftdm_channel_t **ftdmchan)
ftdm_log_chan_msg(check, FTDM_LOG_WARNING, "Channel not opened, proceeding anyway\n");
}
status = check->fio->close(check);
if (status == FTDM_SUCCESS) {
ftdm_channel_done(check);
*ftdmchan = NULL;
}
ftdm_assert(status == FTDM_SUCCESS, "Failed to close channel!\n");
ftdm_channel_done(check);
*ftdmchan = NULL;
check->ring_count = 0;
ftdm_mutex_unlock(check->mutex);
}
@ -2921,23 +3068,27 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
case FTDM_COMMAND_ENABLE_DTMF_DETECT:
{
/* if they don't have thier own, use ours */
if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) {
teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate);
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT);
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF);
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Enabled software DTMF detector\n");
GOTO_STATUS(done, FTDM_SUCCESS);
if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) {
if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) {
teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate);
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT);
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF);
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Enabled software DTMF detector\n");
GOTO_STATUS(done, FTDM_SUCCESS);
}
}
}
break;
case FTDM_COMMAND_DISABLE_DTMF_DETECT:
{
if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) {
teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF);
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Disabled software DTMF detector\n");
GOTO_STATUS(done, FTDM_SUCCESS);
if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) {
if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) {
teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF);
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Disabled software DTMF detector\n");
GOTO_STATUS(done, FTDM_SUCCESS);
}
}
}
break;
@ -5094,6 +5245,16 @@ FT_DECLARE(ftdm_status_t) ftdm_span_start(ftdm_span_t *span)
goto done;
}
/* check the alarms again before starting the signaling module
this works-around some I/O modules (netborder I/O module) that cannot
check the alarm status before during configuration because the spans are
not really started yet at the I/O level */
if (ftdm_set_channels_alarms(span, 0) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Failed to set channel alarms in span %s\n", span->name);
status = FTDM_FAIL;
goto done;
}
status = span->start(span);
if (status == FTDM_SUCCESS) {
ftdm_set_flag_locked(span, FTDM_SPAN_STARTED);
@ -5327,7 +5488,7 @@ static void execute_safety_hangup(void *data)
fchan->hangup_timer = 0;
if (fchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
ftdm_log_chan(fchan, FTDM_LOG_CRIT, "Forcing hangup since the user did not confirmed our hangup after %dms\n", FORCE_HANGUP_TIMER);
_ftdm_channel_call_hangup_nl(fchan, __FILE__, __FUNCTION__, __LINE__);
_ftdm_channel_call_hangup_nl(__FILE__, __FUNCTION__, __LINE__, fchan);
} else {
ftdm_log_chan(fchan, FTDM_LOG_CRIT, "Not performing safety hangup, channel state is %s\n", ftdm_channel_state2str(fchan->state));
}
@ -5337,7 +5498,10 @@ static void execute_safety_hangup(void *data)
FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)
{
if (sigmsg->channel) {
ftdm_mutex_lock(sigmsg->channel->mutex);
ftdm_mutex_lock(sigmsg->channel->mutex);
sigmsg->chan_id = sigmsg->channel->chan_id;
sigmsg->span_id = sigmsg->channel->span_id;
sigmsg->call_id = sigmsg->channel->caller_data.call_id;
}
/* some core things to do on special events */
@ -5347,14 +5511,26 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
{
if (sigmsg->ev_data.sigstatus.status == FTDM_SIG_STATE_UP) {
ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_SIG_UP);
ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_SUSPENDED);
} else {
ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_SIG_UP);
if (sigmsg->ev_data.sigstatus.status == FTDM_SIG_STATE_SUSPENDED) {
ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_SUSPENDED);
} else {
ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_SUSPENDED);
}
}
}
break;
case FTDM_SIGEVENT_START:
{
ftdm_assert(!ftdm_test_flag(sigmsg->channel, FTDM_CHANNEL_CALL_STARTED), "Started call twice!");
if (ftdm_test_flag(sigmsg->channel, FTDM_CHANNEL_OUTBOUND)) {
ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_WARNING, "Inbound call taking over outbound channel\n");
ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_OUTBOUND);
}
ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_CALL_STARTED);
ftdm_call_set_call_id(sigmsg->channel, &sigmsg->channel->caller_data);
ftdm_set_echocancel_call_begin(sigmsg->channel);
@ -5370,20 +5546,46 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
}
break;
case FTDM_SIGEVENT_PROGRESS_MEDIA:
{
/* test signaling module compliance */
if (sigmsg->channel->state != FTDM_CHANNEL_STATE_PROGRESS_MEDIA) {
ftdm_log_chan(sigmsg->channel, FTDM_LOG_WARNING, "FTDM_SIGEVENT_PROGRESS_MEDIA sent in state %s\n", ftdm_channel_state2str(sigmsg->channel->state));
}
}
break;
case FTDM_SIGEVENT_UP:
{
/* test signaling module compliance */
if (sigmsg->channel->state != FTDM_CHANNEL_STATE_UP) {
ftdm_log_chan(sigmsg->channel, FTDM_LOG_WARNING, "FTDM_SIGEVENT_UP sent in state %s\n", ftdm_channel_state2str(sigmsg->channel->state));
}
}
break;
case FTDM_SIGEVENT_STOP:
if (!ftdm_test_flag(sigmsg->channel, FTDM_CHANNEL_CALL_STARTED)) {
/* this happens for FXS devices which blindly send SIGEVENT_STOP, we should fix it there ... */
ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Ignoring SIGEVENT_STOP since user never knew about a call in this channel\n");
goto done;
}
if (ftdm_test_flag(sigmsg->channel, FTDM_CHANNEL_USER_HANGUP)) {
ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Ignoring SIGEVENT_STOP since user already requested hangup\n");
goto done;
}
if (sigmsg->channel->state == FTDM_CHANNEL_STATE_TERMINATING) {
ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Scheduling safety hangup timer\n");
/* if the user does not move us to hangup in 2 seconds, we will do it ourselves */
ftdm_sched_timer(globals.timingsched, "safety-hangup", FORCE_HANGUP_TIMER, execute_safety_hangup, sigmsg->channel, &sigmsg->channel->hangup_timer);
{
/* TODO: we could test for compliance here and check the state is FTDM_CHANNEL_STATE_TERMINATING
* but several modules need to be updated first */
/* if the call was never started, do not send SIGEVENT_STOP
this happens for FXS devices in ftmod_analog which blindly send SIGEVENT_STOP, we should fix it there ... */
if (!ftdm_test_flag(sigmsg->channel, FTDM_CHANNEL_CALL_STARTED)) {
ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Ignoring SIGEVENT_STOP since user never knew about a call in this channel\n");
goto done;
}
if (ftdm_test_flag(sigmsg->channel, FTDM_CHANNEL_USER_HANGUP)) {
ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Ignoring SIGEVENT_STOP since user already requested hangup\n");
goto done;
}
if (sigmsg->channel->state == FTDM_CHANNEL_STATE_TERMINATING) {
ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Scheduling safety hangup timer\n");
/* if the user does not move us to hangup in 2 seconds, we will do it ourselves */
ftdm_sched_timer(globals.timingsched, "safety-hangup", FORCE_HANGUP_TIMER, execute_safety_hangup, sigmsg->channel, &sigmsg->channel->hangup_timer);
}
}
break;
@ -5392,9 +5594,6 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
}
if (sigmsg->channel) {
sigmsg->call_id = sigmsg->channel->caller_data.call_id;
}
/* if the signaling module uses a queue for signaling notifications, then enqueue it */
if (ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE)) {
ftdm_span_queue_signal(span, sigmsg);

@ -70,22 +70,25 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_complete_state(const char *file, const c
if (state == FTDM_CHANNEL_STATE_PROGRESS) {
ftdm_set_flag(fchan, FTDM_CHANNEL_PROGRESS);
} else if (state == FTDM_CHANNEL_STATE_UP) {
ftdm_set_flag(fchan, FTDM_CHANNEL_PROGRESS);
ftdm_set_flag(fchan, FTDM_CHANNEL_MEDIA);
ftdm_set_flag(fchan, FTDM_CHANNEL_ANSWERED);
} else if (state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA) {
ftdm_set_flag(fchan, FTDM_CHANNEL_PROGRESS);
ftdm_set_flag(fchan, FTDM_CHANNEL_MEDIA);
ftdm_test_and_set_media(fchan);
} else if (state == FTDM_CHANNEL_STATE_UP) {
ftdm_set_flag(fchan, FTDM_CHANNEL_PROGRESS);
ftdm_set_flag(fchan, FTDM_CHANNEL_ANSWERED);
ftdm_test_and_set_media(fchan);
} else if (state == FTDM_CHANNEL_STATE_DIALING) {
ftdm_sigmsg_t msg;
memset(&msg, 0, sizeof(msg));
msg.channel = fchan;
msg.event_id = FTDM_SIGEVENT_DIALING;
ftdm_span_send_signal(fchan->span, &msg);
}
/* if there is a pending ack for an indication
* MAINTENANCE WARNING: we're assuming an indication performed
* via state change will involve a single state change
*/
if (ftdm_test_flag(fchan, FTDM_CHANNEL_IND_ACK_PENDING)) {
ftdm_ack_indication(fchan, fchan->indication, FTDM_SUCCESS);
}
/* MAINTENANCE WARNING
* we're assuming an indication performed
* via state change will involve a single state change */
ftdm_ack_indication(fchan, fchan->indication, FTDM_SUCCESS);
hindex = (fchan->hindex == 0) ? (ftdm_array_len(fchan->history) - 1) : (fchan->hindex - 1);
@ -167,6 +170,59 @@ static int ftdm_parse_state_map(ftdm_channel_t *ftdmchan, ftdm_channel_state_t s
return ok;
}
FT_DECLARE(ftdm_status_t) ftdm_channel_cancel_state(const char *file, const char *func, int line, ftdm_channel_t *fchan)
{
ftdm_time_t diff;
ftdm_channel_state_t state;
ftdm_channel_state_t last_state;
uint8_t hindex = 0;
if (!ftdm_test_flag(fchan, FTDM_CHANNEL_STATE_CHANGE)) {
ftdm_log_chan(fchan, FTDM_LOG_WARNING, "Cannot cancel state change from %s to %s, it was already processed\n",
ftdm_channel_state2str(fchan->last_state), ftdm_channel_state2str(fchan->state));
return FTDM_FAIL;
}
if (fchan->state_status != FTDM_STATE_STATUS_NEW) {
ftdm_log_chan(fchan, FTDM_LOG_WARNING, "Failed to cancel state change from %s to %s, state is not new anymore\n",
ftdm_channel_state2str(fchan->last_state), ftdm_channel_state2str(fchan->state));
return FTDM_FAIL;
}
/* compute the last history index */
hindex = (fchan->hindex == 0) ? (ftdm_array_len(fchan->history) - 1) : (fchan->hindex - 1);
diff = fchan->history[hindex].end_time - fchan->history[hindex].time;
/* go back in time and revert the state to the previous state */
state = fchan->state;
last_state = fchan->last_state;
fchan->state = fchan->last_state;
fchan->state_status = FTDM_STATE_STATUS_COMPLETED;
fchan->last_state = fchan->history[hindex].last_state;
fchan->hindex = hindex;
/* clear the state change flag */
ftdm_clear_flag(fchan, FTDM_CHANNEL_STATE_CHANGE);
/* ack any pending indications as cancelled */
ftdm_ack_indication(fchan, fchan->indication, FTDM_ECANCELED);
/* wake up anyone sleeping waiting for the state change to complete, it won't ever be completed */
if (ftdm_test_flag(fchan, FTDM_CHANNEL_BLOCKING)) {
ftdm_clear_flag(fchan, FTDM_CHANNEL_BLOCKING);
ftdm_interrupt_signal(fchan->state_completed_interrupt);
}
/* NOTE
* we could potentially also take out the channel from the pendingchans queue, but I believe is easier just leave it,
* the only side effect will be a call to ftdm_channel_advance_states() for a channel that has nothing to advance */
ftdm_log_chan_ex(fchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, "Cancelled state change from %s to %s in %llums\n",
ftdm_channel_state2str(last_state), ftdm_channel_state2str(state), diff);
return FTDM_SUCCESS;
}
/* this function MUST be called with the channel lock held. If waitrq == 1, the channel will be unlocked/locked (never call it with waitrq == 1 with an lock recursivity > 1) */
#define DEFAULT_WAIT_TIME 1000
FT_DECLARE(ftdm_status_t) ftdm_channel_set_state(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_state_t state, int waitrq)

@ -406,25 +406,36 @@ static ftdm_state_map_t isdn_state_map = {
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_DIALING, FTDM_END},
{FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_PROGRESS,
FTDM_CHANNEL_STATE_UP, FTDM_END}
},
{
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_END}
{FTDM_CHANNEL_STATE_PROCEED, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
},
{
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_DOWN, FTDM_END}
{FTDM_CHANNEL_STATE_RINGING, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
},
{
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
{FTDM_CHANNEL_STATE_DOWN, FTDM_END},
{FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_END}
},
{
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_END}
},
{
ZSD_OUTBOUND,
@ -432,6 +443,24 @@ static ftdm_state_map_t isdn_state_map = {
{FTDM_CHANNEL_STATE_UP, FTDM_END},
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
},
{
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
{FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
},
{
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
{FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
},
{
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
{FTDM_CHANNEL_STATE_DOWN, FTDM_END},
},
/****************************************/
{
@ -462,26 +491,33 @@ static ftdm_state_map_t isdn_state_map = {
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_RING, FTDM_END},
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END}
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_RINGING, FTDM_END}
},
{
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_DOWN, FTDM_END},
{FTDM_CHANNEL_STATE_PROCEED, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS,
FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END}
},
{
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
{FTDM_CHANNEL_STATE_DOWN, FTDM_END},
{FTDM_CHANNEL_STATE_RINGING, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA,
FTDM_CHANNEL_STATE_UP, FTDM_END}
},
{
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA,
FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_UP, FTDM_END},
{FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END}
},
{
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_UP, FTDM_END}
},
{
ZSD_INBOUND,
@ -489,6 +525,24 @@ static ftdm_state_map_t isdn_state_map = {
{FTDM_CHANNEL_STATE_UP, FTDM_END},
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
},
{
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
{FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
},
{
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
{FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
},
{
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
{FTDM_CHANNEL_STATE_DOWN, FTDM_END},
},
}
};
@ -533,8 +587,6 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
break;
case FTDM_CHANNEL_STATE_PROGRESS:
/* RINGING is an alias for PROGRESS state in inbound calls ATM */
case FTDM_CHANNEL_STATE_RINGING:
{
if (ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) {
sig.event_id = FTDM_SIGEVENT_PROGRESS;
@ -542,7 +594,23 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP);
}
} else if (call) {
pri_progress(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 1);
pri_progress(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 0);
} else {
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART);
}
}
break;
case FTDM_CHANNEL_STATE_RINGING:
{
if (ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) {
sig.event_id = FTDM_SIGEVENT_RINGING;
if ((status = ftdm_span_send_signal(ftdm_channel_get_span(chan), &sig) != FTDM_SUCCESS)) {
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP);
}
} else if (call) {
// pri_progress(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 1);
pri_acknowledge(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 1);
} else {
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART);
}
@ -561,7 +629,26 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
ftdm_channel_open_chan(chan);
}
pri_proceeding(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 1);
pri_progress(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 1);
} else {
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART);
}
}
break;
case FTDM_CHANNEL_STATE_PROCEED:
{
if (ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) {
/* PROCEED from other end, notify user */
sig.event_id = FTDM_SIGEVENT_PROCEED;
if ((status = ftdm_span_send_signal(ftdm_channel_get_span(chan), &sig) != FTDM_SUCCESS)) {
ftdm_log(FTDM_LOG_ERROR, "Failed to send PROCEED sigevent on Channel %d:%d\n",
ftdm_channel_get_span_id(chan),
ftdm_channel_get_id(chan));
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP);
}
} else if (call) {
pri_proceeding(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 0);
} else {
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART);
}
@ -572,11 +659,12 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
{
/*
* This needs more auditing for BRI PTMP:
* does pri_acknowledge() steal the call from other devices?
* does pri_acknowledge() steal the call from other devices? (yes, it does)
*/
if (!ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) {
if (call) {
pri_acknowledge(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 0);
pri_proceeding(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 0);
// pri_acknowledge(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 0);
sig.event_id = FTDM_SIGEVENT_START;
if ((status = ftdm_span_send_signal(ftdm_channel_get_span(chan), &sig) != FTDM_SUCCESS)) {
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP);
@ -690,15 +778,22 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
pri_hangup(isdn_data->spri.pri, call, caller_data->hangup_cause);
pri_destroycall(isdn_data->spri.pri, call);
// pri_destroycall(isdn_data->spri.pri, call);
chan->call_data = NULL;
}
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_DOWN);
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
}
break;
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
{
if (call) {
pri_destroycall(isdn_data->spri.pri, call);
chan->call_data = NULL;
}
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_DOWN);
}
break;
case FTDM_CHANNEL_STATE_TERMINATING:
@ -869,7 +964,7 @@ static int on_proceeding(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_
}
}
ftdm_log(FTDM_LOG_DEBUG, "-- Proceeding on channel %d:%d\n", ftdm_span_get_id(span), pevent->proceeding.channel);
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROCEED);
} else {
ftdm_log(FTDM_LOG_DEBUG, "-- Proceeding on channel %d:%d but it's not in the span?\n",
ftdm_span_get_id(span), pevent->proceeding.channel);
@ -909,9 +1004,12 @@ static int on_progress(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING);
goto out;
}
ftdm_log(FTDM_LOG_DEBUG, "-- Progress on channel %d:%d with media\n", ftdm_span_get_id(span), pevent->proceeding.channel);
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
} else {
ftdm_log(FTDM_LOG_DEBUG, "-- Progress on channel %d:%d\n", ftdm_span_get_id(span), pevent->proceeding.channel);
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS);
}
ftdm_log(FTDM_LOG_DEBUG, "-- Progress on channel %d:%d\n", ftdm_span_get_id(span), pevent->proceeding.channel);
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
} else {
ftdm_log(FTDM_LOG_DEBUG, "-- Progress on channel %d:%d but it's not in the span?\n",
ftdm_span_get_id(span), pevent->proceeding.channel);
@ -936,10 +1034,10 @@ static int on_ringing(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve
ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d\n", ftdm_span_get_id(span), pevent->ringing.channel);
/* we may get on_ringing even when we're already in FTDM_CHANNEL_STATE_PROGRESS_MEDIA */
if (ftdm_channel_get_state(chan) == FTDM_CHANNEL_STATE_PROGRESS_MEDIA) {
/* dont try to move to STATE_PROGRESS to avoid annoying veto warning */
return 0;
}
// if (ftdm_channel_get_state(chan) == FTDM_CHANNEL_STATE_PROGRESS_MEDIA) {
// /* dont try to move to STATE_PROGRESS to avoid annoying veto warning */
// return 0;
// }
/* Open channel if inband information is available */
if ((pevent->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) && !ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
@ -959,7 +1057,8 @@ static int on_ringing(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve
goto out;
}
}
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS);
// ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS);
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RINGING);
} else {
ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d but it's not in the span?\n",
ftdm_span_get_id(span), pevent->ringing.channel);
@ -1913,6 +2012,9 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
span->get_channel_sig_status = isdn_get_channel_sig_status;
span->get_span_sig_status = isdn_get_span_sig_status;
/* move calls to PROCEED state when they hit dialplan (ROUTING state in FreeSWITCH) */
ftdm_set_flag(span, FTDM_SPAN_USE_PROCEED_STATE);
if ((isdn_data->opts & FTMOD_LIBPRI_OPT_SUGGEST_CHANNEL)) {
span->channel_request = isdn_channel_request;
ftdm_set_flag(span, FTDM_SPAN_SUGGEST_CHAN_ID);

@ -50,8 +50,6 @@
#include "freetdm.h"
#include "private/ftdm_core.h"
typedef int openr2_call_status_t;
/* when the user stops a span, we clear FTDM_R2_SPAN_STARTED, so that the signaling thread
* knows it must stop, and we wait for FTDM_R2_RUNNING to be clear, which tells us the
* signaling thread is done. */
@ -71,8 +69,8 @@ typedef struct ftdm_r2_call_t {
int accepted:1;
int answer_pending:1;
int disconnect_rcvd:1;
int ftdm_call_started:1;
int protocol_error:1;
int localsuspend_on_alarm:1;
ftdm_size_t dnis_index;
ftdm_size_t ani_index;
char logname[255];
@ -293,8 +291,11 @@ static ftdm_call_cause_t ftdm_r2_cause_to_ftdm_cause(ftdm_channel_t *fchan, open
case OR2_CAUSE_FORCED_RELEASE:
return FTDM_CAUSE_NORMAL_CLEARING;
case OR2_CAUSE_GLARE:
return FTDM_CAUSE_REQUESTED_CHAN_UNAVAIL;
}
ftdm_log_chan(fchan, FTDM_LOG_WARNING, "Mapping openr2 cause %d to unspecified\n", cause);
ftdm_log_chan(fchan, FTDM_LOG_NOTICE, "Mapping openr2 cause %d to unspecified\n", cause);
return FTDM_CAUSE_NORMAL_UNSPECIFIED;
}
@ -329,6 +330,9 @@ static openr2_call_disconnect_cause_t ftdm_r2_ftdm_cause_to_openr2_cause(ftdm_ch
case FTDM_CAUSE_NORMAL_UNSPECIFIED:
return OR2_CAUSE_UNSPECIFIED;
case FTDM_CAUSE_REQUESTED_CHAN_UNAVAIL:
return OR2_CAUSE_GLARE;
}
ftdm_log_chan(fchan, FTDM_LOG_WARNING, "freetdm hangup cause %d mapped to openr2 cause %s\n",
fchan->caller_data.hangup_cause, openr2_proto_get_disconnect_string(OR2_CAUSE_UNSPECIFIED));
@ -345,7 +349,6 @@ static void ft_r2_clean_call(ftdm_r2_call_t *call)
call->accepted = 0;
call->answer_pending = 0;
call->disconnect_rcvd = 0;
call->ftdm_call_started = 0;
call->protocol_error = 0;
call->dnis_index = 0;
call->ani_index = 0;
@ -437,19 +440,12 @@ static __inline openr2_calling_party_category_t ftdm_r2_ftdm_cpc_to_openr2_cpc(f
/* this function must be called with the chan mutex held! */
static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call)
{
openr2_call_status_t callstatus;
int ret;
ftdm_r2_data_t *r2data;
openr2_calling_party_category_t category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
r2data = ftdmchan->span->signal_data;
if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) {
/* collision, an incoming seized the channel between our take and use timing */
ftdm_log_chan(ftdmchan,
FTDM_LOG_CRIT, "R2 cannot dial out in channel in state %s, try another channel!.\n", ftdm_channel_state2str(ftdmchan->state));
return FTDM_FAIL;
}
ft_r2_clean_call(ftdmchan->call_data);
if (ftdmchan->caller_data.cpc == FTDM_CPC_INVALID || ftdmchan->caller_data.cpc == FTDM_CPC_UNKNOWN) {
@ -464,18 +460,17 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call)
ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_OUTPUT_DUMP, &r2data->mf_dump_size);
}
callstatus = openr2_chan_make_call(R2CALL(ftdmchan)->r2chan,
ret = openr2_chan_make_call(R2CALL(ftdmchan)->r2chan,
ftdmchan->caller_data.cid_num.digits,
ftdmchan->caller_data.dnis.digits,
category,
ftdmchan->caller_data.pres == FTDM_PRES_ALLOWED ? 0 : 1);
if (callstatus) {
if (ret) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to make call in R2 channel, openr2_chan_make_call failed\n");
return FTDM_FAIL;
}
R2CALL(ftdmchan)->ftdm_call_started = 1;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DIALING);
ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS);
@ -505,8 +500,16 @@ static ftdm_status_t ftdm_r2_stop(ftdm_span_t *span)
static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_channel_sig_status)
{
openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan;
openr2_cas_signal_t rxcas, txcas;
/* get the current rx and tx cas bits */
openr2_chan_get_cas(r2chan, &rxcas, &txcas);
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
*status = FTDM_SIG_STATE_UP;
} else if (rxcas == OR2_CAS_BLOCK || txcas == OR2_CAS_BLOCK) {
*status = FTDM_SIG_STATE_SUSPENDED;
} else {
*status = FTDM_SIG_STATE_DOWN;
}
@ -567,6 +570,11 @@ static FIO_SPAN_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_span_sig_status)
for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) {
ftdm_channel_t *fchan = ftdm_iterator_current(citer);
ftdm_channel_lock(fchan);
if (ftdm_test_flag(fchan, FTDM_CHANNEL_IN_ALARM)) {
*status = FTDM_SIG_STATE_DOWN;
ftdm_channel_unlock(fchan);
break;
}
if (ftdm_test_flag(fchan, FTDM_CHANNEL_SIG_UP)) {
*status = FTDM_SIG_STATE_UP;
ftdm_channel_unlock(fchan);
@ -639,9 +647,6 @@ static void ftdm_r2_on_call_init(openr2_chan_t *r2chan)
return;
}
/* mark the channel in use (so no outgoing calls can be placed here) */
ftdm_channel_use(ftdmchan);
memset(ftdmchan->caller_data.dnis.digits, 0, sizeof(ftdmchan->caller_data.collected));
memset(ftdmchan->caller_data.ani.digits, 0, sizeof(ftdmchan->caller_data.collected));
@ -826,8 +831,17 @@ static void ftdm_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf
static void ftdm_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
{
ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Alarm notification: %d\n", alarm);
ftdm_channel_t *fchan = openr2_chan_get_client_data(r2chan);
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Alarm notification %d when in state %s (sigstatus = %d)\n",
alarm, ftdm_channel_state2str(fchan->state), ftdm_test_flag(fchan, FTDM_CHANNEL_SIG_UP) ? 1 : 0);
if (alarm) {
R2CALL(fchan)->localsuspend_on_alarm = ftdm_test_flag(fchan, FTDM_CHANNEL_SUSPENDED) ? 1 : 0;
if (ftdm_test_flag(fchan, FTDM_CHANNEL_SIG_UP) || ftdm_test_flag(fchan, FTDM_CHANNEL_SUSPENDED)) {
ftdm_r2_set_chan_sig_status(fchan, FTDM_SIG_STATE_DOWN);
}
}
}
static void ftdm_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
@ -881,14 +895,31 @@ static void ftdm_r2_on_line_blocked(openr2_chan_t *r2chan)
{
ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Far end blocked in state %s\n", ftdm_channel_state2str(ftdmchan->state));
ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_SUSPENDED);
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)
|| !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) {
ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_SUSPENDED);
}
}
static void ftdm_r2_on_line_idle(openr2_chan_t *r2chan)
{
openr2_cas_signal_t rxcas, txcas;
ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
/* get the current rx and tx cas bits */
openr2_chan_get_cas(r2chan, &rxcas, &txcas);
ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Far end unblocked in state %s\n", ftdm_channel_state2str(ftdmchan->state));
ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP);
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)
&& txcas == OR2_CAS_IDLE) {
/* if txcas is not idle, it means we're still blocked as far as the user is concerned, do not send SIGEVENT UP,
* it will be done when the user set the line to IDLE (if the remote is still also IDLE) */
ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP);
} else if (txcas == OR2_CAS_BLOCK && R2CALL(ftdmchan)->localsuspend_on_alarm) {
/* the user requested to block, we do not notify about state up until the user set the bits to IDLE, however
* if we're just getting back from alarmed condition, we notify about suspended again */
ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_SUSPENDED);
}
R2CALL(ftdmchan)->localsuspend_on_alarm = 0;
}
static void ftdm_r2_write_log(openr2_log_level_t level, const char *file, const char *function, int line, const char *message)
@ -920,7 +951,7 @@ static void ftdm_r2_write_log(openr2_log_level_t level, const char *file, const
static void ftdm_r2_on_context_log(openr2_context_t *r2context, const char *file, const char *function, unsigned int line,
openr2_log_level_t level, const char *fmt, va_list ap)
{
#define CONTEXT_TAG "Context -"
#define CONTEXT_TAG "Context - "
char logmsg[256];
char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
@ -1007,8 +1038,19 @@ static void ftdm_r2_on_call_log_created(openr2_chan_t *r2chan, const char *logna
snprintf(r2call->logname, sizeof(r2call->logname), "%s", logname);
}
static void ftdm_r2_on_call_proceed(openr2_chan_t *r2chan)
{
ftdm_sigmsg_t sigev;
ftdm_channel_t *fchan = openr2_chan_get_client_data(r2chan);
memset(&sigev, 0, sizeof(sigev));
sigev.event_id = FTDM_SIGEVENT_PROCEED;
sigev.channel = fchan;
ftdm_span_send_signal(fchan->span, &sigev);
}
static openr2_event_interface_t ftdm_r2_event_iface = {
/* .on_call_init */ ftdm_r2_on_call_init,
/* .on_call_proceed */ ftdm_r2_on_call_proceed,
/* .on_call_offered */ ftdm_r2_on_call_offered,
/* .on_call_accepted */ ftdm_r2_on_call_accepted,
/* .on_call_answered */ ftdm_r2_on_call_answered,
@ -1186,6 +1228,14 @@ static int ftdm_r2_io_get_oob_event(openr2_chan_t *r2chan, openr2_oob_event_t *e
return 0;
}
static int ftdm_r2_io_get_alarm_state(openr2_chan_t *r2chan, int *alarm)
{
ftdm_channel_t *fchan = openr2_chan_get_fd(r2chan);
ftdm_assert_return(alarm, -1, "Alarm pointer is null\n");
*alarm = ftdm_test_flag(fchan, FTDM_CHANNEL_IN_ALARM) ? 1 : 0;
return 0;
}
static openr2_io_interface_t ftdm_r2_io_iface = {
/* .open */ ftdm_r2_io_open, /* never called */
/* .close */ ftdm_r2_io_close, /* never called */
@ -1196,7 +1246,8 @@ static openr2_io_interface_t ftdm_r2_io_iface = {
/* .read */ ftdm_r2_io_read,
/* .setup */ ftdm_r2_io_setup, /* never called */
/* .wait */ ftdm_r2_io_wait,
/* .get_oob_event */ ftdm_r2_io_get_oob_event /* never called */
/* .get_oob_event */ ftdm_r2_io_get_oob_event,
/* .get_alarm_state */ ftdm_r2_io_get_alarm_state
};
/* resolve a loglevel string, such as "debug,notice,warning", to an openr2 log level integer */
@ -1691,8 +1742,7 @@ static ftdm_status_t ftdm_r2_state_advance(ftdm_channel_t *ftdmchan)
uint32_t interval = 0;
ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_INTERVAL, &interval);
ftdm_assert(interval != 0, "Invalid interval!");
ftdm_log_chan(ftdmchan,
FTDM_LOG_DEBUG, "Starting processing of outgoing call in channel with interval %d\n", interval);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Starting outgoing call with interval %d\n", interval);
openr2_chan_enable_read(r2chan);
}
break;
@ -1702,10 +1752,7 @@ static ftdm_status_t ftdm_r2_state_advance(ftdm_channel_t *ftdmchan)
/* notify the user about the new call */
sigev.event_id = FTDM_SIGEVENT_START;
ftdm_span_send_signal(ftdmchan->span, &sigev);
r2call->ftdm_call_started = 1;
break;
/* the call is making progress */
@ -1719,9 +1766,6 @@ static ftdm_status_t ftdm_r2_state_advance(ftdm_channel_t *ftdmchan)
}
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Notifying progress\n");
sigev.event_id = FTDM_SIGEVENT_PROCEED;
ftdm_span_send_signal(ftdmchan->span, &sigev);
sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA;
ftdm_span_send_signal(ftdmchan->span, &sigev);
}
@ -1772,7 +1816,7 @@ static ftdm_status_t ftdm_r2_state_advance(ftdm_channel_t *ftdmchan)
case FTDM_CHANNEL_STATE_TERMINATING:
{
/* if the call has not been started yet we must go to HANGUP right here */
if (!r2call->ftdm_call_started) {
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED)) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
} else {
openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan);
@ -2001,9 +2045,6 @@ static void __inline__ block_channel(ftdm_channel_t *fchan, ftdm_stream_handle_t
if (fchan->state != FTDM_CHANNEL_STATE_DOWN) {
stream->write_function(stream, "cannot block channel %d:%d because has a call in progress\n",
fchan->span_id, fchan->chan_id);
} else if (ftdm_test_flag(fchan, FTDM_CHANNEL_SUSPENDED)) {
stream->write_function(stream, "cannot block channel %d:%d because is already blocked\n",
fchan->span_id, fchan->chan_id);
} else {
if (!openr2_chan_set_blocked(r2chan)) {
ftdm_set_flag(fchan, FTDM_CHANNEL_SUSPENDED);
@ -2021,17 +2062,12 @@ static void __inline__ unblock_channel(ftdm_channel_t *fchan, ftdm_stream_handle
{
openr2_chan_t *r2chan = R2CALL(fchan)->r2chan;
ftdm_mutex_lock(fchan->mutex);
if (ftdm_test_flag(fchan, FTDM_CHANNEL_SUSPENDED)) {
if (!openr2_chan_set_idle(r2chan)) {
ftdm_clear_flag(fchan, FTDM_CHANNEL_SUSPENDED);
stream->write_function(stream, "unblocked channel %d:%d\n",
fchan->span_id, fchan->chan_id);
} else {
stream->write_function(stream, "failed to unblock channel %d:%d\n",
fchan->span_id, fchan->chan_id);
}
if (!openr2_chan_set_idle(r2chan)) {
ftdm_clear_flag(fchan, FTDM_CHANNEL_SUSPENDED);
stream->write_function(stream, "unblocked channel %d:%d\n",
fchan->span_id, fchan->chan_id);
} else {
stream->write_function(stream, "cannot unblock channel %d:%d because is not blocked\n",
stream->write_function(stream, "failed to unblock channel %d:%d\n",
fchan->span_id, fchan->chan_id);
}
ftdm_mutex_unlock(fchan->mutex);

@ -120,7 +120,7 @@ ftdm_state_map_t sangoma_isdn_state_map = {
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_RING, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_END}
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}
},
{
ZSD_INBOUND,
@ -139,7 +139,7 @@ ftdm_state_map_t sangoma_isdn_state_map = {
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
},
{
ZSD_INBOUND,
@ -234,7 +234,7 @@ ftdm_state_map_t sangoma_isdn_state_map = {
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_RINGING, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
},
{
ZSD_OUTBOUND,
@ -788,21 +788,21 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm
/* set the flag to indicate this hangup is started from the local side */
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_REL);
/* If we never sent ack to incoming call, we need to send release instead of disconnect */
if (ftdmchan->last_state == FTDM_CHANNEL_STATE_RING ||
ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALING) {
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
sngisdn_snd_release(ftdmchan, 0);
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
sngisdn_set_span_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
}
} else {
sngisdn_snd_disconnect(ftdmchan);
switch(ftdmchan->last_state) {
case FTDM_CHANNEL_STATE_RING:
/* If we never sent PROCEED/ALERT/PROGRESS/CONNECT on an incoming call, we need to send release instead of disconnect */
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
sngisdn_snd_release(ftdmchan, 0);
break;
case FTDM_CHANNEL_STATE_DIALING:
/* If we never received a PROCEED/ALERT/PROGRESS/CONNECT on an outgoing call, we need to send release instead of disconnect */
sngisdn_snd_release(ftdmchan, 0);
break;
default:
sngisdn_snd_disconnect(ftdmchan);
break;
}
}
/* now go to the HANGUP complete state */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
}
@ -884,6 +884,7 @@ static FIO_CHANNEL_SEND_MSG_FUNCTION(ftdm_sangoma_isdn_send_msg)
switch (sigmsg->event_id) {
case FTDM_SIGEVENT_FACILITY:
sngisdn_snd_fac_req(ftdmchan);
status = FTDM_SUCCESS;
break;
default:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Unsupported signalling msg requested\n");
@ -931,7 +932,6 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_isdn_outgoing_call)
ftdm_channel_unlock(ftdmchan);
return status;
}
static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_get_chan_sig_status)
{
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
@ -1094,6 +1094,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE);
ftdm_set_flag(span, FTDM_SPAN_USE_PROCEED_STATE);
ftdm_set_flag(span, FTDM_SPAN_USE_SKIP_STATES);
ftdm_set_flag(span, FTDM_SPAN_NON_STOPPABLE);
if (span->trunk_type == FTDM_TRUNK_BRI_PTMP ||
span->trunk_type == FTDM_TRUNK_BRI) {

@ -47,11 +47,12 @@
#include <ctype.h>
#include "private/ftdm_core.h"
#include "ftmod_sangoma_isdn_user.h"
#include <sng_isdn.h>
/* Theoretical limit for MAX_SPANS_PER_NFAS_LINK is 31,
but set to 8 for now to save some memor */
but set to 8 for now to save some memory */
#define MAX_SPANS_PER_NFAS_LINK 8
#define NUM_E1_CHANNELS_PER_SPAN 32
@ -64,33 +65,6 @@
/* TODO: rename all *_cc_* to *_an_* */
#define SNGISDN_ENUM_NAMES(_NAME, _STRINGS) static const char * _NAME [] = { _STRINGS , NULL };
#define SNGISDN_STR2ENUM_P(_FUNC1, _FUNC2, _TYPE) _TYPE _FUNC1 (const char *name); const char * _FUNC2 (_TYPE type);
#define SNGISDN_STR2ENUM(_FUNC1, _FUNC2, _TYPE, _STRINGS, _MAX) \
_TYPE _FUNC1 (const char *name) \
{ \
int i; \
_TYPE t = _MAX ; \
\
for (i = 0; i < _MAX ; i++) { \
if (!strcasecmp(name, _STRINGS[i])) { \
t = (_TYPE) i; \
break; \
} \
} \
\
return t; \
} \
const char * _FUNC2 (_TYPE type) \
{ \
if (type > _MAX) { \
type = _MAX; \
} \
return _STRINGS[(int)type]; \
} \
typedef enum {
FLAG_RESET_RX = (1 << 0),
FLAG_RESET_TX = (1 << 1),
@ -165,46 +139,6 @@ typedef enum {
SNGISDN_EVENT_RST_IND,
} ftdm_sngisdn_event_id_t;
typedef enum {
/* Call is not end-to-end ISDN */
SNGISDN_PROGIND_DESCR_NETE_ISDN,
/* Destination address is non-ISDN */
SNGISDN_PROGIND_DESCR_DEST_NISDN,
/* Origination address is non-ISDN */
SNGISDN_PROGIND_DESCR_ORIG_NISDN,
/* Call has returned to the ISDN */
SNGISDN_PROGIND_DESCR_RET_ISDN,
/* Interworking as occured and has resulted in a telecommunication service change */
SNGISDN_PROGIND_DESCR_SERV_CHANGE,
/* In-band information or an appropriate pattern is now available */
SNGISDN_PROGIND_DESCR_IB_AVAIL,
/* Invalid */
SNGISDN_PROGIND_DESCR_INVALID,
} ftdm_sngisdn_progind_descr_t;
#define SNGISDN_PROGIND_DESCR_STRINGS "not-end-to-end-isdn", "destination-is-non-isdn", "origination-is-non-isdn", "call-returned-to-isdn", "service-change", "inband-info-available", "invalid"
SNGISDN_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr2str, ftdm_sngisdn_progind_descr_t);
typedef enum {
/* User */
SNGISDN_PROGIND_LOC_USER,
/* Private network serving the local user */
SNGISDN_PROGIND_LOC_PRIV_NET_LOCAL_USR,
/* Public network serving the local user */
SNGISDN_PROGIND_LOC_PUB_NET_LOCAL_USR,
/* Transit network */
SNGISDN_PROGIND_LOC_TRANSIT_NET,
/* Public network serving remote user */
SNGISDN_PROGIND_LOC_PUB_NET_REMOTE_USR,
/* Private network serving remote user */
SNGISDN_PROGIND_LOC_PRIV_NET_REMOTE_USR,
/* Network beyond the interworking point */
SNGISDN_PROGIND_LOC_NET_BEYOND_INTRW,
/* Invalid */
SNGISDN_PROGIND_LOC_INVALID,
} ftdm_sngisdn_progind_loc_t;
#define SNGISDN_PROGIND_LOC_STRINGS "user", "private-net-local-user", "public-net-local-user", "transit-network", "public-net-remote-user", "private-net-remote-user", "beyond-interworking", "invalid"
SNGISDN_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t);
typedef struct ftdm_sngisdn_prog_ind {
ftdm_sngisdn_progind_loc_t loc; /* location */
ftdm_sngisdn_progind_descr_t descr; /* description */
@ -233,6 +167,7 @@ typedef struct sngisdn_chan_data {
uint32_t flags;
uint8_t ces; /* used only for BRI, otherwise always 0 */
uint8_t dchan_id;
uint16_t call_ref; /* Q.931 call reference, only valid for ETSI/INSNET/QSIG */
uint32_t suInstId; /* instance ID generated locally */
uint32_t spInstId; /* instance ID generated by stack */
@ -446,6 +381,9 @@ void sngisdn_rcv_cc_ind(CcMngmt *status);
void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...);
void sngisdn_rcv_sng_assert(char *message);
#ifdef NETBORDER_CALL_REF
ftdm_status_t get_callref(ftdm_channel_t *ftdmchan, BCCallRef* callRef);
#endif
ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
ftdm_status_t get_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb);
@ -470,11 +408,10 @@ ftdm_status_t set_restart_ind_ie(ftdm_channel_t *ftdmchan, RstInd *rstInd);
ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr);
ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t *data_len);
uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability);
uint8_t sngisdn_get_usrInfoLyr1Prot_from_stack(ftdm_user_layer1_prot_t layer1_prot);
ftdm_bearer_cap_t sngisdn_get_infoTranCap_from_user(uint8_t bearer_capability);
ftdm_user_layer1_prot_t sngisdn_get_usrInfoLyr1Prot_from_user(uint8_t layer1_prot);
uint8_t sngisdn_get_infoTranCap_from_user(ftdm_bearer_cap_t bearer_capability);
uint8_t sngisdn_get_usrInfoLyr1Prot_from_user(ftdm_user_layer1_prot_t layer1_prot);
ftdm_bearer_cap_t sngisdn_get_infoTranCap_from_stack(uint8_t bearer_capability);
ftdm_user_layer1_prot_t sngisdn_get_usrInfoLyr1Prot_from_stack(uint8_t layer1_prot);
static __inline__ uint32_t sngisdn_test_flag(sngisdn_chan_data_t *sngisdn_info, sngisdn_flag_t flag)
{
@ -515,3 +452,15 @@ void sngisdn_print_span(ftdm_stream_handle_t *stream, ftdm_span_t *span);
#endif /* __FTMOD_SNG_ISDN_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:
*/
/******************************************************************************/

@ -38,6 +38,7 @@ static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span
static ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span);
static ftdm_status_t add_local_number(const char* val, ftdm_span_t *span);
static ftdm_status_t parse_yesno(const char* var, const char* val, uint8_t *target);
static ftdm_status_t set_switchtype_defaults(ftdm_span_t *span);
extern ftdm_sngisdn_data_t g_sngisdn_data;
@ -149,7 +150,7 @@ static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span
g_sngisdn_data.spans[signal_data->link_id] = signal_data;
ftdm_log(FTDM_LOG_DEBUG, "%s: cc_id:%d dchan_id:%d span_id:%d\n", span->name, signal_data->cc_id, signal_data->dchan_id, signal_data->span_id);
ftdm_log(FTDM_LOG_DEBUG, "%s: cc_id:%d dchan_id:%d span_id:%d link_id:%d\n", span->name, signal_data->cc_id, signal_data->dchan_id, signal_data->span_id, signal_data->link_id);
chaniter = ftdm_span_get_chan_iterator(span, NULL);
@ -191,6 +192,63 @@ static ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span)
return FTDM_SUCCESS;
}
static ftdm_status_t set_switchtype_defaults(ftdm_span_t *span)
{
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
switch(signal_data->switchtype) {
case SNGISDN_SWITCH_NI2:
case SNGISDN_SWITCH_5ESS:
case SNGISDN_SWITCH_4ESS:
case SNGISDN_SWITCH_DMS100:
if (span->default_caller_data.dnis.plan >= FTDM_NPI_INVALID) {
ftdm_set_npi("isdn", &span->default_caller_data.dnis.plan);
}
if (span->default_caller_data.dnis.type >= FTDM_TON_INVALID) {
ftdm_set_ton("national", &span->default_caller_data.dnis.type);
}
if (span->default_caller_data.cid_num.plan >= FTDM_NPI_INVALID) {
ftdm_set_npi("isdn", &span->default_caller_data.cid_num.plan);
}
if (span->default_caller_data.cid_num.type >= FTDM_TON_INVALID) {
ftdm_set_ton("national", &span->default_caller_data.cid_num.type);
}
if (span->default_caller_data.rdnis.plan >= FTDM_NPI_INVALID) {
ftdm_set_npi("isdn", &span->default_caller_data.rdnis.plan);
}
if (span->default_caller_data.rdnis.type >= FTDM_TON_INVALID) {
ftdm_set_ton("national", &span->default_caller_data.rdnis.type);
}
break;
case SNGISDN_SWITCH_EUROISDN:
case SNGISDN_SWITCH_QSIG:
case SNGISDN_SWITCH_INSNET:
if (span->default_caller_data.dnis.plan >= FTDM_NPI_INVALID) {
ftdm_set_npi("unknown", &span->default_caller_data.dnis.plan);
}
if (span->default_caller_data.dnis.type >= FTDM_TON_INVALID) {
ftdm_set_ton("unknown", &span->default_caller_data.dnis.type);
}
if (span->default_caller_data.cid_num.plan >= FTDM_NPI_INVALID) {
ftdm_set_npi("unknown", &span->default_caller_data.cid_num.plan);
}
if (span->default_caller_data.cid_num.type >= FTDM_TON_INVALID) {
ftdm_set_ton("unknown", &span->default_caller_data.cid_num.type);
}
if (span->default_caller_data.rdnis.plan >= FTDM_NPI_INVALID) {
ftdm_set_npi("unknown", &span->default_caller_data.rdnis.plan);
}
if (span->default_caller_data.rdnis.type >= FTDM_TON_INVALID) {
ftdm_set_ton("unknown", &span->default_caller_data.rdnis.type);
}
break;
case SNGISDN_SWITCH_INVALID:
default:
ftdm_log(FTDM_LOG_ERROR, "Unsupported switchtype[%d]\n", signal_data->switchtype);
return FTDM_FAIL;
}
return FTDM_SUCCESS;
}
ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *span)
{
unsigned paramindex;
@ -205,31 +263,19 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
signal_data->ignore_cause_value = SNGISDN_OPT_DEFAULT;
signal_data->timer_t3 = 8;
signal_data->restart_opt = SNGISDN_OPT_DEFAULT;
signal_data->link_id = span->span_id;
span->default_caller_data.bearer_capability = IN_ITC_SPEECH;
span->default_caller_data.dnis.plan = FTDM_NPI_INVALID;
span->default_caller_data.dnis.type = FTDM_TON_INVALID;
span->default_caller_data.cid_num.plan = FTDM_NPI_INVALID;
span->default_caller_data.cid_num.type = FTDM_TON_INVALID;
span->default_caller_data.rdnis.plan = FTDM_NPI_INVALID;
span->default_caller_data.rdnis.type = FTDM_TON_INVALID;
span->default_caller_data.bearer_capability = IN_ITC_SPEECH;
/* Cannot set default bearer_layer1 yet, as we do not know the switchtype */
span->default_caller_data.bearer_layer1 = FTDM_INVALID_INT_PARM;
if (span->trunk_type == FTDM_TRUNK_BRI ||
span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
ftdm_set_npi("unknown", &span->default_caller_data.dnis.plan);
ftdm_set_ton("unknown", &span->default_caller_data.dnis.type);
ftdm_set_npi("unknown", &span->default_caller_data.cid_num.plan);
ftdm_set_ton("unknown", &span->default_caller_data.cid_num.type);
ftdm_set_npi("unknown", &span->default_caller_data.rdnis.plan);
ftdm_set_ton("unknown", &span->default_caller_data.rdnis.type);
} else {
ftdm_set_npi("isdn", &span->default_caller_data.dnis.plan);
ftdm_set_ton("national", &span->default_caller_data.dnis.type);
ftdm_set_npi("isdn", &span->default_caller_data.cid_num.plan);
ftdm_set_ton("national", &span->default_caller_data.cid_num.type);
ftdm_set_npi("isdn", &span->default_caller_data.rdnis.plan);
ftdm_set_ton("national", &span->default_caller_data.rdnis.type);
}
for (paramindex = 0; ftdm_parameters[paramindex].var; paramindex++) {
ftdm_log(FTDM_LOG_DEBUG, "Sangoma ISDN key=value, %s=%s\n", ftdm_parameters[paramindex].var, ftdm_parameters[paramindex].val);
var = ftdm_parameters[paramindex].var;
@ -239,6 +285,9 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
if (parse_switchtype(val, span) != FTDM_SUCCESS) {
return FTDM_FAIL;
}
if (set_switchtype_defaults(span) != FTDM_SUCCESS) {
return FTDM_FAIL;
}
} else if (!strcasecmp(var, "signalling") ||
!strcasecmp(var, "interface")) {
if (parse_signalling(val, span) != FTDM_SUCCESS) {
@ -277,9 +326,11 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
ftdm_set_ton(val, &span->default_caller_data.rdnis.type);
} else if (!strcasecmp(var, "outbound-rdnis-npi")) {
ftdm_set_npi(val, &span->default_caller_data.rdnis.plan);
} else if (!strcasecmp(var, "outbound-bearer_cap")) {
} else if (!strcasecmp(var, "outbound-bearer_cap") ||
!strcasecmp(var, "outbound-bc-transfer-cap")) {
ftdm_set_bearer_capability(val, (uint8_t*)&span->default_caller_data.bearer_capability);
} else if (!strcasecmp(var, "outbound-bearer_layer1")) {
} else if (!strcasecmp(var, "outbound-bearer_layer1") ||
!strcasecmp(var, "outbound-bc-user-layer1")) {
ftdm_set_bearer_layer1(val, (uint8_t*)&span->default_caller_data.bearer_layer1);
} else if (!strcasecmp(var, "channel-restart-on-link-up")) {
parse_yesno(var, val, &signal_data->restart_opt);

@ -216,7 +216,7 @@ ftdm_status_t sngisdn_stack_cfg_phy_psap(ftdm_span_t *span)
cfg.hdr.entId.inst = S_INST;
cfg.hdr.elmId.elmnt = STPSAP;
cfg.hdr.elmId.elmntInst1 = signal_data->link_id;
cfg.hdr.elmId.elmntInst1 = signal_data->dchan_id;
if (!signal_data->dchan) {
ftdm_log(FTDM_LOG_ERROR, "%s:No d-channels specified\n", span->name);
@ -241,7 +241,8 @@ ftdm_status_t sngisdn_stack_cfg_phy_psap(ftdm_span_t *span)
ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported trunk type %d\n", span->name, span->trunk_type);
return FTDM_FAIL;
}
cfg.t.cfg.s.l1PSAP.spId = signal_data->link_id;
cfg.t.cfg.s.l1PSAP.spId = signal_data->dchan_id;
if (sng_isdn_phy_config(&pst, &cfg)) {
return FTDM_FAIL;
@ -315,7 +316,7 @@ ftdm_status_t sngisdn_stack_cfg_q921_msap(ftdm_span_t *span)
cfg.hdr.entId.inst = S_INST;
cfg.hdr.elmId.elmnt = STMSAP;
cfg.t.cfg.s.bdMSAP.lnkNmb = signal_data->link_id;
cfg.t.cfg.s.bdMSAP.lnkNmb = signal_data->dchan_id;
cfg.t.cfg.s.bdMSAP.maxOutsFrms = 24; /* MAC window */
cfg.t.cfg.s.bdMSAP.tQUpperTrs = 32; /* Tx Queue Upper Threshold */
@ -408,7 +409,7 @@ ftdm_status_t sngisdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t management
cfg.hdr.entId.inst = S_INST;
cfg.hdr.elmId.elmnt = STDLSAP;
cfg.t.cfg.s.bdDLSAP.lnkNmb = signal_data->link_id;
cfg.t.cfg.s.bdDLSAP.lnkNmb = signal_data->dchan_id;
cfg.t.cfg.s.bdDLSAP.n201 = 1028; /* n201 */
if (span->trunk_type == FTDM_TRUNK_BRI_PTMP ||
@ -613,9 +614,9 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
cfg.hdr.response.selector=0;
cfg.t.cfg.s.inDLSAP.sapId = signal_data->dchan_id;
cfg.t.cfg.s.inDLSAP.spId = signal_data->dchan_id;
cfg.t.cfg.s.inDLSAP.sapId = signal_data->link_id;
cfg.t.cfg.s.inDLSAP.spId = signal_data->link_id;
cfg.t.cfg.s.inDLSAP.swtch = sng_isdn_stack_switchtype(signal_data->switchtype);
cfg.t.cfg.s.inDLSAP.n201 = 1024;
@ -876,8 +877,7 @@ ftdm_status_t sngisdn_stack_cfg_q931_lce(ftdm_span_t *span)
cfg.hdr.response.selector=0;
cfg.t.cfg.s.inLCe.sapId = signal_data->link_id;
cfg.t.cfg.s.inLCe.sapId = signal_data->dchan_id;
cfg.t.cfg.s.inLCe.lnkUpDwnInd = TRUE;
cfg.t.cfg.s.inLCe.tCon.enb = TRUE;

@ -146,7 +146,8 @@ ftdm_status_t sngisdn_deactivate_phy(ftdm_span_t *span)
cntrl.t.cntrl.action = AUBND_DIS;
cntrl.t.cntrl.subAction = SAELMNT;
cntrl.t.cntrl.sapId = signal_data->link_id;
cntrl.t.cntrl.sapId = signal_data->dchan_id;
if (sng_isdn_phy_cntrl(&pst, &cntrl)) {
return FTDM_FAIL;
@ -180,7 +181,8 @@ ftdm_status_t sngisdn_wake_up_phy(ftdm_span_t *span)
cntrl.t.cntrl.action = AENA;
cntrl.t.cntrl.subAction = SAELMNT;
cntrl.t.cntrl.sapId = signal_data->link_id;
cntrl.t.cntrl.sapId = signal_data->dchan_id;
if (sng_isdn_phy_cntrl(&pst, &cntrl)) {
return FTDM_FAIL;
@ -298,7 +300,8 @@ ftdm_status_t sngisdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t suba
if (action == AENA && subaction == SATRC) {
cntrl.t.cntrl.trcLen = -1; /* Trace the entire message buffer */
}
cntrl.t.cntrl.sapId = signal_data->link_id;
cntrl.t.cntrl.sapId = signal_data->dchan_id;
cntrl.t.cntrl.ces = 0;
if(sng_isdn_q931_cntrl(&pst, &cntrl)) {
@ -339,11 +342,11 @@ ftdm_status_t sngisdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t suba
cntrl.t.cntrl.subAction = subaction;
#if (SMBD_LMINT3 || BD_LMINT3)
cntrl.t.cntrl.lnkNmb = signal_data->link_id;
cntrl.t.cntrl.lnkNmb = signal_data->dchan_id;
cntrl.t.cntrl.sapi = NOTUSED;
cntrl.t.cntrl.tei = NOTUSED;
#else /* _LMINT3 */
cntrl.hdr.elmId.elmntInst1 = signal_data->link_id;
cntrl.hdr.elmId.elmntInst1 = signal_data->dchan_id;
cntrl.hdr.elmId.elmntInst2 = NOTUSED;
cntrl.hdr.elmId.elmntInst3 = NOTUSED;
#endif /* _LMINT3 */

@ -71,13 +71,12 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
sngisdn_info->glare.suInstId = suInstId; /* Do not generate a suInstId now, we will generate when glared call gets extracted */
sngisdn_info->glare.spInstId = spInstId;
sngisdn_info->glare.dChan = dChan;
sngisdn_info->glare.ces = ces;
sngisdn_info->glare.ces = ces;
break;
}
sngisdn_info->suInstId = get_unique_suInstId(suId);
sngisdn_info->spInstId = spInstId;
if (conEvnt->cdPtyNmb.eh.pres && signal_data->num_local_numbers) {
uint8_t local_number_matched = 0;
@ -125,30 +124,39 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
}
/* Fill in call information */
#ifdef NETBORDER_CALL_REF
get_callref(ftdmchan, &conEvnt->callRef);
#endif
get_calling_num(ftdmchan, &conEvnt->cgPtyNmb);
get_calling_num2(ftdmchan, &conEvnt->cgPtyNmb2);
get_called_num(ftdmchan, &conEvnt->cdPtyNmb);
get_redir_num(ftdmchan, &conEvnt->redirNmb);
get_calling_subaddr(ftdmchan, &conEvnt->cgPtySad);
get_prog_ind_ie(ftdmchan, &conEvnt->progInd);
get_facility_ie(ftdmchan, &conEvnt->facilityStr);
get_facility_ie(ftdmchan, &conEvnt->facilityStr);
if (get_calling_name_from_display(ftdmchan, &conEvnt->display) != FTDM_SUCCESS) {
get_calling_name_from_usr_usr(ftdmchan, &conEvnt->usrUsr);
}
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Incoming call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits);
if (conEvnt->bearCap[0].eh.pres) {
ftdmchan->caller_data.bearer_layer1 = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].usrInfoLyr1Prot.val);
ftdmchan->caller_data.bearer_layer1 = sngisdn_get_usrInfoLyr1Prot_from_stack(conEvnt->bearCap[0].usrInfoLyr1Prot.val);
ftdmchan->caller_data.bearer_capability = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].infoTranCap.val);
}
if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) {
if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) {
snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]);
uint8_t encoding = (conEvnt->ni2OctStr.str.val[2] >> 5);
if (encoding == 0 || encoding == 1) {
/* BCD even or BCD odd */
uint8_t value = (conEvnt->ni2OctStr.str.val[3] & 0x0F)*10 + ((conEvnt->ni2OctStr.str.val[3] >> 4) & 0x0F);
snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", value);
} else if (encoding == 2) {
/* IA 5 */
snprintf(ftdmchan->caller_data.aniII, 5, "%c", conEvnt->ni2OctStr.str.val[3]);
}
}
}
@ -282,6 +290,9 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_DIALING:
#ifdef NETBORDER_CALL_REF
get_callref(ftdmchan, &cnStEvnt->callRef);
#endif
get_prog_ind_ie(ftdmchan, &cnStEvnt->progInd);
get_facility_ie(ftdmchan, &cnStEvnt->facilityStr);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP);
@ -354,6 +365,9 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
case MI_CALLPROC:
case MI_PROGRESS:
case MI_ALERTING:
#ifdef NETBORDER_CALL_REF
get_callref(ftdmchan, &cnStEvnt->callRef);
#endif
get_prog_ind_ie(ftdmchan, &cnStEvnt->progInd);
get_facility_ie(ftdmchan, &cnStEvnt->facilityStr);
@ -372,7 +386,10 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_RINGING:
if (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Early media available\n");
sngisdn_set_flag(sngisdn_info, FLAG_MEDIA_READY);
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Early media not available\n");
}
switch (evntType) {
case MI_CALLPROC:
@ -387,10 +404,8 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
break;
case MI_PROGRESS:
if (sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY)) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
} else if (ftdmchan->state != FTDM_CHANNEL_STATE_PROGRESS) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
}
break;
@ -590,7 +605,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "cause:%d\n", ftdmchan->caller_data.hangup_cause);
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "RELEASE COMPLETE did not have a cause code\n");
ftdmchan->caller_data.hangup_cause = 0;
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_REQUESTED_CHAN_UNAVAIL;
}
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);

@ -39,7 +39,7 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
ConEvnt conEvnt;
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID};
ftdm_assert((!sngisdn_info->suInstId && !sngisdn_info->spInstId), "Trying to call out, but call data was not cleared\n");
@ -261,7 +261,7 @@ void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan)
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
if (!sngisdn_info->suInstId) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending FACILITY, but no call data, ignoring (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
return;
}
@ -491,8 +491,8 @@ void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len)
/* Should we trigger congestion here? */
l1_frame.flags |= SNG_L1FRAME_QUEUE_FULL;
}
sng_isdn_data_ind(signal_data->link_id, &l1_frame);
sng_isdn_data_ind(signal_data->dchan_id, &l1_frame);
}
void sngisdn_snd_event(ftdm_channel_t *dchan, ftdm_oob_event_t event)
@ -506,11 +506,11 @@ void sngisdn_snd_event(ftdm_channel_t *dchan, ftdm_oob_event_t event)
switch(event) {
case FTDM_OOB_ALARM_CLEAR:
l1_event.type = SNG_L1EVENT_ALARM_OFF;
sng_isdn_event_ind(signal_data->link_id, &l1_event);
sng_isdn_event_ind(signal_data->dchan_id, &l1_event);
break;
case FTDM_OOB_ALARM_TRAP:
l1_event.type = SNG_L1EVENT_ALARM_ON;
sng_isdn_event_ind(signal_data->link_id, &l1_event);
sng_isdn_event_ind(signal_data->dchan_id, &l1_event);
break;
default:
/* We do not care about the other OOB events for now */

@ -662,7 +662,9 @@ void sngisdn_rcv_phy_ind(SuId suId, Reason reason)
void sngisdn_rcv_q921_ind(BdMngmt *status)
{
ftdm_span_t *ftdmspan;
sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[status->t.usta.lnkNmb];
sngisdn_span_data_t *signal_data = g_sngisdn_data.dchans[status->t.usta.lnkNmb].spans[1];
if (!signal_data) {
ftdm_log(FTDM_LOG_INFO, "Received q921 status on unconfigured span (lnkNmb:%d)\n", status->t.usta.lnkNmb);
return;
@ -715,7 +717,7 @@ void sngisdn_rcv_q931_ind(InMngmt *status)
case LCM_EVENT_DOWN:
{
ftdm_span_t *ftdmspan;
sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[status->t.usta.suId];
sngisdn_span_data_t *signal_data = g_sngisdn_data.dchans[status->t.usta.suId].spans[1];
if (!signal_data) {
ftdm_log(FTDM_LOG_INFO, "Received q931 status on unconfigured span (lnkNmb:%d)\n", status->t.usta.suId);
return;
@ -784,15 +786,16 @@ void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
uint8_t data;
ftdm_trace_dir_t dir;
uint8_t tdata[1000];
sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[trc->t.trc.suId];
sngisdn_span_data_t *signal_data = g_sngisdn_data.dchans[trc->t.trc.suId].spans[1];
ftdm_assert(mBuf != NULLP, "Received a Q931 trace with no buffer");
mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
if (trc->t.trc.evnt == TL3PKTTX) {
dir = FTDM_TRACE_OUTGOING;
dir = FTDM_TRACE_DIR_OUTGOING;
} else {
dir = FTDM_TRACE_INCOMING;
dir = FTDM_TRACE_DIR_INCOMING;
}
if (mlen) {
@ -830,16 +833,17 @@ void sngisdn_rcv_q921_trace(BdMngmt *trc, Buffer *mBuf)
uint8_t data;
ftdm_trace_dir_t dir;
uint8_t tdata[1000];
sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[trc->t.trc.lnkNmb];
sngisdn_span_data_t *signal_data = g_sngisdn_data.dchans[trc->t.trc.lnkNmb].spans[1];
if (trc->t.trc.evnt == TL2TMR) {
return;
}
if (trc->t.trc.evnt == TL2FRMTX) {
dir = FTDM_TRACE_OUTGOING;
dir = FTDM_TRACE_DIR_OUTGOING;
} else {
dir = FTDM_TRACE_INCOMING;
dir = FTDM_TRACE_DIR_INCOMING;
}
ftdm_assert(mBuf != NULLP, "Received a Q921 trace with no buffer");
@ -879,7 +883,7 @@ int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_l1_frame_t *l1_frame)
{
ftdm_status_t status;
ftdm_wait_flag_t flags = FTDM_WRITE;
sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[spId];
sngisdn_span_data_t *signal_data = g_sngisdn_data.dchans[spId].spans[1];
ftdm_size_t length = l1_frame->len;
ftdm_assert(signal_data, "Received Data request on unconfigured span\n");
@ -912,8 +916,8 @@ int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_l1_frame_t *l1_frame)
}
int16_t sngisdn_rcv_l1_cmd_req(uint16_t spId, sng_l1_cmd_t *l1_cmd)
{
sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[spId];
{
sngisdn_span_data_t *signal_data = g_sngisdn_data.dchans[spId].spans[1];
ftdm_assert(signal_data, "Received Data request on unconfigured span\n");
switch(l1_cmd->type) {

@ -161,6 +161,32 @@ ftdm_status_t sngisdn_set_span_avail_rate(ftdm_span_t *span, sngisdn_avail_t ava
return FTDM_SUCCESS;
}
#ifdef NETBORDER_CALL_REF
ftdm_status_t get_callref(ftdm_channel_t *ftdmchan, BCCallRef* callRef)
{
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
if (signal_data->raw_trace_q931) {
if (callRef->eh.pres != PRSNT_NODEF || callRef->reference.pres != PRSNT_NODEF) {
/* Netborder only supports BRI, so we only care for BRI for now */
if (FTDM_SPAN_IS_BRI(ftdmchan->span) && !sngisdn_info->call_ref) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to obtain call reference\n");
}
return FTDM_FAIL;
}
if (FTDM_SPAN_IS_BRI(ftdmchan->span)) {
sngisdn_info->call_ref = 0x7F & callRef->reference.val;
} else {
sngisdn_info->call_ref = 0x7FFF & callRef->reference.val;
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Call reference:%04x\n", sngisdn_info->call_ref);
}
return FTDM_SUCCESS;
}
#endif
ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
@ -697,7 +723,6 @@ ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8
{
int len;
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
if (caller_data->raw_data_len > 0 && caller_data->raw_data[0] == SNGISDN_Q931_FACILITY_IE_ID) {
len = caller_data->raw_data[1];
memcpy(data, &caller_data->raw_data[2], len);
@ -789,7 +814,7 @@ ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_s
break;
default:
ftdm_log(FTDM_LOG_WARNING, "Invalid prog_ind location:%d\n", loc);
progInd->location.val = IN_PD_NOTETEISDN;
progInd->location.val = IN_LOC_USER;
}
return FTDM_SUCCESS;
}
@ -1033,7 +1058,7 @@ void get_memory_info(void)
return;
}
uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability)
uint8_t sngisdn_get_infoTranCap_from_user(ftdm_bearer_cap_t bearer_capability)
{
switch(bearer_capability) {
case FTDM_BEARER_CAP_SPEECH:
@ -1049,7 +1074,7 @@ uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability)
return FTDM_BEARER_CAP_SPEECH;
}
uint8_t sngisdn_get_usrInfoLyr1Prot_from_stack(ftdm_user_layer1_prot_t layer1_prot)
uint8_t sngisdn_get_usrInfoLyr1Prot_from_user(ftdm_user_layer1_prot_t layer1_prot)
{
switch(layer1_prot) {
case FTDM_USER_LAYER1_PROT_V110:
@ -1065,25 +1090,22 @@ uint8_t sngisdn_get_usrInfoLyr1Prot_from_stack(ftdm_user_layer1_prot_t layer1_pr
return IN_UIL1_G711ULAW;
}
ftdm_bearer_cap_t sngisdn_get_infoTranCap_from_user(uint8_t bearer_capability)
ftdm_bearer_cap_t sngisdn_get_infoTranCap_from_stack(uint8_t bearer_capability)
{
switch(bearer_capability) {
case IN_ITC_SPEECH:
return FTDM_BEARER_CAP_SPEECH;
return FTDM_BEARER_CAP_SPEECH;
case IN_ITC_UNRDIG:
return FTDM_BEARER_CAP_64K_UNRESTRICTED;
return FTDM_BEARER_CAP_64K_UNRESTRICTED;
case IN_ITC_A31KHZ:
return FTDM_BEARER_CAP_3_1KHZ_AUDIO;
default:
return FTDM_BEARER_CAP_SPEECH;
}
return FTDM_BEARER_CAP_SPEECH;
}
ftdm_user_layer1_prot_t sngisdn_get_usrInfoLyr1Prot_from_user(uint8_t layer1_prot)
ftdm_user_layer1_prot_t sngisdn_get_usrInfoLyr1Prot_from_stack(uint8_t layer1_prot)
{
switch(layer1_prot) {
case IN_UIL1_CCITTV110:

@ -38,14 +38,26 @@
#define OCTET(x) (ieData[x-1] & 0xFF)
#define MAX_DECODE_STR_LEN 2000
typedef struct sngisdn_trace_info
{
uint8_t call_ref_flag;
uint16_t call_ref;
uint8_t msgtype;
uint8_t bchan_no;
ftdm_trace_dir_t dir;
} sngisdn_frame_info_t;
void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_start, uint32_t index_end);
uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset, uint8_t *data, uint16_t index_start);
static ftdm_status_t sngisdn_map_call(sngisdn_span_data_t *signal_data, sngisdn_frame_info_t frame_info, ftdm_channel_t **found);
static ftdm_status_t sngisdn_get_frame_info(uint8_t *data, uint32_t data_len, ftdm_trace_dir_t dir, sngisdn_frame_info_t *frame_info);
uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi);
char* get_code_2_str(int code, struct code2str *pCodeTable);
void sngisdn_decode_q921(char* str, uint8_t* data, uint32_t data_len);
void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len);
char* get_code_2_str(int code, struct code2str *pCodeTable)
{
struct code2str* pCode2txt;
@ -118,11 +130,8 @@ void sngisdn_trace_raw_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t d
sigev.channel = signal_data->dchan;
sigev.event_id = FTDM_SIGEVENT_TRACE_RAW;
sigev.ev_data.logevent.dir = dir;
sigev.ev_data.logevent.level = 2;
/* TODO: Map trace to call ID here */
sigev.call_id = 0;
sigev.ev_data.trace.dir = dir;
sigev.ev_data.trace.type = FTDM_TRACE_TYPE_Q921;
raw_data = ftdm_malloc(data_len);
ftdm_assert(raw_data, "Failed to malloc");
@ -219,27 +228,34 @@ void sngisdn_trace_raw_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t d
{
uint8_t *raw_data;
ftdm_sigmsg_t sigev;
ftdm_channel_t *ftdmchan = NULL;
sngisdn_frame_info_t frame_info;
memset(&sigev, 0, sizeof(sigev));
sigev.span_id = signal_data->ftdm_span->span_id;
sigev.chan_id = signal_data->dchan->chan_id;
sigev.channel = signal_data->dchan;
sigev.event_id = FTDM_SIGEVENT_TRACE_RAW;
/* Note: Mapped raw trace assume only exclusive b-channel selection is used. i.e the b-channel selected on outgoing SETUP is always used for the call */
if (sngisdn_get_frame_info(data, data_len, dir, &frame_info) == FTDM_SUCCESS) {
if (sngisdn_map_call(signal_data, frame_info, &ftdmchan) == FTDM_SUCCESS) {
sigev.call_id = ftdmchan->caller_data.call_id;
sigev.span_id = ftdmchan->physical_span_id;
sigev.chan_id = ftdmchan->physical_chan_id;
sigev.channel = ftdmchan;
}
sigev.event_id = FTDM_SIGEVENT_TRACE_RAW;
sigev.ev_data.logevent.dir = dir;
sigev.ev_data.logevent.level = 3;
/* TODO: Map trace to call ID here */
raw_data = ftdm_malloc(data_len);
ftdm_assert(raw_data, "Failed to malloc");
memcpy(raw_data, data, data_len);
sigev.raw.data = raw_data;
sigev.raw.len = data_len;
sigev.raw.autofree = 1;
ftdm_span_send_signal(signal_data->ftdm_span, &sigev);
sigev.ev_data.trace.dir = dir;
sigev.ev_data.trace.type = FTDM_TRACE_TYPE_Q931;
raw_data = ftdm_malloc(data_len);
ftdm_assert(raw_data, "Failed to malloc");
memcpy(raw_data, data, data_len);
sigev.raw.data = raw_data;
sigev.raw.len = data_len;
sigev.raw.autofree = 1;
ftdm_span_send_signal(signal_data->ftdm_span, &sigev);
}
}
void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len)
@ -255,9 +271,6 @@ void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len)
prot_disc = (uint8_t)data[0];
str_len += sprintf(&str[str_len], " Prot Disc:%s (0x%02x)\n", get_code_2_str(prot_disc, dcodQ931ProtDiscTable), prot_disc);
/* Decode Call Reference */
lenCallRef = (uint8_t) (data[1] & 0x0F);
@ -749,4 +762,203 @@ void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_
return;
}
static ftdm_status_t sngisdn_get_frame_info(uint8_t *data, uint32_t data_len, ftdm_trace_dir_t dir, sngisdn_frame_info_t *target)
{
uint8_t pos = 0;
uint8_t flag;
uint16_t ref = 0;
uint8_t ref_len = 0;
uint8_t bchan_no = 0;
uint8_t msgtype;
/* First octet is protocol discriminator */
pos++;
/* Second octet contains length of call reference */
ref_len = data[pos++] & 0x0F;
/* third octet is call reference */
flag = (data[pos] & 0x80) >> 7;
if (ref_len == 2) {
ref = (data[pos++] & 0x7F) << 8;
ref |= (data[pos++] & 0xFF) ;
} else {
ref = (data[pos++] & 0x7F);
}
/* Next octet is the message type */
msgtype = data[pos++] & 0x7F;
/*
ftdm_log(FTDM_LOG_DEBUG, "Raw frame:call_ref:0x%04x flag:%d msgtype:%d\n", ref, flag, msgtype);
*/
if (!ref) {
/* This is not a call specific message (RESTART for example and we do not care about it) */
return FTDM_FAIL;
}
/* Look for the b-channel */
if (msgtype == PROT_Q931_MSGTYPE_SETUP) {
/* Try to find the b-channel no*/
for(; pos < data_len; pos++) {
uint8_t ie_id = data[pos];
uint8_t ie_len = data[pos+1];
switch(ie_id) {
case PROT_Q931_IE_SENDING_COMPLETE:
/* Single octet ie's do not have a length */
ie_len = 0;
break;
case PROT_Q931_IE_CHANNEL_ID:
{
/* Try to obtain the b-channel */
uint8_t ie_pos = pos+2;
//ifaceIdPresent = get_bits(OCTET(3),7,7);
if (data[ie_pos] & 0x20) {
/* Interface type is Primary Rate */
ie_pos+=2;
bchan_no = data[ie_pos] & 0x7F;
} else {
/* Interface type is Basic Interface */
/* Get the channel number from info channel selection */
bchan_no = data[ie_pos] & 0x03;
}
ftdm_log(FTDM_LOG_DEBUG, "Found b-channel:%d\n", bchan_no);
goto parse_ies_done;
}
break;
default:
pos = pos+ie_len+1;
}
//ftdm_log(FTDM_LOG_DEBUG, "Decoded IE:%s\n", get_code_2_str(ie_id, dcodQ931IEIDTable));
}
if (!bchan_no) {
char tmp[1000];
print_hex_dump(tmp, 0, data, 0, data_len);
ftdm_log(FTDM_LOG_WARNING, "Failed to determine b-channel on SETUP message\n%s\n", tmp);
}
}
parse_ies_done:
target->call_ref = ref;
target->call_ref_flag = flag;
target->msgtype = msgtype;
target->bchan_no = bchan_no;
target->dir = dir;
return FTDM_SUCCESS;
}
static ftdm_status_t sngisdn_map_call(sngisdn_span_data_t *signal_data, sngisdn_frame_info_t frame_info, ftdm_channel_t **found)
{
sngisdn_chan_data_t *sngisdn_info;
ftdm_channel_t *ftdmchan = NULL;
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
ftdm_status_t status = FTDM_FAIL;
uint8_t outbound_call = 0;
if ((!frame_info.call_ref_flag && frame_info.dir == FTDM_TRACE_DIR_OUTGOING) ||
(frame_info.call_ref_flag && frame_info.dir == FTDM_TRACE_DIR_INCOMING)) {
/* If this is an outgoing frame and this frame was sent by the originating side
of the call (frame_info.call_ref_flag == 0), then this is an outbound call */
outbound_call = 1;
} else {
outbound_call = 0;
}
switch (frame_info.msgtype) {
case PROT_Q931_MSGTYPE_SETUP:
/* We initiated this outgoing call try to match the call reference with our internal call-id*/
if (!frame_info.bchan_no) {
/* We were not able to determine the bchannel on this call, so we will not be able to match it anyway */
status = FTDM_FAIL;
}
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
ftdmchan = (ftdm_channel_t*)(ftdm_iterator_current(curr));
ftdm_channel_lock(ftdmchan);
if (outbound_call) {
sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data;
if (sngisdn_info && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
if (ftdmchan->caller_data.call_id && ftdmchan->physical_chan_id == frame_info.bchan_no) {
sngisdn_info->call_ref = frame_info.call_ref;
*found = ftdmchan;
status = FTDM_SUCCESS;
}
}
} else {
if (ftdmchan->physical_chan_id == frame_info.bchan_no) {
*found = ftdmchan;
status = FTDM_SUCCESS;
}
}
ftdm_channel_unlock(ftdmchan);
}
ftdm_iterator_free(chaniter);
break;
case PROT_Q931_MSGTYPE_ALERTING:
case PROT_Q931_MSGTYPE_PROCEEDING:
case PROT_Q931_MSGTYPE_PROGRESS:
case PROT_Q931_MSGTYPE_CONNECT:
case PROT_Q931_MSGTYPE_SETUP_ACK:
case PROT_Q931_MSGTYPE_CONNECT_ACK:
case PROT_Q931_MSGTYPE_USER_INFO:
case PROT_Q931_MSGTYPE_DISCONNECT:
case PROT_Q931_MSGTYPE_RELEASE:
case PROT_Q931_MSGTYPE_RELEASE_ACK:
case PROT_Q931_MSGTYPE_RELEASE_COMPLETE:
case PROT_Q931_MSGTYPE_FACILITY:
case PROT_Q931_MSGTYPE_NOTIFY:
case PROT_Q931_MSGTYPE_STATUS_ENQUIRY:
case PROT_Q931_MSGTYPE_INFORMATION:
case PROT_Q931_MSGTYPE_STATUS:
/* Look for an outbound call on that span and and try to match the call-id */
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
ftdmchan = (ftdm_channel_t*)(ftdm_iterator_current(curr));
ftdm_channel_lock(ftdmchan);
sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data;
if (outbound_call) {
if (sngisdn_info && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
if (sngisdn_info->call_ref == frame_info.call_ref) {
*found = ftdmchan;
status = FTDM_SUCCESS;
}
}
} else {
if (sngisdn_info && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
if (sngisdn_info->call_ref && sngisdn_info->call_ref == frame_info.call_ref) {
*found = ftdmchan;
status = FTDM_SUCCESS;
}
}
}
ftdm_channel_unlock(ftdmchan);
}
ftdm_iterator_free(chaniter);
break;
default:
/* This frame is not call specific, ignore */
break;
}
if (status == FTDM_SUCCESS) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Mapped %s with Call Ref:%04x to call-id:%d\n", get_code_2_str(frame_info.msgtype, dcodQ931MsgTypeTable), frame_info.call_ref, (*found)->caller_data.call_id);
} else {
/* We could not map this frame to a call-id */
ftdm_log(FTDM_LOG_DEBUG, "Failed to map %s with Call Ref:%04x to local call\n",
get_code_2_str(frame_info.msgtype, dcodQ931MsgTypeTable), frame_info.call_ref);
}
return status;
}

@ -191,37 +191,65 @@ struct code2str dcodQ931CallRefLoTable[] = {
{13, "D"},
{14, "E"},
{15, "F"},
{-1,"?"},
{-1, "?"},
};
#define PROT_Q931_MSGTYPE_ALERTING 1
#define PROT_Q931_MSGTYPE_PROCEEDING 2
#define PROT_Q931_MSGTYPE_PROGRESS 3
#define PROT_Q931_MSGTYPE_SETUP 5
#define PROT_Q931_MSGTYPE_CONNECT 7
#define PROT_Q931_MSGTYPE_SETUP_ACK 13
#define PROT_Q931_MSGTYPE_CONNECT_ACK 15
#define PROT_Q931_MSGTYPE_USER_INFO 32
#define PROT_Q931_MSGTYPE_SUSPEND_REJ 33
#define PROT_Q931_MSGTYPE_RESUME_REJ 34
#define PROT_Q931_MSGTYPE_SUSPEND 37
#define PROT_Q931_MSGTYPE_RESUME 38
#define PROT_Q931_MSGTYPE_SUSPEND_ACK 45
#define PROT_Q931_MSGTYPE_RESUME_ACK 46
#define PROT_Q931_MSGTYPE_DISCONNECT 69
#define PROT_Q931_MSGTYPE_RESTART 70
#define PROT_Q931_MSGTYPE_RELEASE 77
#define PROT_Q931_MSGTYPE_RELEASE_ACK 78
#define PROT_Q931_MSGTYPE_RELEASE_COMPLETE 90
#define PROT_Q931_MSGTYPE_SEGMENT 96
#define PROT_Q931_MSGTYPE_FACILITY 98
#define PROT_Q931_MSGTYPE_NOTIFY 110
#define PROT_Q931_MSGTYPE_STATUS_ENQUIRY 117
#define PROT_Q931_MSGTYPE_CONGESTION_CNTRL 121
#define PROT_Q931_MSGTYPE_INFORMATION 123
#define PROT_Q931_MSGTYPE_STATUS 125
struct code2str dcodQ931MsgTypeTable[] = {
{1, "Alerting"},
{2, "Call Proceeding"},
{3, "Progress"},
{5, "Setup"},
{7, "Connect"},
{13, "Setup Ack"},
{15, "Connect Ack"},
{32, "User Info"},
{33, "Suspend Rej"},
{34, "Resume Rej"},
{37, "Suspend"},
{38, "Resume"},
{45, "Suspend Ack"},
{46, "Resume Ack"},
{69, "Disconnect"},
{70, "Restart"},
{77, "Release"},
{78, "Release Ack"},
{90, "Release Compl"},
{96, "Segment"},
{98, "Facility"},
{110, "Notify"},
{117, "Status Enquiry"},
{121, "Congest Cntrl"},
{123, "Information"},
{125, "Status"},
{-1, "Unknown"},
{PROT_Q931_MSGTYPE_ALERTING, "ALERT"},
{PROT_Q931_MSGTYPE_PROCEEDING, "PROCEED"},
{PROT_Q931_MSGTYPE_PROGRESS, "PROGRESS"},
{PROT_Q931_MSGTYPE_SETUP, "SETUP"},
{PROT_Q931_MSGTYPE_CONNECT, "CONNECT"},
{PROT_Q931_MSGTYPE_SETUP_ACK, "SETUP ACK"},
{PROT_Q931_MSGTYPE_CONNECT_ACK, "CONNECT ACK"},
{PROT_Q931_MSGTYPE_USER_INFO, "USER INFO"},
{PROT_Q931_MSGTYPE_SUSPEND_REJ, "SUSPEND REJ"},
{PROT_Q931_MSGTYPE_RESUME_REJ, "RESUME REJ"},
{PROT_Q931_MSGTYPE_SUSPEND, "SUSPEND"},
{PROT_Q931_MSGTYPE_RESUME, "RESUME"},
{PROT_Q931_MSGTYPE_SUSPEND_ACK, "SUSPEND ACK"},
{PROT_Q931_MSGTYPE_RESUME_ACK, "RESUME ACK"},
{PROT_Q931_MSGTYPE_DISCONNECT, "DISCONNECT"},
{PROT_Q931_MSGTYPE_RESTART, "RESTART"},
{PROT_Q931_MSGTYPE_RELEASE, "RELEASE"},
{PROT_Q931_MSGTYPE_RELEASE_ACK, "RELEASR ACK"},
{PROT_Q931_MSGTYPE_RELEASE_COMPLETE, "RELEASE COMPLETE"},
{PROT_Q931_MSGTYPE_SEGMENT, "SEGMENT"},
{PROT_Q931_MSGTYPE_FACILITY, "FACILITY"},
{PROT_Q931_MSGTYPE_NOTIFY, "NOTIFY"},
{PROT_Q931_MSGTYPE_STATUS_ENQUIRY, "STATUS ENQ"},
{PROT_Q931_MSGTYPE_CONGESTION_CNTRL, "CONGESTION CTRL"},
{PROT_Q931_MSGTYPE_INFORMATION, "INFO"},
{PROT_Q931_MSGTYPE_STATUS, "STATUS"},
{-1, "UNKNOWN"},
};
struct code2str dcodQ931CauseCodeTable[] = {

@ -0,0 +1,118 @@
/*
* Copyright (c) 2010, Sangoma Technologies
* David Yat Sin <davidy@sangoma.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __FTMOD_SANGOMA_ISDN_USER_H__
#define __FTMOD_SANGOMA_ISDN_USER_H__
#define SNGISDN_ENUM_NAMES(_NAME, _STRINGS) static const char * _NAME [] = { _STRINGS , NULL };
#define SNGISDN_STR2ENUM_P(_FUNC1, _FUNC2, _TYPE) _TYPE _FUNC1 (const char *name); const char * _FUNC2 (_TYPE type);
#define SNGISDN_STR2ENUM(_FUNC1, _FUNC2, _TYPE, _STRINGS, _MAX) \
_TYPE _FUNC1 (const char *name) \
{ \
int i; \
_TYPE t = _MAX ; \
\
for (i = 0; i < _MAX ; i++) { \
if (!strcasecmp(name, _STRINGS[i])) { \
t = (_TYPE) i; \
break; \
} \
} \
return t; \
} \
const char * _FUNC2 (_TYPE type) \
{ \
if (type > _MAX) { \
type = _MAX; \
} \
return _STRINGS[(int)type]; \
} \
typedef enum {
/* Call is not end-to-end ISDN */
SNGISDN_PROGIND_DESCR_NETE_ISDN,
/* Destination address is non-ISDN */
SNGISDN_PROGIND_DESCR_DEST_NISDN,
/* Origination address is non-ISDN */
SNGISDN_PROGIND_DESCR_ORIG_NISDN,
/* Call has returned to the ISDN */
SNGISDN_PROGIND_DESCR_RET_ISDN,
/* Interworking as occured and has resulted in a telecommunication service change */
SNGISDN_PROGIND_DESCR_SERV_CHANGE,
/* In-band information or an appropriate pattern is now available */
SNGISDN_PROGIND_DESCR_IB_AVAIL,
/* Invalid */
SNGISDN_PROGIND_DESCR_INVALID,
} ftdm_sngisdn_progind_descr_t;
#define SNGISDN_PROGIND_DESCR_STRINGS "not-end-to-end-isdn", "destination-is-non-isdn", "origination-is-non-isdn", "call-returned-to-isdn", "service-change", "inband-info-available", "invalid"
SNGISDN_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr2str, ftdm_sngisdn_progind_descr_t);
typedef enum {
/* User */
SNGISDN_PROGIND_LOC_USER,
/* Private network serving the local user */
SNGISDN_PROGIND_LOC_PRIV_NET_LOCAL_USR,
/* Public network serving the local user */
SNGISDN_PROGIND_LOC_PUB_NET_LOCAL_USR,
/* Transit network */
SNGISDN_PROGIND_LOC_TRANSIT_NET,
/* Public network serving remote user */
SNGISDN_PROGIND_LOC_PUB_NET_REMOTE_USR,
/* Private network serving remote user */
SNGISDN_PROGIND_LOC_PRIV_NET_REMOTE_USR,
/* Network beyond the interworking point */
SNGISDN_PROGIND_LOC_NET_BEYOND_INTRW,
/* Invalid */
SNGISDN_PROGIND_LOC_INVALID,
} ftdm_sngisdn_progind_loc_t;
#define SNGISDN_PROGIND_LOC_STRINGS "user", "private-net-local-user", "public-net-local-user", "transit-network", "public-net-remote-user", "private-net-remote-user", "beyond-interworking", "invalid"
SNGISDN_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t);
#endif /* __FTMOD_SANGOMA_ISDN_USER_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:
*/
/******************************************************************************/

@ -230,6 +230,8 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
ftdm_channel_t *chan;
ftdm_socket_t sockfd = FTDM_INVALID_SOCKET;
const char *dtmf = "none";
const char *hwec_str = "none";
const char *hwec_idle = "none";
if (!strncasecmp(span->name, "smg_prid_nfas", 8) && span->trunk_type == FTDM_TRUNK_T1 && x == 24) {
#ifdef LIBSANGOMA_VERSION
sockfd = __tdmv_api_open_span_chan(spanno, x);
@ -271,6 +273,8 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
|| type == FTDM_CHAN_TYPE_B) {
int err;
hwec_str = "unavailable";
hwec_idle = "enabled";
dtmf = "software";
err = sangoma_tdm_get_hw_coding(chan->sockfd, &tdm_api);
@ -289,6 +293,7 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
err = sangoma_tdm_get_hw_ec(chan->sockfd, &tdm_api);
if (err > 0) {
hwec_str = "available";
ftdm_channel_set_feature(chan, FTDM_CHANNEL_FEATURE_HWEC);
}
@ -296,6 +301,7 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
err = sangoma_tdm_get_hwec_persist_status(chan->sockfd, &tdm_api);
if (err == 0) {
ftdm_channel_set_feature(chan, FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE);
hwec_idle = "disabled";
}
#else
if (span->trunk_type == FTDM_TRUNK_BRI || span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
@ -365,8 +371,8 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
ftdm_copy_string(chan->chan_number, number, sizeof(chan->chan_number));
}
configured++;
ftdm_log_chan(chan, FTDM_LOG_INFO, "configured wanpipe device s%dc%d as FreeTDM channel %d:%d fd:%d DTMF: %s\n",
spanno, x, chan->span_id, chan->chan_id, sockfd, dtmf);
ftdm_log_chan(chan, FTDM_LOG_INFO, "Configured wanpipe device FD: %d, DTMF: %s, HWEC: %s, HWEC_IDLE: %s\n",
sockfd, dtmf, hwec_str, hwec_idle);
} else {
ftdm_log(FTDM_LOG_ERROR, "ftdm_span_add_channel failed for wanpipe span %d channel %d\n", spanno, x);
@ -1180,7 +1186,7 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms)
unsigned int alarms = 0;
int err;
memset(&tdm_api,0,sizeof(tdm_api));
memset(&tdm_api, 0, sizeof(tdm_api));
#ifdef LIBSANGOMA_VERSION
if ((err = sangoma_tdm_get_fe_alarms(ftdmchan->sockfd, &tdm_api, &alarms))) {
@ -1226,9 +1232,19 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms)
alarms &= ~WAN_TE_BIT_ALARM_RAI;
}
if (!ftdmchan->alarm_flags) {
if (FTDM_IS_DIGITAL_CHANNEL(ftdmchan)) {
ftdm_channel_hw_link_status_t sangoma_status = 0;
/* there is a bug in wanpipe where alarms were not properly set when they should be
* on at application startup, until that is fixed we check the link status here too */
ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_LINK_STATUS, &sangoma_status);
ftdmchan->alarm_flags = sangoma_status == FTDM_HW_LINK_DISCONNECTED ? 1 : 0;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Link status is %d\n", sangoma_status);
}
}
if (alarms) {
/* FIXME: investigate what else does the driver report */
ftdm_log(FTDM_LOG_DEBUG, "Unmapped wanpipe alarms: %d\n", alarms);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Unmapped wanpipe alarms: %d\n", alarms);
}
return FTDM_SUCCESS;
@ -1243,30 +1259,38 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms)
*/
static __inline__ ftdm_status_t wanpipe_channel_process_event(ftdm_channel_t *fchan, ftdm_oob_event_t *event_id, wanpipe_tdm_api_t *tdm_api)
{
ftdm_status_t status = FTDM_SUCCESS;
switch(tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_type) {
case WP_API_EVENT_LINK_STATUS:
{
switch(tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_link_status) {
case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED:
*event_id = FTDM_OOB_ALARM_CLEAR;
/* *event_id = FTDM_OOB_ALARM_CLEAR; */
ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Ignoring wanpipe link connected event\n");
break;
default:
*event_id = FTDM_OOB_ALARM_TRAP;
/* *event_id = FTDM_OOB_ALARM_TRAP; */
ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Ignoring wanpipe link disconnected event\n");
break;
};
/* The WP_API_EVENT_ALARM event should be used to clear alarms */
*event_id = FTDM_OOB_NOOP;
}
break;
case WP_API_EVENT_RXHOOK:
{
if (fchan->type == FTDM_CHAN_TYPE_FXS) {
*event_id = tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_OFFHOOK : FTDM_OOB_ONHOOK;
*event_id = tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_hook_state
& WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_OFFHOOK : FTDM_OOB_ONHOOK;
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Got wanpipe %s\n", ftdm_oob_event2str(*event_id));
if (*event_id == FTDM_OOB_OFFHOOK) {
if (ftdm_test_flag(fchan, FTDM_CHANNEL_FLASH)) {
ftdm_clear_flag(fchan, FTDM_CHANNEL_FLASH);
ftdm_clear_flag(fchan, FTDM_CHANNEL_WINK);
*event_id = FTDM_OOB_FLASH;
goto event;
goto done;
} else {
ftdm_set_flag(fchan, FTDM_CHANNEL_WINK);
}
@ -1275,12 +1299,14 @@ static __inline__ ftdm_status_t wanpipe_channel_process_event(ftdm_channel_t *fc
ftdm_clear_flag(fchan, FTDM_CHANNEL_WINK);
ftdm_clear_flag(fchan, FTDM_CHANNEL_FLASH);
*event_id = FTDM_OOB_WINK;
goto event;
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Wink flag is set, delivering %s\n",
ftdm_oob_event2str(*event_id));
goto done;
} else {
ftdm_set_flag(fchan, FTDM_CHANNEL_FLASH);
}
}
break;
status = FTDM_BREAK;
} else {
ftdm_status_t status;
wanpipe_tdm_api_t onhook_tdm_api;
@ -1338,8 +1364,13 @@ static __inline__ ftdm_status_t wanpipe_channel_process_event(ftdm_channel_t *fc
break;
case WP_API_EVENT_ALARM:
{
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Got wanpipe alarms %d\n", tdm_api->wp_tdm_cmd.event.wp_api_event_alarm);
*event_id = FTDM_OOB_ALARM_TRAP;
if (tdm_api->wp_tdm_cmd.event.wp_api_event_alarm) {
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Got Wanpipe alarms %d\n", tdm_api->wp_tdm_cmd.event.wp_api_event_alarm);
*event_id = FTDM_OOB_ALARM_TRAP;
} else {
ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Wanpipe alarms cleared\n");
*event_id = FTDM_OOB_ALARM_CLEAR;
}
}
break;
case WP_API_EVENT_POLARITY_REVERSE:
@ -1355,8 +1386,8 @@ static __inline__ ftdm_status_t wanpipe_channel_process_event(ftdm_channel_t *fc
}
break;
}
event:
return FTDM_SUCCESS;
done:
return status;
}
/**
@ -1385,12 +1416,16 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event)
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "read wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type);
if ((wanpipe_channel_process_event(ftdmchan, &event_id, &tdm_api)) != FTDM_SUCCESS) {
status = wanpipe_channel_process_event(ftdmchan, &event_id, &tdm_api);
if (status == FTDM_BREAK) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Ignoring event for now\n");
} else if (status != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failed to process event from channel\n");
return FTDM_FAIL;
} else {
ftdmchan->last_event_time = 0;
}
ftdmchan->last_event_time = 0;
span->event_header.e_type = FTDM_EVENT_OOB;
span->event_header.enum_id = event_id;
span->event_header.channel = ftdmchan;
@ -1409,8 +1444,10 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event)
uint32_t i,err;
ftdm_oob_event_t event_id;
for(i = 1; i <= span->chan_count; i++) {
/* as a hack for wink/flash detection, wanpipe_poll_event overrides the timeout parameter
* to force the user to call this function each 5ms or so to detect the timeout of our wink/flash */
if (span->channels[i]->last_event_time && !ftdm_test_flag(span->channels[i], FTDM_CHANNEL_EVENT)) {
uint32_t diff = (uint32_t)(ftdm_current_time_in_ms() - span->channels[i]->last_event_time);
ftdm_time_t diff = ftdm_current_time_in_ms() - span->channels[i]->last_event_time;
/* XX printf("%u %u %u\n", diff, (unsigned)ftdm_current_time_in_ms(), (unsigned)span->channels[i]->last_event_time); */
if (ftdm_test_flag(span->channels[i], FTDM_CHANNEL_WINK)) {
if (diff > wp_globals.wink_ms) {
@ -1418,6 +1455,7 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event)
ftdm_clear_flag_locked(span->channels[i], FTDM_CHANNEL_FLASH);
ftdm_set_flag_locked(span->channels[i], FTDM_CHANNEL_OFFHOOK);
event_id = FTDM_OOB_OFFHOOK;
ftdm_log_chan(span->channels[i], FTDM_LOG_DEBUG, "Diff since last event = %llums, delivering %s now\n", diff, ftdm_oob_event2str(event_id));
goto event;
}
}
@ -1436,11 +1474,13 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event)
sangoma_tdm_txsig_onhook(ftdmchan->sockfd,&tdm_api);
}
ftdm_log_chan(span->channels[i], FTDM_LOG_DEBUG, "Diff since last event = %llums, delivering %s now\n", diff, ftdm_oob_event2str(event_id));
goto event;
}
}
}
if (ftdm_test_flag(span->channels[i], FTDM_CHANNEL_EVENT)) {
ftdm_status_t status;
wanpipe_tdm_api_t tdm_api;
ftdm_channel_t *ftdmchan = span->channels[i];
memset(&tdm_api, 0, sizeof(tdm_api));
@ -1448,18 +1488,22 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event)
err = sangoma_tdm_read_event(ftdmchan->sockfd, &tdm_api);
if (err != FTDM_SUCCESS) {
snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno));
ftdm_log_chan(span->channels[i], FTDM_LOG_ERROR, "read wanpipe event got error: %s\n", strerror(errno));
return FTDM_FAIL;
}
ftdm_log_chan(span->channels[i], FTDM_LOG_DEBUG, "read wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type);
ftdm_channel_lock(ftdmchan);
if ((wanpipe_channel_process_event(ftdmchan, &event_id, &tdm_api)) != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failed to process events from channel\n");
ftdm_channel_unlock(ftdmchan);
status = wanpipe_channel_process_event(ftdmchan, &event_id, &tdm_api);
ftdm_channel_unlock(ftdmchan);
if (status == FTDM_BREAK) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring event for now\n");
continue;
} else if (status != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failed to process event from channel\n");
return FTDM_FAIL;
}
ftdm_channel_unlock(ftdmchan);
event:
@ -1471,7 +1515,7 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event)
return FTDM_SUCCESS;
}
}
return FTDM_FAIL;
return FTDM_BREAK;
}
/**

@ -1064,6 +1064,12 @@ static __inline__ ftdm_status_t zt_channel_process_event(ftdm_channel_t *fchan,
fchan->rx_cas_bits = bits;
}
break;
case ZT_EVENT_NONE:
{
ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "No event\n");
*event_id = FTDM_OOB_NOOP;
}
break;
default:
{
ftdm_log_chan(fchan, FTDM_LOG_WARNING, "Unhandled event %d\n", zt_event_id);
@ -1125,26 +1131,26 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event)
ftdm_channel_t *fchan = span->channels[i];
if (ftdm_test_flag(fchan, FTDM_CHANNEL_EVENT)) {
ftdm_clear_flag(fchan, FTDM_CHANNEL_EVENT);
}
if (ioctl(fchan->sockfd, codes.GETEVENT, &zt_event_id) == -1) {
snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno));
return FTDM_FAIL;
}
if (ioctl(fchan->sockfd, codes.GETEVENT, &zt_event_id) == -1) {
snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno));
return FTDM_FAIL;
}
ftdm_channel_lock(fchan);
if ((zt_channel_process_event(fchan, &event_id, zt_event_id)) != FTDM_SUCCESS) {
ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Failed to process event from channel\n");
ftdm_channel_lock(fchan);
if ((zt_channel_process_event(fchan, &event_id, zt_event_id)) != FTDM_SUCCESS) {
ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Failed to process event from channel\n");
ftdm_channel_unlock(fchan);
return FTDM_FAIL;
}
ftdm_channel_unlock(fchan);
return FTDM_FAIL;
}
ftdm_channel_unlock(fchan);
fchan->last_event_time = 0;
span->event_header.e_type = FTDM_EVENT_OOB;
span->event_header.enum_id = event_id;
span->event_header.channel = fchan;
*event = &span->event_header;
return FTDM_SUCCESS;
fchan->last_event_time = 0;
span->event_header.e_type = FTDM_EVENT_OOB;
span->event_header.enum_id = event_id;
span->event_header.channel = fchan;
*event = &span->event_header;
return FTDM_SUCCESS;
}
}
return FTDM_FAIL;

@ -82,8 +82,12 @@ typedef enum {
FTDM_CAUSE_UNALLOCATED = 1,
FTDM_CAUSE_NO_ROUTE_TRANSIT_NET = 2,
FTDM_CAUSE_NO_ROUTE_DESTINATION = 3,
FTDM_CAUSE_SEND_SPECIAL_INFO_TONE = 4,
FTDM_CAUSE_MISDIALED_TRUNK_PREFIX = 5,
FTDM_CAUSE_CHANNEL_UNACCEPTABLE = 6,
FTDM_CAUSE_CALL_AWARDED_DELIVERED = 7,
FTDM_CAUSE_PREEMPTION = 8,
FTDM_CAUSE_PREEMPTION_CIRCUIT_RESERVED = 9,
FTDM_CAUSE_NORMAL_CLEARING = 16,
FTDM_CAUSE_USER_BUSY = 17,
FTDM_CAUSE_NO_USER_RESPONSE = 18,
@ -100,23 +104,38 @@ typedef enum {
FTDM_CAUSE_NORMAL_UNSPECIFIED = 31,
FTDM_CAUSE_NORMAL_CIRCUIT_CONGESTION = 34,
FTDM_CAUSE_NETWORK_OUT_OF_ORDER = 38,
FTDM_CAUSE_PERMANENT_FRAME_MODE_CONNECTION_OOS = 39,
FTDM_CAUSE_PERMANENT_FRAME_MODE_OPERATIONAL = 40,
FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE = 41,
FTDM_CAUSE_SWITCH_CONGESTION = 42,
FTDM_CAUSE_ACCESS_INFO_DISCARDED = 43,
FTDM_CAUSE_REQUESTED_CHAN_UNAVAIL = 44,
FTDM_CAUSE_PRE_EMPTED = 45,
FTDM_CAUSE_PRECEDENCE_CALL_BLOCKED = 46,
FTDM_CAUSE_RESOURCE_UNAVAILABLE_UNSPECIFIED = 47,
FTDM_CAUSE_QOS_NOT_AVAILABLE = 49,
FTDM_CAUSE_FACILITY_NOT_SUBSCRIBED = 50,
FTDM_CAUSE_OUTGOING_CALL_BARRED = 52,
FTDM_CAUSE_INCOMING_CALL_BARRED = 54,
FTDM_CAUSE_OUTGOING_CALL_BARRED = 53,
FTDM_CAUSE_INCOMING_CALL_BARRED = 55,
FTDM_CAUSE_BEARERCAPABILITY_NOTAUTH = 57,
FTDM_CAUSE_BEARERCAPABILITY_NOTAVAIL = 58,
FTDM_CAUSE_INCONSISTENCY_IN_INFO = 62,
FTDM_CAUSE_SERVICE_UNAVAILABLE = 63,
FTDM_CAUSE_BEARERCAPABILITY_NOTIMPL = 65,
FTDM_CAUSE_CHAN_NOT_IMPLEMENTED = 66,
FTDM_CAUSE_FACILITY_NOT_IMPLEMENTED = 69,
FTDM_CAUSE_ONLY_DIGITAL_INFO_BC_AVAIL = 70,
FTDM_CAUSE_SERVICE_NOT_IMPLEMENTED = 79,
FTDM_CAUSE_INVALID_CALL_REFERENCE = 81,
FTDM_CAUSE_IDENTIFIED_CHAN_NOT_EXIST = 82,
FTDM_CAUSE_SUSPENDED_CALL_EXISTS_BUT_CALL_ID_DOES_NOT = 83,
FTDM_CAUSE_CALL_ID_IN_USE = 84,
FTDM_CAUSE_NO_CALL_SUSPENDED = 85,
FTDM_CAUSE_CALL_WITH_CALL_ID_CLEARED = 86,
FTDM_CAUSE_USER_NOT_CUG = 87,
FTDM_CAUSE_INCOMPATIBLE_DESTINATION = 88,
FTDM_CAUSE_NON_EXISTENT_CUG = 90,
FTDM_CAUSE_INVALID_TRANSIT_NETWORK_SELECTION = 91,
FTDM_CAUSE_INVALID_MSG_UNSPECIFIED = 95,
FTDM_CAUSE_MANDATORY_IE_MISSING = 96,
FTDM_CAUSE_MESSAGE_TYPE_NONEXIST = 97,
@ -126,6 +145,7 @@ typedef enum {
FTDM_CAUSE_WRONG_CALL_STATE = 101,
FTDM_CAUSE_RECOVERY_ON_TIMER_EXPIRE = 102,
FTDM_CAUSE_MANDATORY_IE_LENGTH_ERROR = 103,
FTDM_CAUSE_MSG_WITH_UNRECOGNIZED_PARAM_DISCARDED = 110,
FTDM_CAUSE_PROTOCOL_ERROR = 111,
FTDM_CAUSE_INTERWORKING = 127,
FTDM_CAUSE_SUCCESS = 142,
@ -168,10 +188,17 @@ typedef enum {
FTDM_STR2ENUM_P(ftdm_str2ftdm_chan_type, ftdm_chan_type2str, ftdm_chan_type_t)
/*! \brief Test if a channel is a voice channel */
#define FTDM_IS_VOICE_CHANNEL(ftdm_chan) ((ftdm_chan)->type != FTDM_CHAN_TYPE_DQ921 && (ftdm_chan)->type != FTDM_CHAN_TYPE_DQ931)
#define FTDM_IS_VOICE_CHANNEL(fchan) ((fchan)->type != FTDM_CHAN_TYPE_DQ921 && (fchan)->type != FTDM_CHAN_TYPE_DQ931)
/*! \brief Test if a channel is a D-channel */
#define FTDM_IS_DCHAN(ftdm_chan) ((ftdm_chan)->type == FTDM_CHAN_TYPE_DQ921 || (ftdm_chan)->type == FTDM_CHAN_TYPE_DQ931)
#define FTDM_IS_DCHAN(fchan) ((fchan)->type == FTDM_CHAN_TYPE_DQ921 || (fchan)->type == FTDM_CHAN_TYPE_DQ931)
/*! \brief Test if a channel is digital channel */
#define FTDM_IS_DIGITAL_CHANNEL(fchan) ((fchan)->span->trunk_type == FTDM_TRUNK_E1 || \
(fchan)->span->trunk_type == FTDM_TRUNK_T1 || \
(fchan)->span->trunk_type == FTDM_TRUNK_J1 || \
(fchan)->span->trunk_type == FTDM_TRUNK_BRI || \
(fchan)->span->trunk_type == FTDM_TRUNK_BRI_PTMP)
/*! \brief Logging function prototype to be used for all FreeTDM logs
* you should use ftdm_global_set_logger to set your own logger
@ -321,8 +348,57 @@ typedef struct ftdm_caller_data {
* should use the call_id from sigmsg otherwise */
uint32_t call_id; /*!< Unique call ID for this call */
ftdm_channel_t *fchan; /*!< FreeTDM channel associated (can be NULL) */
void *priv; /*!< Private data for the FreeTDM user */
} ftdm_caller_data_t;
/*! \brief Hunting mode */
typedef enum {
FTDM_HUNT_SPAN, /*!< Hunt channels in a given span */
FTDM_HUNT_GROUP, /*!< Hunt channels in a given group */
FTDM_HUNT_CHAN, /*!< Hunt for a specific channel */
} ftdm_hunt_mode_t;
/*! \brief Structure used for FTDM_HUNT_SPAN mode */
typedef struct {
uint32_t span_id;
ftdm_direction_t direction;
} ftdm_span_hunt_t;
/*! \brief Structure used for FTDM_HUNT_GROUP mode */
typedef struct {
uint32_t group_id;
ftdm_direction_t direction;
} ftdm_group_hunt_t;
/*! \brief Structure used for FTDM_HUNT_CHAN mode */
typedef struct {
uint32_t span_id;
uint32_t chan_id;
} ftdm_chan_hunt_t;
/*! \brief Function called before placing the call in the hunted channel
* The user can have a last saying in whether to proceed or abort
* the call attempt. Be aware that this callback will be called with
* the channel lock and you must not do any blocking operations during
* its execution.
* \param fchan The channel that will be used to place the call
* \param caller_data The caller data provided to ftdm_call_place
* \return FTDM_SUCCESS to proceed or FTDM_BREAK to abort the hunting
*/
typedef ftdm_status_t (*ftdm_hunt_result_cb_t)(ftdm_channel_t *fchan, ftdm_caller_data_t *caller_data);
/*! \brief Channel Hunting provided to ftdm_call_place() */
typedef struct {
ftdm_hunt_mode_t mode;
union {
ftdm_span_hunt_t span;
ftdm_group_hunt_t group;
ftdm_chan_hunt_t chan;
} mode_data;
ftdm_hunt_result_cb_t result_cb;
} ftdm_hunting_scheme_t;
/*! \brief Tone type */
typedef enum {
FTDM_TONE_DTMF = (1 << 0)
@ -335,7 +411,7 @@ typedef enum {
FTDM_SIGEVENT_RELEASED, /*!< Channel is completely released and available */
FTDM_SIGEVENT_UP, /*!< Outgoing call has been answered */
FTDM_SIGEVENT_FLASH, /*!< Flash event (typically on-hook/off-hook for analog devices) */
FTDM_SIGEVENT_PROCEED, /*!< Outgoing call got a response */
FTDM_SIGEVENT_PROCEED, /*!< Outgoing call got an initial positive response from the other end */
FTDM_SIGEVENT_RINGING, /*!< Remote side is in ringing state */
FTDM_SIGEVENT_PROGRESS, /*!< Outgoing call is making progress */
FTDM_SIGEVENT_PROGRESS_MEDIA, /*!< Outgoing call is making progress and there is media available */
@ -345,17 +421,17 @@ typedef enum {
FTDM_SIGEVENT_ADD_CALL, /*!< New call should be added to the channel */
FTDM_SIGEVENT_RESTART, /*!< Restart has been requested. Typically you hangup your call resources here */
FTDM_SIGEVENT_SIGSTATUS_CHANGED, /*!< Signaling protocol status changed (ie: D-chan up), see new status in raw_data ftdm_sigmsg_t member */
FTDM_SIGEVENT_COLLISION, /*!< Outgoing call was dropped because an incoming call arrived at the same time */
FTDM_SIGEVENT_FACILITY, /*!< In call facility event */
FTDM_SIGEVENT_TRACE, /*!<Interpreted trace event */
FTDM_SIGEVENT_TRACE_RAW, /*!<Raw trace event */
FTDM_SIGEVENT_INDICATION_COMPLETED, /*!< Last requested indication was completed */
FTDM_SIGEVENT_DIALING, /* Outgoing call just started */
FTDM_SIGEVENT_INVALID, /*!<Invalid */
} ftdm_signal_event_t;
#define SIGNAL_STRINGS "START", "STOP", "RELEASED", "UP", "FLASH", "PROCEED", "RINGING", "PROGRESS", \
"PROGRESS_MEDIA", "ALARM_TRAP", "ALARM_CLEAR", \
"COLLECTED_DIGIT", "ADD_CALL", "RESTART", "SIGSTATUS_CHANGED", "COLLISION", "FACILITY", \
"TRACE", "TRACE_RAW", "INDICATION_COMPLETED", "INVALID"
"TRACE", "TRACE_RAW", "INDICATION_COMPLETED", "DIALING", "INVALID"
/*! \brief Move from string to ftdm_signal_event_t and viceversa */
FTDM_STR2ENUM_P(ftdm_str2ftdm_signal_event, ftdm_signal_event2str, ftdm_signal_event_t)
@ -413,21 +489,31 @@ typedef struct {
typedef enum {
/* This is an received frame */
FTDM_TRACE_INCOMING,
FTDM_TRACE_DIR_INCOMING,
/* This is a transmitted frame */
FTDM_TRACE_OUTGOING,
FTDM_TRACE_DIR_OUTGOING,
/* Invalid */
FTDM_TRACE_INVALID,
FTDM_TRACE_DIR_INVALID,
} ftdm_trace_dir_t;
#define TRACE_DIR_STRINGS "INCOMING", "OUTGOING", "INVALID"
/*! \brief Move string to ftdm_trace_dir_t and viceversa */
FTDM_STR2ENUM_P(ftdm_str2ftdm_trace_dir, ftdm_trace_dir2str, ftdm_trace_dir_t)
typedef enum {
FTDM_TRACE_TYPE_Q931,
FTDM_TRACE_TYPE_Q921,
FTDM_TRACE_TYPE_INVALID,
} ftdm_trace_type_t;
#define TRACE_TYPE_STRINGS "Q931", "Q921", "INVALID"
/*! \brief Move string to ftdm_trace_type_t and viceversa */
FTDM_STR2ENUM_P(ftdm_str2ftdm_trace_type, ftdm_trace_type2str, ftdm_trace_type_t)
typedef struct {
/* Direction - incoming or outgoing */
ftdm_trace_dir_t dir;
uint8_t level; /* 1 for phy layer, 2 for q921/mtp2, 3 for q931/mtp3 */
ftdm_trace_type_t type;
} ftdm_event_trace_t;
typedef struct {
@ -470,7 +556,7 @@ struct ftdm_sigmsg {
uint32_t call_id; /*!< unique call id for this call */
union {
ftdm_event_sigstatus_t sigstatus; /*!< valid if event_id is FTDM_SIGEVENT_SIGSTATUS_CHANGED */
ftdm_event_trace_t logevent; /*!< valid if event_id is FTDM_SIGEVENT_TRACE or FTDM_SIGEVENT_TRACE_RAW */
ftdm_event_trace_t trace; /*!< valid if event_id is FTDM_SIGEVENT_TRACE or FTDM_SIGEVENT_TRACE_RAW */
ftdm_event_collected_t collected; /*!< valid if event_id is FTDM_SIGEVENT_COLLECTED_DIGIT */
ftdm_event_indication_completed_t indication_completed; /*!< valid if the event_id is FTDM_SIGEVENT_INDICATION_COMPLETED */
} ev_data;
@ -508,84 +594,84 @@ typedef struct ftdm_iterator ftdm_iterator_t;
/*! \brief Channel commands that can be executed through ftdm_channel_command() */
typedef enum {
FTDM_COMMAND_NOOP,
FTDM_COMMAND_SET_INTERVAL,
FTDM_COMMAND_GET_INTERVAL,
FTDM_COMMAND_SET_CODEC,
FTDM_COMMAND_GET_CODEC,
FTDM_COMMAND_SET_NATIVE_CODEC,
FTDM_COMMAND_GET_NATIVE_CODEC,
FTDM_COMMAND_ENABLE_DTMF_DETECT,
FTDM_COMMAND_DISABLE_DTMF_DETECT,
FTDM_COMMAND_SEND_DTMF,
FTDM_COMMAND_SET_DTMF_ON_PERIOD,
FTDM_COMMAND_GET_DTMF_ON_PERIOD,
FTDM_COMMAND_SET_DTMF_OFF_PERIOD,
FTDM_COMMAND_GET_DTMF_OFF_PERIOD,
FTDM_COMMAND_GENERATE_RING_ON,
FTDM_COMMAND_GENERATE_RING_OFF,
FTDM_COMMAND_OFFHOOK,
FTDM_COMMAND_ONHOOK,
FTDM_COMMAND_FLASH,
FTDM_COMMAND_WINK,
FTDM_COMMAND_ENABLE_PROGRESS_DETECT,
FTDM_COMMAND_DISABLE_PROGRESS_DETECT,
FTDM_COMMAND_NOOP = 0,
FTDM_COMMAND_SET_INTERVAL = 1,
FTDM_COMMAND_GET_INTERVAL = 2,
FTDM_COMMAND_SET_CODEC = 3,
FTDM_COMMAND_GET_CODEC = 4,
FTDM_COMMAND_SET_NATIVE_CODEC = 5,
FTDM_COMMAND_GET_NATIVE_CODEC = 6,
FTDM_COMMAND_ENABLE_DTMF_DETECT = 7,
FTDM_COMMAND_DISABLE_DTMF_DETECT = 8,
FTDM_COMMAND_SEND_DTMF = 9,
FTDM_COMMAND_SET_DTMF_ON_PERIOD = 10,
FTDM_COMMAND_GET_DTMF_ON_PERIOD = 11,
FTDM_COMMAND_SET_DTMF_OFF_PERIOD = 12,
FTDM_COMMAND_GET_DTMF_OFF_PERIOD = 13,
FTDM_COMMAND_GENERATE_RING_ON = 14,
FTDM_COMMAND_GENERATE_RING_OFF = 15,
FTDM_COMMAND_OFFHOOK = 16,
FTDM_COMMAND_ONHOOK = 17,
FTDM_COMMAND_FLASH = 18,
FTDM_COMMAND_WINK = 19,
FTDM_COMMAND_ENABLE_PROGRESS_DETECT = 20,
FTDM_COMMAND_DISABLE_PROGRESS_DETECT = 21,
/*!< Start tracing input and output from channel to the given file */
FTDM_COMMAND_TRACE_INPUT,
FTDM_COMMAND_TRACE_OUTPUT,
FTDM_COMMAND_TRACE_INPUT = 22,
FTDM_COMMAND_TRACE_OUTPUT = 23,
/*!< Stop both Input and Output trace, closing the files */
FTDM_COMMAND_TRACE_END_ALL,
FTDM_COMMAND_TRACE_END_ALL = 24,
/*!< Enable DTMF debugging */
FTDM_COMMAND_ENABLE_DEBUG_DTMF,
FTDM_COMMAND_ENABLE_DEBUG_DTMF = 25,
/*!< Disable DTMF debugging (if not disabled explicitly, it is disabled automatically when calls hangup) */
FTDM_COMMAND_DISABLE_DEBUG_DTMF,
FTDM_COMMAND_DISABLE_DEBUG_DTMF = 26,
/*!< Start dumping all input to a circular buffer. The size of the circular buffer can be specified, default used otherwise */
FTDM_COMMAND_ENABLE_INPUT_DUMP,
FTDM_COMMAND_ENABLE_INPUT_DUMP = 27,
/*!< Stop dumping all input to a circular buffer. */
FTDM_COMMAND_DISABLE_INPUT_DUMP,
FTDM_COMMAND_DISABLE_INPUT_DUMP = 28,
/*!< Start dumping all output to a circular buffer. The size of the circular buffer can be specified, default used otherwise */
FTDM_COMMAND_ENABLE_OUTPUT_DUMP,
FTDM_COMMAND_ENABLE_OUTPUT_DUMP = 29,
/*!< Stop dumping all output to a circular buffer. */
FTDM_COMMAND_DISABLE_OUTPUT_DUMP,
FTDM_COMMAND_DISABLE_OUTPUT_DUMP = 30,
/*!< Dump the current input circular buffer to the specified FILE* structure */
FTDM_COMMAND_DUMP_INPUT,
FTDM_COMMAND_DUMP_INPUT = 31,
/*!< Dump the current output circular buffer to the specified FILE* structure */
FTDM_COMMAND_DUMP_OUTPUT,
FTDM_COMMAND_DUMP_OUTPUT = 32,
FTDM_COMMAND_ENABLE_CALLERID_DETECT,
FTDM_COMMAND_DISABLE_CALLERID_DETECT,
FTDM_COMMAND_ENABLE_ECHOCANCEL,
FTDM_COMMAND_DISABLE_ECHOCANCEL,
FTDM_COMMAND_ENABLE_ECHOTRAIN,
FTDM_COMMAND_DISABLE_ECHOTRAIN,
FTDM_COMMAND_SET_CAS_BITS,
FTDM_COMMAND_GET_CAS_BITS,
FTDM_COMMAND_SET_RX_GAIN,
FTDM_COMMAND_GET_RX_GAIN,
FTDM_COMMAND_SET_TX_GAIN,
FTDM_COMMAND_GET_TX_GAIN,
FTDM_COMMAND_FLUSH_TX_BUFFERS,
FTDM_COMMAND_FLUSH_RX_BUFFERS,
FTDM_COMMAND_FLUSH_BUFFERS,
FTDM_COMMAND_FLUSH_IOSTATS,
FTDM_COMMAND_SET_PRE_BUFFER_SIZE,
FTDM_COMMAND_SET_LINK_STATUS,
FTDM_COMMAND_GET_LINK_STATUS,
FTDM_COMMAND_ENABLE_LOOP,
FTDM_COMMAND_DISABLE_LOOP,
FTDM_COMMAND_SET_RX_QUEUE_SIZE,
FTDM_COMMAND_SET_TX_QUEUE_SIZE,
FTDM_COMMAND_SET_POLARITY,
FTDM_COMMAND_ENABLE_CALLERID_DETECT = 33,
FTDM_COMMAND_DISABLE_CALLERID_DETECT = 34,
FTDM_COMMAND_ENABLE_ECHOCANCEL = 35,
FTDM_COMMAND_DISABLE_ECHOCANCEL = 36,
FTDM_COMMAND_ENABLE_ECHOTRAIN = 37,
FTDM_COMMAND_DISABLE_ECHOTRAIN = 38,
FTDM_COMMAND_SET_CAS_BITS = 39,
FTDM_COMMAND_GET_CAS_BITS = 40,
FTDM_COMMAND_SET_RX_GAIN = 41,
FTDM_COMMAND_GET_RX_GAIN = 42,
FTDM_COMMAND_SET_TX_GAIN = 43,
FTDM_COMMAND_GET_TX_GAIN = 44,
FTDM_COMMAND_FLUSH_TX_BUFFERS = 45,
FTDM_COMMAND_FLUSH_RX_BUFFERS = 46,
FTDM_COMMAND_FLUSH_BUFFERS = 47,
FTDM_COMMAND_FLUSH_IOSTATS = 48,
FTDM_COMMAND_SET_PRE_BUFFER_SIZE = 49,
FTDM_COMMAND_SET_LINK_STATUS = 50,
FTDM_COMMAND_GET_LINK_STATUS = 51,
FTDM_COMMAND_ENABLE_LOOP = 52,
FTDM_COMMAND_DISABLE_LOOP = 53,
FTDM_COMMAND_SET_RX_QUEUE_SIZE = 54,
FTDM_COMMAND_SET_TX_QUEUE_SIZE = 55,
FTDM_COMMAND_SET_POLARITY = 56,
FTDM_COMMAND_COUNT,
} ftdm_command_t;
@ -772,8 +858,10 @@ FT_DECLARE(ftdm_status_t) ftdm_global_set_queue_handler(ftdm_queue_handler_t *ha
FT_DECLARE(int) ftdm_channel_get_availability(ftdm_channel_t *ftdmchan);
/*! \brief Answer call. This can also be accomplished by ftdm_channel_call_indicate with FTDM_CHANNEL_INDICATE_ANSWER, in both
* cases you will get a FTDM_SIGEVENT_INDICATION_COMPLETED when the indication is sent (or an error occurs)
* \note Although this API will result in FTDM_SIGEVENT_INDICATION_COMPLETED event being delivered,
* cases you will get a FTDM_SIGEVENT_INDICATION_COMPLETED when the indication is sent (or an error occurs).
* Just as with ftdm_channel_call_indicate you won't receive FTDM_SIGEVENT_INDICATION_COMPLETED when this function
* returns anything else than FTDM_SUCCESS
* \note Although this API may result in FTDM_SIGEVENT_INDICATION_COMPLETED event being delivered,
* there is no guarantee of whether the event will arrive after or before your execution thread returns
* from ftdm_channel_call_answer
*/
@ -782,12 +870,36 @@ FT_DECLARE(int) ftdm_channel_get_availability(ftdm_channel_t *ftdmchan);
/*! \brief Answer call recording the source code point where the it was called (see ftdm_channel_call_answer for an easy to use macro) */
FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan);
/*! \brief Place an outgoing call */
/*! \brief Place an outgoing call in the given channel
* \deprecated This macro is deprecated since leaves the door open to glare issues, use ftdm_call_place instead
*/
#define ftdm_channel_call_place(ftdmchan) _ftdm_channel_call_place(__FILE__, __FUNCTION__, __LINE__, (ftdmchan))
/*! \brief Place an outgoing call recording the source code point where it was called (see ftdm_channel_call_place for an easy to use macro) */
/*! \brief Place an outgoing call recording the source code point where it was called (see ftdm_channel_call_place for an easy to use macro)
* \deprecated This function is deprecated since leaves the door open to glare issues, use ftdm_call_place instead
*/
FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan);
/*! \brief Place an outgoing call with the given caller data in a channel according to the hunting scheme provided */
#define ftdm_call_place(callerdata, hunting) _ftdm_call_place(__FILE__, __FUNCTION__, __LINE__, (callerdata), (hunting))
/*! \brief Place an outgoing call with the given caller data in a channel according to the hunting scheme provided and records
* the place where it was called. See ftdm_call_place for an easy to use macro
* \return FTDM_SUCCESS if the call attempt was successful
* FTDM_FAIL if there was an unspecified error
* FTDM_EBUSY if the channel was busy
* FTDM_BREAK if glare was detected and you must try again
* \note Even when FTDM_SUCCESS is returned, the call may still fail later on due to glare, in such case FTDM_SIGEVENT_STOP
* will be sent with the hangup cause field set to FTDM_CAUSE_REQUESTED_CHAN_UNAVAIL
*
* \note When this function returns FTDM_SUCCESS, the member .fchan from caller_data will be set to the channel used to place the call
* and .call_id to the generated call id for that call
*
* \note When this function is successful you are guaranteed to receive FTDM_SIGEVENT_DIALING, this event could even be delivered
* before your execution thread returns from this function
*/
FT_DECLARE(ftdm_status_t) _ftdm_call_place(const char *file, const char *func, int line, ftdm_caller_data_t *caller_data, ftdm_hunting_scheme_t *hunting);
/*! \brief Indicate a new condition in an incoming call
*
* \note Every indication request will result in FTDM_SIGEVENT_INDICATION_COMPLETED event being delivered with
@ -972,6 +1084,9 @@ FT_DECLARE(ftdm_codec_t) ftdm_channel_get_codec(const ftdm_channel_t *ftdmchan);
/*!
* \brief Get the last error string for the channel
*
* \deprecated This API will disappear in the future and not every
* FreeTDM API set the last error value
*
* \param ftdmchan The channel to get the error from
*
* \retval The error string (not thread-safe, the string is per channel, not per thread)
@ -1044,6 +1159,9 @@ FT_DECLARE(ftdm_status_t) ftdm_span_find(uint32_t id, ftdm_span_t **span);
/*!
* \brief Get the last error string for the given span
*
* \deprecated This API will disappear in the future and not every
* FreeTDM API set the last error value
*
* \param span The span to get the last error from
*
* \retval character string for the last error
@ -1123,6 +1241,8 @@ FT_DECLARE(uint32_t) ftdm_group_get_id(const ftdm_group_t *group);
/*!
* \brief Open a channel specifying the span id and chan id (required before placing a call on the channel)
*
* \warning Try using ftdm_call_place instead if you plan to place a call after opening the channel
*
* \note You must call ftdm_channel_close() or ftdm_channel_call_hangup() to release the channel afterwards
* Only use ftdm_channel_close if there is no call (incoming or outgoing) in the channel
*
@ -1138,6 +1258,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open(uint32_t span_id, uint32_t chan_id,
/*!
* \brief Hunts and opens a channel specifying the span id only
*
* \warning Try using ftdm_call_place instead if you plan to place a call after opening the channel
*
* \note You must call ftdm_channel_close() or ftdm_channel_call_hangup() to release the channel afterwards
* Only use ftdm_channel_close if there is no call (incoming or outgoing) in the channel
*
@ -1154,6 +1276,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direc
/*!
* \brief Hunts and opens a channel specifying group id
*
* \warning Try using ftdm_call_place instead if you plan to place a call after opening the channel
*
* \note You must call ftdm_channel_close() or ftdm_channel_call_hangup() to release the channel afterwards
* Only use ftdm_channel_close if there is no call (incoming or outgoing) in the channel
*
@ -1170,8 +1294,11 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_group(uint32_t group_id, ftdm_dir
/*!
* \brief Close a previously open channel
*
* \note If you call ftdm_channel_call_hangup() you MUST NOT call this function, the signaling
* stack will close the channel.
* \warning FreeTDM is more and more a signaling API rather than just a plane IO API, unless you are using
* FreeTDM as a pure IO API without its signaling modules, you should not use this function
*
* \note If you placed a call in this channel use ftdm_channel_call_hangup(), you MUST NOT call this function,
* the signaling stack will close the channel when the call is done.
*
* \param ftdmchan pointer to the channel to close
*
@ -1341,7 +1468,9 @@ FT_DECLARE(const char *) ftdm_channel_get_number(const ftdm_channel_t *ftdmchan)
FT_DECLARE(uint32_t) ftdm_channel_get_ph_id(const ftdm_channel_t *ftdmchan);
/*!
* \brief Configure span with a signaling type (deprecated use ftdm_configure_span_signaling instead)
* \brief Configure span with a signaling type
*
* \deprecated use ftdm_configure_span_signaling instead
*
* \note This function does the same as ftdm_configure_span_signaling
*
@ -1542,7 +1671,7 @@ FT_DECLARE(const char *) ftdm_channel_get_last_state_str(const ftdm_channel_t *c
FT_DECLARE(char *) ftdm_channel_get_history_str(const ftdm_channel_t *channel);
/*! \brief Initialize channel state for an outgoing call
* \note This API will eventually be deprecated, is only needed if you use boost signaling
* \deprecated This API is only used for boost signaling
*/
FT_DECLARE(ftdm_status_t) ftdm_channel_init(ftdm_channel_t *ftdmchan);

@ -622,6 +622,9 @@ FT_DECLARE(ftdm_status_t) ftdm_span_trigger_signals(const ftdm_span_t *span);
/*! \brief clear the tone detector state */
FT_DECLARE(void) ftdm_channel_clear_detected_tones(ftdm_channel_t *ftdmchan);
/* start/stop echo cancelling at the beginning/end of a call */
FT_DECLARE(void) ftdm_set_echocancel_call_begin(ftdm_channel_t *chan);
FT_DECLARE(void) ftdm_set_echocancel_call_end(ftdm_channel_t *chan);
/*!
\brief Assert condition
@ -664,7 +667,11 @@ FT_DECLARE(void) ftdm_channel_clear_detected_tones(ftdm_channel_t *ftdmchan);
}
#define ftdm_log_chan_ex(fchan, file, func, line, level, format, ...) ftdm_log(file, func, line, level, "[s%dc%d][%d:%d] " format, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, __VA_ARGS__)
#define ftdm_log_chan_ex_msg(fchan, file, func, line, level, msg) ftdm_log(file, func, line, level, "[s%dc%d][%d:%d] " msg, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id)
#define ftdm_log_chan(fchan, level, format, ...) ftdm_log(level, "[s%dc%d][%d:%d] " format, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, __VA_ARGS__)
#define ftdm_log_chan_msg(fchan, level, msg) ftdm_log(level, "[s%dc%d][%d:%d] " msg, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id)
#define ftdm_log_chan_throttle(fchan, level, format, ...) ftdm_log_throttle(level, "[s%dc%d][%d:%d] " format, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, __VA_ARGS__)
@ -673,6 +680,14 @@ FT_DECLARE(void) ftdm_channel_clear_detected_tones(ftdm_channel_t *ftdmchan);
#define ftdm_span_lock(span) ftdm_mutex_lock(span->mutex)
#define ftdm_span_unlock(span) ftdm_mutex_unlock(span->mutex)
#define ftdm_test_and_set_media(fchan) \
do { \
if (!ftdm_test_flag((fchan), FTDM_CHANNEL_MEDIA)) { \
ftdm_set_flag((fchan), FTDM_CHANNEL_MEDIA); \
ftdm_set_echocancel_call_begin((fchan)); \
} \
} while (0);
FT_DECLARE_DATA extern const char *FTDM_LEVEL_NAMES[9];
static __inline__ void ftdm_abort(void)

@ -177,6 +177,12 @@ struct ftdm_state_map {
};
typedef struct ftdm_state_map ftdm_state_map_t;
/*!\brief Cancel the state processing for a channel (the channel must be locked when calling this function)
* \note Only the core should use this function
*/
FT_DECLARE(ftdm_status_t) ftdm_channel_cancel_state(const char *file, const char *func, int line,
ftdm_channel_t *ftdmchan);
/*!\brief Set the state for a channel (the channel must be locked when calling this function)
* \note Signaling modules should use ftdm_set_state macro instead
* \note If this function is called with the wait parameter set to a non-zero value, the recursivity

@ -186,6 +186,9 @@ typedef enum {
/* If this flag is set, the signalling module supports jumping directly to state up, without
going through PROGRESS/PROGRESS_MEDIA */
FTDM_SPAN_USE_SKIP_STATES = (1 << 12),
/* If this flag is set, then this span cannot be stopped individually, it can only be stopped
on freetdm unload */
FTDM_SPAN_NON_STOPPABLE = (1 << 13),
} ftdm_span_flag_t;
/*! \brief Channel supported features */
@ -224,16 +227,11 @@ typedef enum {
#define FTDM_CHANNEL_OUTBOUND (1ULL << 18)
#define FTDM_CHANNEL_SUSPENDED (1ULL << 19)
#define FTDM_CHANNEL_3WAY (1ULL << 20)
/* this 3 flags are really nonsense used by boost module only, as soon
* as we deprecate/delete boost module we can get rid of them
* ==================
* */
#define FTDM_CHANNEL_PROGRESS (1ULL << 21)
/*!< There is media on the channel already */
#define FTDM_CHANNEL_MEDIA (1ULL << 22)
/*!< The channel was answered */
#define FTDM_CHANNEL_ANSWERED (1ULL << 23)
/* ================== */
#define FTDM_CHANNEL_MUTE (1ULL << 24)
#define FTDM_CHANNEL_USE_RX_GAIN (1ULL << 25)
#define FTDM_CHANNEL_USE_TX_GAIN (1ULL << 26)

@ -1,6 +1,6 @@
/*
* libteletone
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@ -17,13 +17,13 @@
* The Original Code is libteletone
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
*
*
* libteletone.h -- Tone Generator/Detector

@ -1,6 +1,6 @@
/*
* libteletone
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* libteletone_detect.c Tone Detection Code
*

@ -1,6 +1,6 @@
/*
* libteletone
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Copyright (c) 2007, Anthony Minessale II
* All rights reserved.

@ -1,7 +1,7 @@
/*****************************************************************************
* sangoma_tdm_api.h Sangoma TDM API Portability functions
*
* Author(s): Anthony Minessale II <anthmct@yahoo.com>
* Author(s): Anthony Minessale II <anthm@freeswitch.org>
* Nenad Corbic <ncorbic@sangoma.com>
* Michael Jerris <mike@jerris.com>
* David Rokhvarg <davidr@sangoma.com>

@ -1,12 +1,12 @@
/*
* libteletone
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Much less efficient expansion interface was added to allow for the detection of
* a single arbitrary tone combination which may also exceed 2 simultaneous tones.
* (controlled by compile time constant TELETONE_MAX_TONES)
*
* Copyright (C) 2006 Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2006 Anthony Minessale II <anthm@freeswitch.org>
*
* libteletone_detect.c Tone Detection Code
*

@ -1,7 +1,7 @@
/*****************************************************************************
* priserver.c Refactoring of pritest.c
*
* Author(s): Anthony Minessale II <anthmct@yahoo.com>
* Author(s): Anthony Minessale II <anthm@freeswitch.org>
* Nenad Corbic <ncorbic@sangoma.com>
*
* Copyright: (c) 2005 Anthony Minessale II

@ -1,7 +1,7 @@
/*****************************************************************************
* sangoma_pri.c libpri Sangoma integration
*
* Author(s): Anthony Minessale II <anthmct@yahoo.com>
* Author(s): Anthony Minessale II <anthm@freeswitch.org>
* Nenad Corbic <ncorbic@sangoma.com>
*
* Copyright: (c) 2005 Anthony Minessale II

@ -1,7 +1,7 @@
/*****************************************************************************
* libsangoma.c AFT T1/E1: HDLC API Code Library
*
* Author(s): Anthony Minessale II <anthmct@yahoo.com>
* Author(s): Anthony Minessale II <anthm@freeswitch.org>
* Nenad Corbic <ncorbic@sangoma.com>
*
* Copyright: (c) 2005 Anthony Minessale II

@ -1,42 +1,42 @@
/ -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
/
/ 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 the Netscape Portable Runtime (NSPR).
/
/ The Initial Developer of the Original Code is Netscape
/ Communications Corporation. Portions created by Netscape are
/ Copyright (C) 2000 Netscape Communications Corporation. All
/ Rights Reserved.
/
/ Contributor(s):
/
/ Alternatively, the contents of this file may be used under the
/ terms of the GNU General Public License Version 2 or later (the
/ "GPL"), in which case the provisions of the GPL are applicable
/ instead of those above. If you wish to allow use of your
/ version of this file only under the terms of the GPL and not to
/ allow others to use your version of this file under the MPL,
/ indicate your decision by deleting the provisions above and
/ replace them with the notice and other provisions required by
/ the GPL. If you do not delete the provisions above, a recipient
/ may use your version of this file under either the MPL or the
/ GPL.
/
// -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
//
// 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 the Netscape Portable Runtime (NSPR).
//
// The Initial Developer of the Original Code is Netscape
// Communications Corporation. Portions created by Netscape are
// Copyright (C) 2000 Netscape Communications Corporation. All
// Rights Reserved.
//
// Contributor(s):
//
// Alternatively, the contents of this file may be used under the
// terms of the GNU General Public License Version 2 or later (the
// "GPL"), in which case the provisions of the GPL are applicable
// instead of those above. If you wish to allow use of your
// version of this file only under the terms of the GPL and not to
// allow others to use your version of this file under the MPL,
// indicate your decision by deleting the provisions above and
// replace them with the notice and other provisions required by
// the GPL. If you do not delete the provisions above, a recipient
// may use your version of this file under either the MPL or the
// GPL.
//
/ PRInt32 _PR_x86_AtomicIncrement(PRInt32 *val)
/
/ Atomically increment the integer pointed to by 'val' and return
/ the result of the increment.
/
// PRInt32 _PR_x86_AtomicIncrement(PRInt32 *val)
//
// Atomically increment the integer pointed to by 'val' and return
// the result of the increment.
//
.text
.globl _PR_x86_AtomicIncrement
.align 4
@ -48,11 +48,11 @@ _PR_x86_AtomicIncrement:
incl %eax
ret
/ PRInt32 _PR_x86_AtomicDecrement(PRInt32 *val)
/
/ Atomically decrement the integer pointed to by 'val' and return
/ the result of the decrement.
/
// PRInt32 _PR_x86_AtomicDecrement(PRInt32 *val)
//
// Atomically decrement the integer pointed to by 'val' and return
// the result of the decrement.
//
.text
.globl _PR_x86_AtomicDecrement
.align 4
@ -64,25 +64,25 @@ _PR_x86_AtomicDecrement:
decl %eax
ret
/ PRInt32 _PR_x86_AtomicSet(PRInt32 *val, PRInt32 newval)
/
/ Atomically set the integer pointed to by 'val' to the new
/ value 'newval' and return the old value.
/
/ An alternative implementation:
/ .text
/ .globl _PR_x86_AtomicSet
/ .align 4
/_PR_x86_AtomicSet:
/ movl 4(%esp), %ecx
/ movl 8(%esp), %edx
/ movl (%ecx), %eax
/retry:
/ lock
/ cmpxchgl %edx, (%ecx)
/ jne retry
/ ret
/
// PRInt32 _PR_x86_AtomicSet(PRInt32 *val, PRInt32 newval)
//
// Atomically set the integer pointed to by 'val' to the new
// value 'newval' and return the old value.
//
// An alternative implementation:
// .text
// .globl _PR_x86_AtomicSet
// .align 4
//_PR_x86_AtomicSet:
// movl 4(%esp), %ecx
// movl 8(%esp), %edx
// movl (%ecx), %eax
//retry:
// lock
// cmpxchgl %edx, (%ecx)
// jne retry
// ret
//
.text
.globl _PR_x86_AtomicSet
.align 4
@ -92,11 +92,11 @@ _PR_x86_AtomicSet:
xchgl %eax, (%ecx)
ret
/ PRInt32 _PR_x86_AtomicAdd(PRInt32 *ptr, PRInt32 val)
/
/ Atomically add 'val' to the integer pointed to by 'ptr'
/ and return the result of the addition.
/
// PRInt32 _PR_x86_AtomicAdd(PRInt32 *ptr, PRInt32 val)
//
// Atomically add 'val' to the integer pointed to by 'ptr'
// and return the result of the addition.
//
.text
.globl _PR_x86_AtomicAdd
.align 4
@ -109,5 +109,5 @@ _PR_x86_AtomicAdd:
addl %edx, %eax
ret
/ Magic indicating no need for an executable stack
// Magic indicating no need for an executable stack
.section .note.GNU-stack, "", @progbits ; .previous

@ -1,42 +1,42 @@
/ -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
/
/ 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 the Netscape Portable Runtime (NSPR).
/
/ The Initial Developer of the Original Code is Netscape
/ Communications Corporation. Portions created by Netscape are
/ Copyright (C) 2004 Netscape Communications Corporation. All
/ Rights Reserved.
/
/ Contributor(s):
/
/ Alternatively, the contents of this file may be used under the
/ terms of the GNU General Public License Version 2 or later (the
/ "GPL"), in which case the provisions of the GPL are applicable
/ instead of those above. If you wish to allow use of your
/ version of this file only under the terms of the GPL and not to
/ allow others to use your version of this file under the MPL,
/ indicate your decision by deleting the provisions above and
/ replace them with the notice and other provisions required by
/ the GPL. If you do not delete the provisions above, a recipient
/ may use your version of this file under either the MPL or the
/ GPL.
/
// -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
//
// 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 the Netscape Portable Runtime (NSPR).
//
// The Initial Developer of the Original Code is Netscape
// Communications Corporation. Portions created by Netscape are
// Copyright (C) 2004 Netscape Communications Corporation. All
// Rights Reserved.
//
// Contributor(s):
//
// Alternatively, the contents of this file may be used under the
// terms of the GNU General Public License Version 2 or later (the
// "GPL"), in which case the provisions of the GPL are applicable
// instead of those above. If you wish to allow use of your
// version of this file only under the terms of the GPL and not to
// allow others to use your version of this file under the MPL,
// indicate your decision by deleting the provisions above and
// replace them with the notice and other provisions required by
// the GPL. If you do not delete the provisions above, a recipient
// may use your version of this file under either the MPL or the
// GPL.
//
/ PRInt32 _PR_x86_64_AtomicIncrement(PRInt32 *val)
/
/ Atomically increment the integer pointed to by 'val' and return
/ the result of the increment.
/
// PRInt32 _PR_x86_64_AtomicIncrement(PRInt32 *val)
//
// Atomically increment the integer pointed to by 'val' and return
// the result of the increment.
//
.text
.globl _PR_x86_64_AtomicIncrement
.align 4
@ -47,11 +47,11 @@ _PR_x86_64_AtomicIncrement:
incl %eax
ret
/ PRInt32 _PR_x86_64_AtomicDecrement(PRInt32 *val)
/
/ Atomically decrement the integer pointed to by 'val' and return
/ the result of the decrement.
/
// PRInt32 _PR_x86_64_AtomicDecrement(PRInt32 *val)
//
// Atomically decrement the integer pointed to by 'val' and return
// the result of the decrement.
//
.text
.globl _PR_x86_64_AtomicDecrement
.align 4
@ -62,11 +62,11 @@ _PR_x86_64_AtomicDecrement:
decl %eax
ret
/ PRInt32 _PR_x86_64_AtomicSet(PRInt32 *val, PRInt32 newval)
/
/ Atomically set the integer pointed to by 'val' to the new
/ value 'newval' and return the old value.
/
// PRInt32 _PR_x86_64_AtomicSet(PRInt32 *val, PRInt32 newval)
//
// Atomically set the integer pointed to by 'val' to the new
// value 'newval' and return the old value.
//
.text
.globl _PR_x86_64_AtomicSet
.align 4
@ -75,11 +75,11 @@ _PR_x86_64_AtomicSet:
xchgl %eax, (%rdi)
ret
/ PRInt32 _PR_x86_64_AtomicAdd(PRInt32 *ptr, PRInt32 val)
/
/ Atomically add 'val' to the integer pointed to by 'ptr'
/ and return the result of the addition.
/
// PRInt32 _PR_x86_64_AtomicAdd(PRInt32 *ptr, PRInt32 val)
//
// Atomically add 'val' to the integer pointed to by 'ptr'
// and return the result of the addition.
//
.text
.globl _PR_x86_64_AtomicAdd
.align 4
@ -90,5 +90,5 @@ _PR_x86_64_AtomicAdd:
addl %esi, %eax
ret
/ Magic indicating no need for an executable stack
/.section .note.GNU-stack, "", @progbits ; .previous
// Magic indicating no need for an executable stack
//.section .note.GNU-stack, "", @progbits ; .previous

@ -1,36 +1,36 @@
/ -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
/
/ 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 the Netscape Portable Runtime (NSPR).
/
/ The Initial Developer of the Original Code is Netscape
/ Communications Corporation. Portions created by Netscape are
/ Copyright (C) 1998-2000 Netscape Communications Corporation. All
/ Rights Reserved.
/
/ Contributor(s):
/
/ Alternatively, the contents of this file may be used under the
/ terms of the GNU General Public License Version 2 or later (the
/ "GPL"), in which case the provisions of the GPL are applicable
/ instead of those above. If you wish to allow use of your
/ version of this file only under the terms of the GPL and not to
/ allow others to use your version of this file under the MPL,
/ indicate your decision by deleting the provisions above and
/ replace them with the notice and other provisions required by
/ the GPL. If you do not delete the provisions above, a recipient
/ may use your version of this file under either the MPL or the
/ GPL.
/
// -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
//
// 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 the Netscape Portable Runtime (NSPR).
//
// The Initial Developer of the Original Code is Netscape
// Communications Corporation. Portions created by Netscape are
// Copyright (C) 1998-2000 Netscape Communications Corporation. All
// Rights Reserved.
//
// Contributor(s):
//
// Alternatively, the contents of this file may be used under the
// terms of the GNU General Public License Version 2 or later (the
// "GPL"), in which case the provisions of the GPL are applicable
// instead of those above. If you wish to allow use of your
// version of this file only under the terms of the GPL and not to
// allow others to use your version of this file under the MPL,
// indicate your decision by deleting the provisions above and
// replace them with the notice and other provisions required by
// the GPL. If you do not delete the provisions above, a recipient
// may use your version of this file under either the MPL or the
// GPL.
//
.text
@ -56,31 +56,31 @@ _MD_FlushRegisterWindows:
ret
/
/ sol_getsp()
/
/ Return the current sp (for debugging)
/
//
// sol_getsp()
//
// Return the current sp (for debugging)
//
.globl sol_getsp
sol_getsp:
movl %esp, %eax
ret
/
/ sol_curthread()
/
/ Return a unique identifier for the currently active thread.
/
//
// sol_curthread()
//
// Return a unique identifier for the currently active thread.
//
.globl sol_curthread
sol_curthread:
movl %ecx, %eax
ret
/ PRInt32 _MD_AtomicIncrement(PRInt32 *val)
/
/ Atomically increment the integer pointed to by 'val' and return
/ the result of the increment.
/
// PRInt32 _MD_AtomicIncrement(PRInt32 *val)
//
// Atomically increment the integer pointed to by 'val' and return
// the result of the increment.
//
.text
.globl _MD_AtomicIncrement
.align 4
@ -92,11 +92,11 @@ _MD_AtomicIncrement:
incl %eax
ret
/ PRInt32 _MD_AtomicDecrement(PRInt32 *val)
/
/ Atomically decrement the integer pointed to by 'val' and return
/ the result of the decrement.
/
// PRInt32 _MD_AtomicDecrement(PRInt32 *val)
//
// Atomically decrement the integer pointed to by 'val' and return
// the result of the decrement.
//
.text
.globl _MD_AtomicDecrement
.align 4
@ -108,25 +108,25 @@ _MD_AtomicDecrement:
decl %eax
ret
/ PRInt32 _MD_AtomicSet(PRInt32 *val, PRInt32 newval)
/
/ Atomically set the integer pointed to by 'val' to the new
/ value 'newval' and return the old value.
/
/ An alternative implementation:
/ .text
/ .globl _MD_AtomicSet
/ .align 4
/_MD_AtomicSet:
/ movl 4(%esp), %ecx
/ movl 8(%esp), %edx
/ movl (%ecx), %eax
/retry:
/ lock
/ cmpxchgl %edx, (%ecx)
/ jne retry
/ ret
/
// PRInt32 _MD_AtomicSet(PRInt32 *val, PRInt32 newval)
//
// Atomically set the integer pointed to by 'val' to the new
// value 'newval' and return the old value.
//
// An alternative implementation:
// .text
// .globl _MD_AtomicSet
// .align 4
//_MD_AtomicSet:
// movl 4(%esp), %ecx
// movl 8(%esp), %edx
// movl (%ecx), %eax
//retry:
// lock
// cmpxchgl %edx, (%ecx)
// jne retry
// ret
//
.text
.globl _MD_AtomicSet
.align 4
@ -136,11 +136,11 @@ _MD_AtomicSet:
xchgl %eax, (%ecx)
ret
/ PRInt32 _MD_AtomicAdd(PRInt32 *ptr, PRInt32 val)
/
/ Atomically add 'val' to the integer pointed to by 'ptr'
/ and return the result of the addition.
/
// PRInt32 _MD_AtomicAdd(PRInt32 *ptr, PRInt32 val)
//
// Atomically add 'val' to the integer pointed to by 'ptr'
// and return the result of the addition.
//
.text
.globl _MD_AtomicAdd
.align 4

@ -1,42 +1,42 @@
/ -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
/
/ 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 the Netscape Portable Runtime (NSPR).
/
/ The Initial Developer of the Original Code is Netscape
/ Communications Corporation. Portions created by Netscape are
/ Copyright (C) 2004 Netscape Communications Corporation. All
/ Rights Reserved.
/
/ Contributor(s):
/
/ Alternatively, the contents of this file may be used under the
/ terms of the GNU General Public License Version 2 or later (the
/ "GPL"), in which case the provisions of the GPL are applicable
/ instead of those above. If you wish to allow use of your
/ version of this file only under the terms of the GPL and not to
/ allow others to use your version of this file under the MPL,
/ indicate your decision by deleting the provisions above and
/ replace them with the notice and other provisions required by
/ the GPL. If you do not delete the provisions above, a recipient
/ may use your version of this file under either the MPL or the
/ GPL.
/
// -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
//
// 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 the Netscape Portable Runtime (NSPR).
//
// The Initial Developer of the Original Code is Netscape
// Communications Corporation. Portions created by Netscape are
// Copyright (C) 2004 Netscape Communications Corporation. All
// Rights Reserved.
//
// Contributor(s):
//
// Alternatively, the contents of this file may be used under the
// terms of the GNU General Public License Version 2 or later (the
// "GPL"), in which case the provisions of the GPL are applicable
// instead of those above. If you wish to allow use of your
// version of this file only under the terms of the GPL and not to
// allow others to use your version of this file under the MPL,
// indicate your decision by deleting the provisions above and
// replace them with the notice and other provisions required by
// the GPL. If you do not delete the provisions above, a recipient
// may use your version of this file under either the MPL or the
// GPL.
//
/ PRInt32 _MD_AtomicIncrement(PRInt32 *val)
/
/ Atomically increment the integer pointed to by 'val' and return
/ the result of the increment.
/
// PRInt32 _MD_AtomicIncrement(PRInt32 *val)
//
// Atomically increment the integer pointed to by 'val' and return
// the result of the increment.
//
.text
.globl _MD_AtomicIncrement
.align 4
@ -47,11 +47,11 @@ _MD_AtomicIncrement:
incl %eax
ret
/ PRInt32 _MD_AtomicDecrement(PRInt32 *val)
/
/ Atomically decrement the integer pointed to by 'val' and return
/ the result of the decrement.
/
// PRInt32 _MD_AtomicDecrement(PRInt32 *val)
//
// Atomically decrement the integer pointed to by 'val' and return
// the result of the decrement.
//
.text
.globl _MD_AtomicDecrement
.align 4
@ -62,11 +62,11 @@ _MD_AtomicDecrement:
decl %eax
ret
/ PRInt32 _MD_AtomicSet(PRInt32 *val, PRInt32 newval)
/
/ Atomically set the integer pointed to by 'val' to the new
/ value 'newval' and return the old value.
/
// PRInt32 _MD_AtomicSet(PRInt32 *val, PRInt32 newval)
//
// Atomically set the integer pointed to by 'val' to the new
// value 'newval' and return the old value.
//
.text
.globl _MD_AtomicSet
.align 4
@ -75,11 +75,11 @@ _MD_AtomicSet:
xchgl %eax, (%rdi)
ret
/ PRInt32 _MD_AtomicAdd(PRInt32 *ptr, PRInt32 val)
/
/ Atomically add 'val' to the integer pointed to by 'ptr'
/ and return the result of the addition.
/
// PRInt32 _MD_AtomicAdd(PRInt32 *ptr, PRInt32 val)
//
// Atomically add 'val' to the integer pointed to by 'ptr'
// and return the result of the addition.
//
.text
.globl _MD_AtomicAdd
.align 4

@ -1,6 +1,6 @@
/*
* libDingaLing XMPP Jingle Library
* Copyright (C) 2005/2006, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*

@ -1,6 +1,6 @@
/*
* libDingaLing XMPP Jingle Library
* Copyright (C) 2005/2006, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*

@ -1,6 +1,6 @@
/*
* libDingaLing XMPP Jingle Library
* Copyright (C) 2005/2006, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*

@ -1,6 +1,6 @@
/*
* libteletone
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@ -17,13 +17,13 @@
* The Original Code is libteletone
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
*
*
* libteletone.h -- Tone Generator/Detector

@ -1,6 +1,6 @@
/*
* libteletone
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@ -32,7 +32,7 @@
* a single arbitrary tone combination which may also exceed 2 simultaneous tones.
* (controlled by compile time constant TELETONE_MAX_TONES)
*
* Copyright (C) 2006 Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2006 Anthony Minessale II <anthm@freeswitch.org>
*
*
* libteletone_detect.c Tone Detection Code

@ -1,6 +1,6 @@
/*
* libteletone
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@ -32,7 +32,7 @@
* a single arbitrary tone combination which may also exceed 2 simultaneous tones.
* (controlled by compile time constant TELETONE_MAX_TONES)
*
* Copyright (C) 2006 Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2006 Anthony Minessale II <anthm@freeswitch.org>
*
*
* libteletone_detect.c Tone Detection Code

@ -1,6 +1,6 @@
/*
* libteletone
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@ -17,13 +17,13 @@
* The Original Code is libteletone
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
*
*
* libteletone.c -- Tone Generator

@ -1,6 +1,6 @@
/*
* libteletone
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@ -17,13 +17,13 @@
* The Original Code is libteletone
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
*
*
* libteletone.h -- Tone Generator

@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@ -17,13 +17,13 @@
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
* Moises Silva <moy@sangoma.com>
*
*

@ -1,6 +1,6 @@
/*
* libteletone
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@ -17,13 +17,13 @@
* The Original Code is libteletone
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
*
*
* libteletone.h -- Tone Generator/Detector

@ -1,6 +1,6 @@
/*
* libteletone
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* libteletone_detect.c Tone Detection Code
*

@ -1,6 +1,6 @@
/*
* libteletone
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Copyright (c) 2007, Anthony Minessale II
* All rights reserved.

@ -1,7 +1,7 @@
/*****************************************************************************
* sangoma_tdm_api.h Sangoma TDM API Portability functions
*
* Author(s): Anthony Minessale II <anthmct@yahoo.com>
* Author(s): Anthony Minessale II <anthm@freeswitch.org>
* Nenad Corbic <ncorbic@sangoma.com>
* Michael Jerris <mike@jerris.com>
* David Rokhvarg <davidr@sangoma.com>

@ -1,12 +1,12 @@
/*
* libteletone
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Much less efficient expansion interface was added to allow for the detection of
* a single arbitrary tone combination which may also exceed 2 simultaneous tones.
* (controlled by compile time constant TELETONE_MAX_TONES)
*
* Copyright (C) 2006 Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2006 Anthony Minessale II <anthm@freeswitch.org>
*
* libteletone_detect.c Tone Detection Code
*

@ -1,7 +1,7 @@
/*****************************************************************************
* priserver.c Refactoring of pritest.c
*
* Author(s): Anthony Minessale II <anthmct@yahoo.com>
* Author(s): Anthony Minessale II <anthm@freeswitch.org>
* Nenad Corbic <ncorbic@sangoma.com>
*
* Copyright: (c) 2005 Anthony Minessale II

@ -1,7 +1,7 @@
/*****************************************************************************
* sangoma_pri.c libpri Sangoma integration
*
* Author(s): Anthony Minessale II <anthmct@yahoo.com>
* Author(s): Anthony Minessale II <anthm@freeswitch.org>
* Nenad Corbic <ncorbic@sangoma.com>
*
* Copyright: (c) 2005 Anthony Minessale II

@ -1,7 +1,7 @@
/*****************************************************************************
* libsangoma.c AFT T1/E1: HDLC API Code Library
*
* Author(s): Anthony Minessale II <anthmct@yahoo.com>
* Author(s): Anthony Minessale II <anthm@freeswitch.org>
* Nenad Corbic <ncorbic@sangoma.com>
*
* Copyright: (c) 2005 Anthony Minessale II

@ -76,7 +76,7 @@
<Tool
Name="VCCustomBuildTool"
Description="Downloading CELT."
CommandLine="if not exist &quot;$(ProjectDir)..\celt-0.7.1&quot; cscript /nologo &quot;$(ProjectDir)util.vbs&quot; GetUnzip http://files.freeswitch.org/downloads/libs/celt-0.7.1.tar.gz &quot;$(ProjectDir)..&quot;&#x0D;&#x0A;xcopy &quot;$(ProjectDir)\celt\config.h&quot; &quot;$(ProjectDir)..\celt-0.7.1\libcelt&quot; /C /D /Y /S /I&#x0D;&#x0A;xcopy &quot;$(ProjectDir)\celt\float_cast.h&quot; &quot;$(ProjectDir)..\celt-0.7.1\libcelt&quot; /C /D /Y /S /I&#x0D;&#x0A;"
CommandLine="if not exist &quot;$(ProjectDir)..\celt-0.10.0&quot; cscript /nologo &quot;$(ProjectDir)util.vbs&quot; GetUnzip http://files.freeswitch.org/downloads/libs/celt-0.10.0.tar.gz &quot;$(ProjectDir)..&quot;&#x0D;&#x0A;xcopy &quot;$(ProjectDir)\celt\config.h&quot; &quot;$(ProjectDir)..\celt-0.10.0\libcelt&quot; /C /D /Y /S /I&#x0D;&#x0A;xcopy &quot;$(ProjectDir)\celt\float_cast.h&quot; &quot;$(ProjectDir)..\celt-0.10.0\libcelt&quot; /C /D /Y /S /I&#x0D;&#x0A;"
Outputs="$(ProjectDir)..\CELT"
/>
</FileConfiguration>
@ -86,7 +86,7 @@
<Tool
Name="VCCustomBuildTool"
Description="Downloading CELT."
CommandLine="if not exist &quot;$(ProjectDir)..\celt-0.7.1&quot; cscript /nologo &quot;$(ProjectDir)util.vbs&quot; GetUnzip http://files.freeswitch.org/downloads/libs/celt-0.7.1.tar.gz &quot;$(ProjectDir)..&quot;&#x0D;&#x0A;xcopy &quot;$(ProjectDir)\celt\config.h&quot; &quot;$(ProjectDir)..\celt-0.7.1\libcelt&quot; /C /D /Y /S /I&#x0D;&#x0A;xcopy &quot;$(ProjectDir)\celt\float_cast.h&quot; &quot;$(ProjectDir)..\celt-0.7.1\libcelt&quot; /C /D /Y /S /I&#x0D;&#x0A;"
CommandLine="if not exist &quot;$(ProjectDir)..\celt-0.10.0&quot; cscript /nologo &quot;$(ProjectDir)util.vbs&quot; GetUnzip http://files.freeswitch.org/downloads/libs/celt-0.10.0.tar.gz &quot;$(ProjectDir)..&quot;&#x0D;&#x0A;xcopy &quot;$(ProjectDir)\celt\config.h&quot; &quot;$(ProjectDir)..\celt-0.10.0\libcelt&quot; /C /D /Y /S /I&#x0D;&#x0A;xcopy &quot;$(ProjectDir)\celt\float_cast.h&quot; &quot;$(ProjectDir)..\celt-0.10.0\libcelt&quot; /C /D /Y /S /I&#x0D;&#x0A;"
Outputs="$(ProjectDir)..\CELT"
/>
</FileConfiguration>

@ -65,15 +65,15 @@
<CustomBuild Include="cleancount">
<FileType>Document</FileType>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Downloading CELT.</Message>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">if not exist "$(ProjectDir)..\celt-0.7.1" cscript /nologo "$(ProjectDir)util.vbs" GetUnzip http://files.freeswitch.org/downloads/libs/celt-0.7.1.tar.gz "$(ProjectDir).."
xcopy "$(ProjectDir)\celt\config.h" "$(ProjectDir)..\celt-0.7.1\libcelt" /C /D /Y /S /I
xcopy "$(ProjectDir)\celt\float_cast.h" "$(ProjectDir)..\celt-0.7.1\libcelt" /C /D /Y /S /I
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">if not exist "$(ProjectDir)..\celt-0.10.0" cscript /nologo "$(ProjectDir)util.vbs" GetUnzip http://files.freeswitch.org/downloads/libs/celt-0.10.0.tar.gz "$(ProjectDir).."
xcopy "$(ProjectDir)\celt\config.h" "$(ProjectDir)..\celt-0.10.0\libcelt" /C /D /Y /S /I
xcopy "$(ProjectDir)\celt\float_cast.h" "$(ProjectDir)..\celt-0.10.0\libcelt" /C /D /Y /S /I
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)..\CELT;%(Outputs)</Outputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Downloading CELT.</Message>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">if not exist "$(ProjectDir)..\celt-0.7.1" cscript /nologo "$(ProjectDir)util.vbs" GetUnzip http://files.freeswitch.org/downloads/libs/celt-0.7.1.tar.gz "$(ProjectDir).."
xcopy "$(ProjectDir)\celt\config.h" "$(ProjectDir)..\celt-0.7.1\libcelt" /C /D /Y /S /I
xcopy "$(ProjectDir)\celt\float_cast.h" "$(ProjectDir)..\celt-0.7.1\libcelt" /C /D /Y /S /I
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">if not exist "$(ProjectDir)..\celt-0.10.0" cscript /nologo "$(ProjectDir)util.vbs" GetUnzip http://files.freeswitch.org/downloads/libs/celt-0.10.0.tar.gz "$(ProjectDir).."
xcopy "$(ProjectDir)\celt\config.h" "$(ProjectDir)..\celt-0.10.0\libcelt" /C /D /Y /S /I
xcopy "$(ProjectDir)\celt\float_cast.h" "$(ProjectDir)..\celt-0.10.0\libcelt" /C /D /Y /S /I
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)..\CELT;%(Outputs)</Outputs>
</CustomBuild>

@ -44,7 +44,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\celt-0.7.1\libcelt"
AdditionalIncludeDirectories="..\..\celt-0.10.0\libcelt"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;HAVE_CONFIG_H"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@ -107,7 +107,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\celt-0.7.1\libcelt"
AdditionalIncludeDirectories="..\..\celt-0.10.0\libcelt"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;_AMD64_;_WIN64"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@ -171,7 +171,7 @@
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="&quot;..\..\celt-0.7.1\libcelt&quot;"
AdditionalIncludeDirectories="&quot;..\..\celt-0.10.0\libcelt&quot;"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;HAVE_CONFIG_H"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
@ -235,7 +235,7 @@
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="&quot;..\..\celt-0.7.1\libcelt&quot;"
AdditionalIncludeDirectories="&quot;..\..\celt-0.10.0\libcelt&quot;"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;_AMD64_;_WIN64"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
@ -281,71 +281,79 @@
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\..\celt-0.7.1\libcelt\bands.c"
RelativePath="..\..\celt-0.10.0\libcelt\bands.c"
>
</File>
<File
RelativePath="..\..\celt-0.7.1\libcelt\celt.c"
RelativePath="..\..\celt-0.10.0\libcelt\celt.c"
>
</File>
<File
RelativePath="..\..\celt-0.7.1\libcelt\cwrs.c"
RelativePath="..\..\celt-0.10.0\libcelt\cwrs.c"
>
</File>
<File
RelativePath="..\..\celt-0.7.1\libcelt\entcode.c"
RelativePath="..\..\celt-0.10.0\libcelt\entcode.c"
>
</File>
<File
RelativePath="..\..\celt-0.7.1\libcelt\entdec.c"
RelativePath="..\..\celt-0.10.0\libcelt\entdec.c"
>
</File>
<File
RelativePath="..\..\celt-0.7.1\libcelt\entenc.c"
RelativePath="..\..\celt-0.10.0\libcelt\entenc.c"
>
</File>
<File
RelativePath="..\..\celt-0.7.1\libcelt\header.c"
RelativePath="..\..\celt-0.10.0\libcelt\header.c"
>
</File>
<File
RelativePath="..\..\celt-0.7.1\libcelt\kiss_fft.c"
RelativePath="..\..\celt-0.10.0\libcelt\kiss_fft.c"
>
</File>
<File
RelativePath="..\..\celt-0.7.1\libcelt\laplace.c"
RelativePath="..\..\celt-0.10.0\libcelt\laplace.c"
>
</File>
<File
RelativePath="..\..\celt-0.7.1\libcelt\mdct.c"
RelativePath="..\..\celt-0.10.0\libcelt\mathops.c"
>
</File>
<File
RelativePath="..\..\celt-0.7.1\libcelt\modes.c"
RelativePath="..\..\celt-0.10.0\libcelt\mdct.c"
>
</File>
<File
RelativePath="..\..\celt-0.7.1\libcelt\pitch.c"
RelativePath="..\..\celt-0.10.0\libcelt\modes.c"
>
</File>
<File
RelativePath="..\..\celt-0.7.1\libcelt\quant_bands.c"
RelativePath="..\..\celt-0.10.0\libcelt\pitch.c"
>
</File>
<File
RelativePath="..\..\celt-0.7.1\libcelt\rangedec.c"
RelativePath="..\..\celt-0.10.0\libcelt\plc.c"
>
</File>
<File
RelativePath="..\..\celt-0.7.1\libcelt\rangeenc.c"
RelativePath="..\..\celt-0.10.0\libcelt\quant_bands.c"
>
</File>
<File
RelativePath="..\..\celt-0.7.1\libcelt\rate.c"
RelativePath="..\..\celt-0.10.0\libcelt\rangedec.c"
>
</File>
<File
RelativePath="..\..\celt-0.7.1\libcelt\vq.c"
RelativePath="..\..\celt-0.10.0\libcelt\rangeenc.c"
>
</File>
<File
RelativePath="..\..\celt-0.10.0\libcelt\rate.c"
>
</File>
<File
RelativePath="..\..\celt-0.10.0\libcelt\vq.c"
>
</File>
</Filter>

@ -68,7 +68,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\celt-0.7.1\libcelt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\celt-0.10.0\libcelt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
@ -82,7 +82,7 @@
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\celt-0.7.1\libcelt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\celt-0.10.0\libcelt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;_AMD64_;_WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
@ -94,7 +94,7 @@
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..\celt-0.7.1\libcelt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\celt-0.10.0\libcelt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@ -108,7 +108,7 @@
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..\celt-0.7.1\libcelt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\celt-0.10.0\libcelt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;_AMD64_;_WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@ -116,23 +116,25 @@
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\celt-0.7.1\libcelt\bands.c" />
<ClCompile Include="..\..\celt-0.7.1\libcelt\celt.c" />
<ClCompile Include="..\..\celt-0.7.1\libcelt\cwrs.c" />
<ClCompile Include="..\..\celt-0.7.1\libcelt\entcode.c" />
<ClCompile Include="..\..\celt-0.7.1\libcelt\entdec.c" />
<ClCompile Include="..\..\celt-0.7.1\libcelt\entenc.c" />
<ClCompile Include="..\..\celt-0.7.1\libcelt\header.c" />
<ClCompile Include="..\..\celt-0.7.1\libcelt\kiss_fft.c" />
<ClCompile Include="..\..\celt-0.7.1\libcelt\laplace.c" />
<ClCompile Include="..\..\celt-0.7.1\libcelt\mdct.c" />
<ClCompile Include="..\..\celt-0.7.1\libcelt\modes.c" />
<ClCompile Include="..\..\celt-0.7.1\libcelt\pitch.c" />
<ClCompile Include="..\..\celt-0.7.1\libcelt\quant_bands.c" />
<ClCompile Include="..\..\celt-0.7.1\libcelt\rangedec.c" />
<ClCompile Include="..\..\celt-0.7.1\libcelt\rangeenc.c" />
<ClCompile Include="..\..\celt-0.7.1\libcelt\rate.c" />
<ClCompile Include="..\..\celt-0.7.1\libcelt\vq.c" />
<ClCompile Include="..\..\celt-0.10.0\libcelt\bands.c" />
<ClCompile Include="..\..\celt-0.10.0\libcelt\celt.c" />
<ClCompile Include="..\..\celt-0.10.0\libcelt\cwrs.c" />
<ClCompile Include="..\..\celt-0.10.0\libcelt\entcode.c" />
<ClCompile Include="..\..\celt-0.10.0\libcelt\entdec.c" />
<ClCompile Include="..\..\celt-0.10.0\libcelt\entenc.c" />
<ClCompile Include="..\..\celt-0.10.0\libcelt\header.c" />
<ClCompile Include="..\..\celt-0.10.0\libcelt\kiss_fft.c" />
<ClCompile Include="..\..\celt-0.10.0\libcelt\laplace.c" />
<ClCompile Include="..\..\celt-0.10.0\libcelt\mathops.c" />
<ClCompile Include="..\..\celt-0.10.0\libcelt\mdct.c" />
<ClCompile Include="..\..\celt-0.10.0\libcelt\modes.c" />
<ClCompile Include="..\..\celt-0.10.0\libcelt\pitch.c" />
<ClCompile Include="..\..\celt-0.10.0\libcelt\plc.c" />
<ClCompile Include="..\..\celt-0.10.0\libcelt\quant_bands.c" />
<ClCompile Include="..\..\celt-0.10.0\libcelt\rangedec.c" />
<ClCompile Include="..\..\celt-0.10.0\libcelt\rangeenc.c" />
<ClCompile Include="..\..\celt-0.10.0\libcelt\rate.c" />
<ClCompile Include="..\..\celt-0.10.0\libcelt\vq.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Download CELT.vcxproj">

@ -15,55 +15,61 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\celt-0.7.1\libcelt\bands.c">
<ClCompile Include="..\..\celt-0.10.0\libcelt\bands.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\celt-0.7.1\libcelt\celt.c">
<ClCompile Include="..\..\celt-0.10.0\libcelt\celt.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\celt-0.7.1\libcelt\cwrs.c">
<ClCompile Include="..\..\celt-0.10.0\libcelt\cwrs.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\celt-0.7.1\libcelt\entcode.c">
<ClCompile Include="..\..\celt-0.10.0\libcelt\entcode.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\celt-0.7.1\libcelt\entdec.c">
<ClCompile Include="..\..\celt-0.10.0\libcelt\entdec.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\celt-0.7.1\libcelt\entenc.c">
<ClCompile Include="..\..\celt-0.10.0\libcelt\entenc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\celt-0.7.1\libcelt\header.c">
<ClCompile Include="..\..\celt-0.10.0\libcelt\header.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\celt-0.7.1\libcelt\kiss_fft.c">
<ClCompile Include="..\..\celt-0.10.0\libcelt\kiss_fft.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\celt-0.7.1\libcelt\laplace.c">
<ClCompile Include="..\..\celt-0.10.0\libcelt\laplace.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\celt-0.7.1\libcelt\mdct.c">
<ClCompile Include="..\..\celt-0.10.0\libcelt\mdct.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\celt-0.7.1\libcelt\modes.c">
<ClCompile Include="..\..\celt-0.10.0\libcelt\modes.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\celt-0.7.1\libcelt\pitch.c">
<ClCompile Include="..\..\celt-0.10.0\libcelt\pitch.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\celt-0.7.1\libcelt\quant_bands.c">
<ClCompile Include="..\..\celt-0.10.0\libcelt\quant_bands.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\celt-0.7.1\libcelt\rangedec.c">
<ClCompile Include="..\..\celt-0.10.0\libcelt\rangedec.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\celt-0.7.1\libcelt\rangeenc.c">
<ClCompile Include="..\..\celt-0.10.0\libcelt\rangeenc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\celt-0.7.1\libcelt\rate.c">
<ClCompile Include="..\..\celt-0.10.0\libcelt\rate.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\celt-0.7.1\libcelt\vq.c">
<ClCompile Include="..\..\celt-0.10.0\libcelt\vq.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\celt-0.10.0\libcelt\mathops.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\celt-0.10.0\libcelt\plc.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>

@ -9,8 +9,7 @@
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <winsock.h>
#include <errno.h>
#include <winsock2.h>
#include "xmlrpc_config.h"
#include "xmlrpc-c/util_int.h"
@ -249,6 +248,7 @@ struct socketWin {
SOCKET winsock;
bool userSuppliedWinsock;
/* 'socket' was supplied by the user; it belongs to him */
HANDLE interruptEvent;
};
static
@ -322,6 +322,8 @@ channelDestroy(TChannel * const channelP) {
if (!socketWinP->userSuppliedWinsock)
closesocket(socketWinP->winsock);
CloseHandle(socketWinP->interruptEvent);
free(socketWinP);
}
@ -430,9 +432,9 @@ channelWait(TChannel * const channelP,
timedOut = TRUE;
break;
case -1: /* socket error */
if (errno != EINTR)
if (WSAGetLastError() != WSAEINTR)
failed = TRUE;
break;
break;
default:
if (FD_ISSET(socketWinP->winsock, &rfds))
readRdy = TRUE;
@ -460,7 +462,9 @@ channelInterrupt(TChannel * const channelP) {
now or in the future.
Actually, this is just a no-op because we don't yet know how to
accomplish that.
accomplish that. (But we could probably do it the same way
chanSwitchInterrupt() works -- no one has needed it enough yet to do that
work).
-----------------------------------------------------------------------------*/
}
@ -484,7 +488,7 @@ ChannelWinGetPeerName(TChannel * const channelP,
if (rc != 0) {
int const lastError = WSAGetLastError();
xmlrpc_asprintf(errorP, "getpeername() failed. WSAERROR = %d (%s)",
xmlrpc_asprintf(errorP, "getpeername() failed. WSA error = %d (%s)",
lastError, getWSAError(lastError));
} else {
if (addrlen != sizeof(sockAddr))
@ -581,7 +585,8 @@ makeChannelFromWinsock(SOCKET const winsock,
socketWinP->winsock = winsock;
socketWinP->userSuppliedWinsock = TRUE;
socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
ChannelCreate(&channelVtbl, socketWinP, &channelP);
if (channelP == NULL)
@ -591,8 +596,10 @@ makeChannelFromWinsock(SOCKET const winsock,
*channelPP = channelP;
*errorP = NULL;
}
if (*errorP)
if (*errorP) {
CloseHandle(socketWinP->interruptEvent);
free(socketWinP);
}
}
}
@ -632,7 +639,7 @@ ChannelWinCreateWinsock(SOCKET const fd,
socklen_t peerAddrLen;
int rc;
peerAddrLen = sizeof(peerAddrLen);
peerAddrLen = sizeof(peerAddr);
rc = getpeername(fd, &peerAddr, &peerAddrLen);
@ -676,6 +683,8 @@ chanSwitchDestroy(TChanSwitch * const chanSwitchP) {
if (!socketWinP->userSuppliedWinsock)
closesocket(socketWinP->winsock);
CloseHandle(socketWinP->interruptEvent);
free(socketWinP);
}
@ -711,6 +720,49 @@ chanSwitchListen(TChanSwitch * const chanSwitchP,
static void
createChannelForAccept(int const acceptedWinsock,
struct sockaddr const peerAddr,
TChannel ** const channelPP,
void ** const channelInfoPP,
const char ** const errorP) {
struct abyss_win_chaninfo * channelInfoP;
makeChannelInfo(&channelInfoP, peerAddr, sizeof(peerAddr), errorP);
if (!*errorP) {
struct socketWin * acceptedSocketP;
MALLOCVAR(acceptedSocketP);
if (!acceptedSocketP)
xmlrpc_asprintf(errorP, "Unable to allocate memory");
else {
TChannel * channelP;
acceptedSocketP->winsock = acceptedWinsock;
acceptedSocketP->userSuppliedWinsock = FALSE;
acceptedSocketP->interruptEvent =
CreateEvent(NULL, FALSE, FALSE, NULL);
ChannelCreate(&channelVtbl, acceptedSocketP, &channelP);
if (!channelP)
xmlrpc_asprintf(errorP,
"Failed to create TChannel object.");
else {
*errorP = NULL;
*channelPP = channelP;
*channelInfoPP = channelInfoP;
}
if (*errorP) {
CloseHandle(acceptedSocketP->interruptEvent);
free(acceptedSocketP);
}
}
}
}
static SwitchAcceptImpl chanSwitchAccept;
static void
@ -728,7 +780,7 @@ chanSwitchAccept(TChanSwitch * const chanSwitchP,
*channelPP == NULL.
-----------------------------------------------------------------------------*/
struct socketWin * const listenSocketP = chanSwitchP->implP;
HANDLE acceptEvent = WSACreateEvent();
bool interrupted;
TChannel * channelP;
@ -736,46 +788,44 @@ chanSwitchAccept(TChanSwitch * const chanSwitchP,
channelP = NULL; /* No connection yet */
*errorP = NULL; /* No error yet */
WSAEventSelect(listenSocketP->winsock, acceptEvent,
FD_ACCEPT | FD_CLOSE | FD_READ);
while (!channelP && !*errorP && !interrupted) {
HANDLE interrupts[2] = {acceptEvent, listenSocketP->interruptEvent};
int rc;
struct sockaddr peerAddr;
socklen_t size = sizeof(peerAddr);
int rc;
rc = WaitForMultipleObjects(2, interrupts, FALSE, INFINITE);
if (WAIT_OBJECT_0 + 1 == rc) {
interrupted = TRUE;
continue;
};
rc = accept(listenSocketP->winsock, &peerAddr, &size);
if (rc >= 0) {
int const acceptedWinsock = rc;
struct socketWin * acceptedSocketP;
MALLOCVAR(acceptedSocketP);
createChannelForAccept(acceptedWinsock, peerAddr,
&channelP, channelInfoPP, errorP);
if (!acceptedSocketP)
xmlrpc_asprintf(errorP, "Unable to allocate memory");
else {
acceptedSocketP->winsock = acceptedWinsock;
acceptedSocketP->userSuppliedWinsock = FALSE;
*channelInfoPP = NULL;
ChannelCreate(&channelVtbl, acceptedSocketP, &channelP);
if (!channelP)
xmlrpc_asprintf(errorP,
"Failed to create TChannel object.");
else
*errorP = NULL;
if (*errorP)
free(acceptedSocketP);
}
if (*errorP)
closesocket(acceptedWinsock);
} else if (errno == EINTR)
interrupted = TRUE;
else
xmlrpc_asprintf(errorP, "accept() failed, errno = %d (%s)",
errno, strerror(errno));
} else {
int const lastError = WSAGetLastError();
if (lastError == WSAEINTR)
interrupted = TRUE;
else
xmlrpc_asprintf(errorP,
"accept() failed, WSA error = %d (%s)",
lastError, getWSAError(lastError));
}
}
*channelPP = channelP;
CloseHandle(acceptEvent);
}
@ -787,15 +837,10 @@ chanSwitchInterrupt(TChanSwitch * const chanSwitchP) {
/*----------------------------------------------------------------------------
Interrupt any waiting that a thread might be doing in chanSwitchAccept()
now or in the future.
Actually, this is just a no-op because we don't yet know how to
accomplish that.
-----------------------------------------------------------------------------*/
struct socketWin * const socketWinP = chanSwitchP->implP;
if (!socketWinP->userSuppliedWinsock)
closesocket(socketWinP->winsock);
struct socketWin * const listenSocketP = chanSwitchP->implP;
SetEvent(listenSocketP->interruptEvent);
}
@ -889,6 +934,7 @@ ChanSwitchWinCreate(uint16_t const portNumber,
} else {
socketWinP->winsock = winsock;
socketWinP->userSuppliedWinsock = FALSE;
socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
setSocketOptions(socketWinP->winsock, errorP);
if (!*errorP) {
@ -899,8 +945,10 @@ ChanSwitchWinCreate(uint16_t const portNumber,
chanSwitchPP);
}
if (*errorP)
if (*errorP) {
CloseHandle(socketWinP->interruptEvent);
closesocket(winsock);
}
}
if (*errorP)
free(socketWinP);
@ -929,7 +977,8 @@ ChanSwitchWinCreateWinsock(SOCKET const winsock,
socketWinP->winsock = winsock;
socketWinP->userSuppliedWinsock = TRUE;
socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
ChanSwitchCreate(&chanSwitchVtbl, socketWinP, &chanSwitchP);
if (chanSwitchP == NULL)
@ -939,8 +988,10 @@ ChanSwitchWinCreateWinsock(SOCKET const winsock,
*chanSwitchPP = chanSwitchP;
*errorP = NULL;
}
if (*errorP)
if (*errorP) {
CloseHandle(socketWinP->interruptEvent);
free(socketWinP);
}
}
}
}

@ -29,7 +29,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* Copyright (C) 2007, Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2007, Anthony Minessale II <anthm@freeswitch.org>
*/
#include <stdio.h>

@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@ -17,13 +17,13 @@
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
*
*
* api.js Demo javascript FSAPI Interface

@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2005/2006, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@ -17,13 +17,13 @@
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
*
*
* SpeechTools.jm Speech Detection Interface

@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@ -17,13 +17,13 @@
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
*
*
* pizza.js ASR Demonstration Application

@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@ -17,13 +17,13 @@
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthmct@yahoo.com>
* Anthony Minessale II <anthm@freeswitch.org>
*
*
* pizza.js ASR Demonstration Application

@ -5,7 +5,7 @@
# voicemail gateway with no mail server>
#
# (c) 2005 Anthony Minessale II
# Anthony Minessale <anthmct@yahoo.com>
# Anthony Minessale <anthm@freeswitch.org>
#
################################################################################
use Net::SMTP;

@ -1,6 +1,6 @@
"""
FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
Version: MPL 1.1
@ -17,7 +17,7 @@ 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 <anthmct@yahoo.com>
Anthony Minessale II <anthm@freeswitch.org>
Portions created by the Initial Developer are Copyright (C)
the Initial Developer. All Rights Reserved.

@ -1,6 +1,6 @@
"""
FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
Version: MPL 1.1
@ -17,7 +17,7 @@ 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 <anthmct@yahoo.com>
Anthony Minessale II <anthm@freeswitch.org>
Portions created by the Initial Developer are Copyright (C)
the Initial Developer. All Rights Reserved.

@ -2,7 +2,7 @@
"""
FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
Version: MPL 1.1
@ -19,7 +19,7 @@ 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 <anthmct@yahoo.com>
Anthony Minessale II <anthm@freeswitch.org>
Portions created by the Initial Developer are Copyright (C)
the Initial Developer. All Rights Reserved.

@ -1,6 +1,6 @@
"""
FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
Version: MPL 1.1
@ -17,7 +17,7 @@ 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 <anthmct@yahoo.com>
Anthony Minessale II <anthm@freeswitch.org>
Portions created by the Initial Developer are Copyright (C)
the Initial Developer. All Rights Reserved.

@ -1,6 +1,6 @@
"""
FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
Version: MPL 1.1
@ -17,7 +17,7 @@ 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 <anthmct@yahoo.com>
Anthony Minessale II <anthm@freeswitch.org>
Portions created by the Initial Developer are Copyright (C)
the Initial Developer. All Rights Reserved.

@ -4,7 +4,7 @@
#
# Copyright (C) 2006, Anthony Minessale
#
# Anthony Minessale <anthmct@yahoo.com>
# Anthony Minessale <anthm@freeswitch.org>
#
# This program is free software, distributed under the terms of
# Perl itself

@ -1,6 +1,6 @@
#!/usr/bin/perl
# sipgrep version 0.2. Skin for ngrep. (C) 2005-2006 Alexandr Dubovikov <shurik@start4.info>
# Modified 2007 Anthony Minessale <anthmct@yahoo.com>
# Modified 2007 Anthony Minessale <anthm@freeswitch.org>
use Term::ANSIColor;
use Getopt::Std;

@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*

@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*

@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*

@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*

@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*

@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*

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