Merge branch 'master' of git://git.freeswitch.org/freeswitch

This commit is contained in:
Michael S Collins 2011-01-24 12:07:00 -08:00
commit d6cfc2f1e9
49 changed files with 1483 additions and 370 deletions

View File

@ -349,7 +349,7 @@ scripts/fsxs: scripts/fsxs.in
-e "s|@INCLUDES\@|-I$(prefix)/include|" \
-e "s|@SOLINK\@|$(SOLINK)|" \
-e "s|@LDFLAGS\@|-L$(prefix)/lib|" \
-e "s|@LIBS\@|`./libs/apr/apr-1-config --libs` `./libs/apr-util/apu-1-config --libs`|" \
-e "s|@LIBS\@||" \
$(top_srcdir)/scripts/fsxs.in > scripts/fsxs
##

View File

@ -78,6 +78,7 @@ event_handlers/mod_cdr_sqlite
#event_handlers/mod_cdr_pg_csv
#event_handlers/mod_radius_cdr
#event_handlers/mod_erlang_event
#event_handlers/mod_snmp
formats/mod_native_file
formats/mod_sndfile
#formats/mod_shout

View File

@ -11,6 +11,9 @@
<!-- IP or Hostname of Default Route -->
<param name="default-gateway" value="192.168.66.6"/>
<!-- Number of times to retry ODBC connection on connection problems, default is 120 -->
<param name="odbc-retries" value="120"/>
<!-- Customer Query. Use this with Care!!! We are not responsible if you mess
This up!!! Query *MUST* return columns in the following order!
gateway varchar(128) - contains destination gateway host:port pair (ex: 192.168.1.1:5060 )

View File

@ -24,6 +24,7 @@
<load module="mod_event_socket"/>
<!-- <load module="mod_zeroconf"/> -->
<!-- <load module="mod_erlang_event"/> -->
<!-- <load module="mod_snmp"/> -->
<!-- Directory Interfaces -->
<!-- <load module="mod_ldap"/> -->

View File

@ -16,7 +16,7 @@
<match>
<action function="play-file" data="directory/dir-to_search_by.wav"/>
<action function="play-file" data="directory/dir-first_name.wav"/>
<action function="play-file" data="directory/dir-press.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$2" method="pronounced" type="name_spelled"/>
</match>
</input>
@ -24,7 +24,7 @@
<match>
<action function="play-file" data="directory/dir-to_search_by.wav"/>
<action function="play-file" data="directory/dir-last_name.wav"/>
<action function="play-file" data="directory/dir-press.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$2" method="pronounced" type="name_spelled"/>
</match>
</input>

View File

@ -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

View File

@ -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
@ -893,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
@ -951,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

View File

@ -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

View File

@ -11,3 +11,12 @@
cannot be shown to end users, we already provide extensive logging for problem
troubleshooting.
- Implement threaded IO.
Currently IO modules only work on-demand, where the user (ie, FreeSWITCH) drives the read/write
of media. If the user stops reading, some functions are not possible
(DTMF detection or Hangup tone detection). It would be useful to implement a FreeTDM mode
where the media is driven by a group of threads that are always reading (and possibly writing)
then when the user does ftdm_channel_read(), the media would be read from the buffers filled
by the media thread and not from the underlying IO device, this gives a chance to FreeTDM to
still perform hangup detection or other media services even if the application is not reading.

View File

@ -0,0 +1,13 @@
Last Updated: Jan 19, 2011
== BACKGROUND ==
The IO module provides an abstracted IO interface to FreeTDM.
== SHUTDOWN ==
Upon global shutdown, for each channel FIO_CLOSE_FUNCTION will be called.
When FIO_CLOSE_FUNCTION is called, all waiters on this channel shall be signalled.
If FIO_WAIT_FUNCTION is called on a function that has already been closed, this function shall return FTDM_TIMEOUT without blocking.
FIO_CHANNEL_DESTROY will eventually be called, and IO module is responsible for clearing all internal states and free allocated memory upon channel destroy.

View File

@ -404,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,
@ -2417,8 +2417,6 @@ static ftdm_status_t _ftdm_channel_call_place_nl(const char *file, const char *f
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);
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;
@ -5548,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;

View File

@ -70,13 +70,13 @@ 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));

View File

@ -295,7 +295,7 @@ static ftdm_call_cause_t ftdm_r2_cause_to_ftdm_cause(ftdm_channel_t *fchan, open
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;
}
@ -647,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));

View File

@ -394,8 +394,7 @@ static void *ftdm_sangoma_isdn_dchan_run(ftdm_thread_t *me, void *obj)
default:
ftdm_log_chan_msg(dchan, FTDM_LOG_CRIT, "Unhandled IO event\n");
}
}
ftdm_channel_close(&dchan);
}
return NULL;
}
@ -677,6 +676,9 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm
/*OUTBOUND...so we were told by the line of this so noifiy the user*/
sigev.event_id = FTDM_SIGEVENT_PROCEED;
ftdm_span_send_signal(ftdmchan->span, &sigev);
if (sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY)) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
}
} else {
if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
/* By default, we do not send a progress indicator in the proceed */

View File

@ -112,6 +112,11 @@ typedef enum {
SNGISDN_OPT_FALSE = 2,
} sngisdn_opt_t;
typedef enum {
SNGISDN_EARLY_MEDIA_ON_PROCEED = (1 << 0),
SNGISDN_EARLY_MEDIA_ON_PROGRESS = (1 << 1),
SNGISDN_EARLY_MEDIA_ON_ALERT= (1 << 2),
} sngisdn_early_media_opt_t;
typedef enum {
SNGISDN_AVAIL_DOWN = 1,
@ -188,7 +193,8 @@ typedef struct sngisdn_span_data {
uint8_t span_id;
uint8_t tei;
uint8_t min_digits;
uint8_t trace_flags; /* TODO: change to flags, so we can use ftdm_test_flag etc.. */
uint8_t trace_flags; /* TODO change to bit map of sngisdn_tracetype_t */
uint8_t early_media_flags; /* bit map of ftdm_sngisdn_early_media_opt_t */
uint8_t overlap_dial;
uint8_t setup_arb;
uint8_t facility_ie_decode;
@ -196,10 +202,10 @@ typedef struct sngisdn_span_data {
int8_t facility_timeout;
uint8_t num_local_numbers;
uint8_t ignore_cause_value;
uint8_t raw_trace_q931;
uint8_t raw_trace_q921;
uint8_t raw_trace_q931; /* TODO: combine with trace_flags */
uint8_t raw_trace_q921; /* TODO: combine with trace_flags */
uint8_t timer_t3;
uint8_t restart_opt;
uint8_t restart_opt;
char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS];
ftdm_sched_t *sched;
ftdm_queue_t *event_queue;

View File

@ -192,6 +192,24 @@ static ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span)
return FTDM_SUCCESS;
}
static ftdm_status_t parse_early_media(const char* opt, ftdm_span_t *span)
{
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
if (!strcasecmp(opt, "on-proceed")) {
signal_data->early_media_flags |= SNGISDN_EARLY_MEDIA_ON_PROCEED;
} else if (!strcasecmp(opt, "on-progress")) {
signal_data->early_media_flags |= SNGISDN_EARLY_MEDIA_ON_PROGRESS;
} else if (!strcasecmp(opt, "on-alert")) {
signal_data->early_media_flags |= SNGISDN_EARLY_MEDIA_ON_ALERT;
} else {
ftdm_log(FTDM_LOG_ERROR, "Unsupported early-media option %s\n", opt);
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_DEBUG, "Early media opt:0x%x\n", signal_data->early_media_flags);
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;
@ -249,6 +267,7 @@ static ftdm_status_t set_switchtype_defaults(ftdm_span_t *span)
return FTDM_SUCCESS;
}
ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *span)
{
unsigned paramindex;
@ -351,10 +370,14 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
parse_yesno(var, val, &signal_data->raw_trace_q931);
} else if (!strcasecmp(var, "q921-raw-trace")) {
parse_yesno(var, val, &signal_data->raw_trace_q921);
} else if (!strcasecmp(var, "early-media-override")) {
if (parse_early_media(val, span) != FTDM_SUCCESS) {
return FTDM_FAIL;
}
} else {
ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var);
}
}
} /* for (paramindex = 0; ftdm_parameters[paramindex].var; paramindex++) */
if (signal_data->switchtype == SNGISDN_SWITCH_INVALID) {
ftdm_log(FTDM_LOG_ERROR, "%s: switchtype not specified", span->name);
@ -366,10 +389,11 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
}
if (span->default_caller_data.bearer_layer1 == FTDM_INVALID_INT_PARM) {
if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) {
span->default_caller_data.bearer_layer1 = IN_UIL1_G711ULAW;
} else {
if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN ||
signal_data->switchtype == SNGISDN_SWITCH_QSIG) {
span->default_caller_data.bearer_layer1 = IN_UIL1_G711ALAW;
} else {
span->default_caller_data.bearer_layer1 = IN_UIL1_G711ULAW;
}
}
return FTDM_SUCCESS;

View File

@ -167,12 +167,12 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
char retrieved_str[255];
ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str);
/*
return values for "sng_isdn_retrieve_facility_information_following":
If there will be no information following, or fails to decode IE, returns -1
If there will be no information following, but current FACILITY IE contains a caller name, returns 0
If there will be information following, returns 1
*/
/*
return values for "sng_isdn_retrieve_facility_information_following":
If there will be no information following, or fails to decode IE, returns -1
If there will be no information following, but current FACILITY IE contains a caller name, returns 0
If there will be information following, returns 1
*/
if (ret_val == 1) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n");
@ -346,6 +346,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt;
@ -384,7 +385,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
case FTDM_CHANNEL_STATE_DIALING:
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_RINGING:
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);
@ -393,16 +394,34 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
}
switch (evntType) {
case MI_CALLPROC:
if (!sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY) &&
(signal_data->early_media_flags & SNGISDN_EARLY_MEDIA_ON_PROCEED)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Early media override on proceed\n");
sngisdn_set_flag(sngisdn_info, FLAG_MEDIA_READY);
}
if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROCEED);
}
break;
case MI_ALERTING:
if (!sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY) &&
(signal_data->early_media_flags & SNGISDN_EARLY_MEDIA_ON_ALERT)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Early media override on alert\n");
sngisdn_set_flag(sngisdn_info, FLAG_MEDIA_READY);
}
if (ftdmchan->state == FTDM_CHANNEL_STATE_PROCEED) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RINGING);
}
break;
case MI_PROGRESS:
if (!sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY) &&
(signal_data->early_media_flags & SNGISDN_EARLY_MEDIA_ON_PROGRESS)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Early media override on progress\n");
sngisdn_set_flag(sngisdn_info, FLAG_MEDIA_READY);
}
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) {

View File

@ -881,18 +881,27 @@ ftdm_status_t set_bear_cap_ie(ftdm_channel_t *ftdmchan, BearCap *bearCap)
bearCap->usrInfoLyr1Prot.pres = PRSNT_NODEF;
bearCap->usrInfoLyr1Prot.val = sngisdn_get_usrInfoLyr1Prot_from_user(ftdmchan->caller_data.bearer_layer1);
if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN &&
bearCap->usrInfoLyr1Prot.val == IN_UIL1_G711ULAW) {
/* We are bridging a call from T1 */
bearCap->usrInfoLyr1Prot.val = IN_UIL1_G711ALAW;
} else if (bearCap->usrInfoLyr1Prot.val == IN_UIL1_G711ALAW) {
/* We are bridging a call from E1 */
bearCap->usrInfoLyr1Prot.val = IN_UIL1_G711ULAW;
switch (signal_data->switchtype) {
case SNGISDN_SWITCH_NI2:
case SNGISDN_SWITCH_4ESS:
case SNGISDN_SWITCH_5ESS:
case SNGISDN_SWITCH_DMS100:
case SNGISDN_SWITCH_INSNET:
if (bearCap->usrInfoLyr1Prot.val == IN_UIL1_G711ALAW) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Overriding bearer cap to u-law\n");
bearCap->usrInfoLyr1Prot.val = IN_UIL1_G711ULAW;
}
break;
case SNGISDN_SWITCH_EUROISDN:
case SNGISDN_SWITCH_QSIG:
if (bearCap->usrInfoLyr1Prot.val == IN_UIL1_G711ULAW) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Overriding bearer cap to a-law\n");
bearCap->usrInfoLyr1Prot.val = IN_UIL1_G711ALAW;
}
break;
}
bearCap->lyr1Ident.pres = PRSNT_NODEF;
bearCap->lyr1Ident.val = IN_L1_IDENT;
}

View File

@ -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);
@ -237,7 +239,11 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
ftdm_log(FTDM_LOG_ERROR, "span %d channel %d cannot be configured as smg_prid_nfas, you need to compile freetdm with newer libsangoma\n", spanno, x);
#endif
} else {
#ifdef LIBSANGOMA_VERSION
sockfd = __tdmv_api_open_span_chan(spanno, x);
#else
sockfd = tdmv_api_open_span_chan(spanno, x);
#endif
}
if (sockfd == FTDM_INVALID_SOCKET) {
@ -271,6 +277,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 +297,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 +305,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,7 +375,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 fd:%d DTMF: %s\n", 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);
@ -653,6 +664,8 @@ static FIO_COMMAND_FUNCTION(wanpipe_command)
}
}
break;
case FTDM_COMMAND_DISABLE_ECHOTRAIN: { err = 0; }
break;
case FTDM_COMMAND_ENABLE_DTMF_DETECT:
{
#ifdef WP_API_FEATURE_DTMF_EVENTS
@ -1257,20 +1270,18 @@ static __inline__ ftdm_status_t wanpipe_channel_process_event(ftdm_channel_t *fc
switch(tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_type) {
case WP_API_EVENT_LINK_STATUS:
{
#if 0
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;
};
#else
/* The WP_API_EVENT_ALARM event should be used to clear alarms */
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Ignoring wanpipe link status event\n", ftdm_oob_event2str(*event_id));
*event_id = FTDM_OOB_NOOP;
#endif
}
break;

View File

@ -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,
@ -171,7 +191,7 @@ FTDM_STR2ENUM_P(ftdm_str2ftdm_chan_type, ftdm_chan_type2str, ftdm_chan_type_t)
#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) ((fchan)->type == FTDM_CHAN_TYPE_DQ921 || (fchan)->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 || \
@ -410,7 +430,7 @@ typedef enum {
} 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", \
"COLLECTED_DIGIT", "ADD_CALL", "RESTART", "SIGSTATUS_CHANGED", "FACILITY", \
"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)
@ -574,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;

View File

@ -132,8 +132,8 @@ extern "C" {
#define ftdm_channel_test_feature(obj, flag) ((obj)->features & flag)
#define ftdm_channel_set_feature(obj, flag) (obj)->features |= (flag)
#define ftdm_channel_clear_feature(obj, flag) (obj)->features &= ~(flag)
#define ftdm_channel_set_feature(obj, flag) (obj)->features = (ftdm_channel_feature_t)((obj)->features | flag)
#define ftdm_channel_clear_feature(obj, flag) (obj)->features = (ftdm_channel_feature_t)((obj)->features & ( ~(flag) ))
#define ftdm_channel_set_member_locked(obj, _m, _v) ftdm_mutex_lock(obj->mutex); obj->_m = _v; ftdm_mutex_unlock(obj->mutex)
/*!
@ -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
@ -677,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)

View File

@ -227,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)

View File

@ -1,5 +1,5 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
exec_prefix=@prefix@
libdir=@libdir@
includedir=@includedir@

View File

@ -192,7 +192,7 @@ static inline char switch_itodtmf(char i)
r = i + 55;
}
return r;
return r + 48;
}
static inline int switch_dtmftoi(char *s)

View File

@ -477,6 +477,7 @@ static switch_status_t conference_add_event_member_data(conference_member_t *mem
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Mute-Detect", "%s", switch_test_flag(member, MFLAG_MUTE_DETECT) ? "true" : "false" );
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-ID", "%u", member->id);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-Type", "%s", switch_test_flag(member, MFLAG_MOD) ? "moderator" : "member");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Energy-Level", "%d", member->energy_level);
return status;
}
@ -5596,6 +5597,7 @@ SWITCH_STANDARD_APP(conference_function)
char pin_buf[80] = "";
int pin_retries = 3; /* XXX - this should be configurable - i'm too lazy to do it right now... */
int pin_valid = 0;
int be_friendly = 0;
switch_status_t status = SWITCH_STATUS_SUCCESS;
char *supplied_pin_value;
@ -5630,19 +5632,23 @@ SWITCH_STANDARD_APP(conference_function)
switch_status_t pstatus = SWITCH_STATUS_FALSE;
/* be friendly */
if (conference->pin_sound) {
pstatus = conference_local_play_file(conference, session, conference->pin_sound, 20, pin_buf, sizeof(pin_buf));
} else if (conference->tts_engine && conference->tts_voice) {
pstatus =
switch_ivr_speak_text(session, conference->tts_engine, conference->tts_voice, "please enter the conference pin number", NULL);
} else {
pstatus = switch_ivr_speak_text(session, "flite", "slt", "please enter the conference pin number", NULL);
if (!be_friendly) {
if (conference->pin_sound) {
pstatus = conference_local_play_file(conference, session, conference->pin_sound, 20, pin_buf, sizeof(pin_buf));
} else if (conference->tts_engine && conference->tts_voice) {
pstatus =
switch_ivr_speak_text(session, conference->tts_engine, conference->tts_voice, "please enter the conference pin number", NULL);
} else {
pstatus = switch_ivr_speak_text(session, "flite", "slt", "please enter the conference pin number", NULL);
}
if (pstatus != SWITCH_STATUS_SUCCESS && pstatus != SWITCH_STATUS_BREAK) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Cannot ask the user for a pin, ending call");
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
}
}
if (pstatus != SWITCH_STATUS_SUCCESS && pstatus != SWITCH_STATUS_BREAK) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Cannot ask the user for a pin, ending call");
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
}
be_friendly = 1;
/* wait for them if neccessary */
if (strlen(pin_buf) < strlen(dpin)) {
@ -5659,13 +5665,12 @@ SWITCH_STANDARD_APP(conference_function)
pin_valid = (status == SWITCH_STATUS_SUCCESS && strcmp(pin_buf, dpin) == 0);
if (!pin_valid) {
/* zero the collected pin */
memset(pin_buf, 0, sizeof(pin_buf));
/* more friendliness */
if (conference->bad_pin_sound) {
conference_local_play_file(conference, session, conference->bad_pin_sound, 20, pin_buf, sizeof(pin_buf));
}
/* zero the collected pin */
memset(pin_buf, 0, sizeof(pin_buf));
}
pin_retries--;
}

View File

@ -2982,6 +2982,8 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
}
}
}
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_user", user);
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_domain", domain);
if (!dest) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No dial-string available, please check your user directory.\n");

View File

@ -65,6 +65,7 @@ static struct {
switch_mutex_t *mutex;
char *custom_query;
switch_odbc_handle_t *master_odbc;
int odbc_num_retries;
} globals;
SWITCH_MODULE_LOAD_FUNCTION(mod_easyroute_load);
@ -120,6 +121,8 @@ static switch_status_t load_config(void)
set_global_default_gateway(val);
} else if (!strcasecmp(var, "custom-query")) {
set_global_custom_query(val);
} else if (!strcasecmp(var, "odbc-retries")) {
globals.odbc_num_retries = atoi(val);
}
}
}
@ -143,6 +146,9 @@ static switch_status_t load_config(void)
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opened ODBC Database!\n");
}
if (globals.odbc_num_retries) {
switch_odbc_set_num_retries(globals.master_odbc, globals.odbc_num_retries);
}
if (switch_odbc_handle_connect(globals.master_odbc) != SWITCH_ODBC_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open ODBC Database!\n");
status = SWITCH_STATUS_FALSE;
@ -205,7 +211,7 @@ static switch_status_t route_lookup(char *dn, easyroute_results_t *results, int
switch_mutex_lock(globals.mutex);
}
/* Do the Query */
if (switch_odbc_handle_callback_exec(globals.master_odbc, sql, route_callback, &pdata, NULL) == SWITCH_ODBC_SUCCESS) {
if (globals.master_odbc && switch_odbc_handle_callback_exec(globals.master_odbc, sql, route_callback, &pdata, NULL) == SWITCH_ODBC_SUCCESS) {
char tmp_profile[129];
char tmp_gateway[129];
@ -418,7 +424,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_easyroute_load)
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_easyroute_shutdown)
{
switch_odbc_handle_disconnect(globals.master_odbc);
if (globals.master_odbc) {
switch_odbc_handle_disconnect(globals.master_odbc);
switch_odbc_handle_destroy(&globals.master_odbc);
}
switch_safe_free(globals.db_username);
switch_safe_free(globals.db_password);
switch_safe_free(globals.db_dsn);

View File

@ -311,6 +311,7 @@ static void destroy_profile(const char *profile_name, switch_bool_t block)
/* Static buffer, 2 bytes */
static switch_xml_config_string_options_t config_dtmf = { NULL, 2, "[0-9#\\*]" };
static switch_xml_config_string_options_t config_dtmf_optional = { NULL, 2, "[0-9#\\*]?" };
static switch_xml_config_string_options_t config_login_keys = { NULL, 16, "[0-9#\\*]*" };
static switch_xml_config_string_options_t config_file_ext = { NULL, 10, NULL };
static switch_xml_config_int_options_t config_int_0_10000 = { SWITCH_TRUE, 0, SWITCH_TRUE, 10000 };
@ -520,8 +521,8 @@ vm_profile_t *profile_set_config(vm_profile_t *profile)
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "urgent-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE,
&profile->urgent_key, "*", &config_dtmf, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "operator-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE,
&profile->operator_key, "", &config_dtmf, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "vmain-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, &profile->vmain_key, "", &config_dtmf, NULL, NULL);
&profile->operator_key, "", &config_dtmf_optional, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "vmain-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, &profile->vmain_key, "", &config_dtmf_optional, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "vmain-extension", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE,
&profile->vmain_ext, "", &profile->config_str_pool, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "forward-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE,

View File

@ -53,8 +53,8 @@ static switch_status_t switch_celt_init(switch_codec_t *codec, switch_codec_flag
return SWITCH_STATUS_FALSE;
}
context->mode_object = celt_mode_create(codec->implementation->actual_samples_per_second, codec->implementation->samples_per_packet, NULL);
context->frame_size = codec->implementation->samples_per_packet;
context->mode_object = celt_mode_create(codec->implementation->actual_samples_per_second, context->frame_size, NULL);
context->bytes_per_packet = (codec->implementation->bits_per_second * context->frame_size / codec->implementation->actual_samples_per_second + 4) / 8;
/*
@ -106,15 +106,22 @@ static switch_status_t switch_celt_encode(switch_codec_t *codec,
unsigned int *flag)
{
struct celt_context *context = codec->private_info;
int bytes = 0;
if (!context) {
return SWITCH_STATUS_FALSE;
}
*encoded_data_len = (uint32_t) celt_encode(context->encoder_object, (void *) decoded_data, codec->implementation->samples_per_packet,
(unsigned char *) encoded_data, context->bytes_per_packet);
bytes = (uint32_t) celt_encode(context->encoder_object, (void *) decoded_data, codec->implementation->samples_per_packet,
(unsigned char *) encoded_data, context->bytes_per_packet);
return SWITCH_STATUS_SUCCESS;
if (bytes > 0) {
*encoded_data_len = (uint32_t) bytes;
return SWITCH_STATUS_SUCCESS;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Encoder Error!\n");
return SWITCH_STATUS_GENERR;
}
static switch_status_t switch_celt_decode(switch_codec_t *codec,
@ -152,23 +159,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_celt_load)
SWITCH_ADD_CODEC(codec_interface, "CELT ultra-low delay");
switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
114, /* the IANA code number */
"CELT", /* the IANA code name */
NULL, /* default fmtp to send (can be overridden by the init function) */
32000, /* samples transferred per second */
32000, /* actual samples transferred per second */
32000, /* bits transferred per second */
10000, /* number of microseconds per frame */
320, /* number of samples per frame */
640, /* number of bytes per frame decompressed */
0, /* number of bytes per frame compressed */
1, /* number of channels represented */
1, /* number of frames per network packet */
switch_celt_init, /* function to initialize a codec handle using this implementation */
switch_celt_encode, /* function to encode raw data into encoded data */
switch_celt_decode, /* function to decode encoded data into raw data */
switch_celt_destroy); /* deinitalize a codec handle using this implementation */
ms_per_frame = 2000;
samples_per_frame = 96;
bytes_per_frame = 192;

View File

@ -630,6 +630,11 @@ static void actual_sofia_presence_event_handler(switch_event_t *event)
char *probe_user = NULL, *probe_euser, *probe_host, *p;
struct dialog_helper dh = { { 0 } };
if (strcasecmp(proto, SOFIA_CHAT_PROTO) != 0) {
goto done;
}
if (!to || !(probe_user = strdup(to))) {
goto done;
}
@ -2405,6 +2410,20 @@ void sofia_presence_handle_sip_i_subscribe(int status,
switch_event_fire(&sevent);
}
} else if (to_user && (strcasecmp(proto, SOFIA_CHAT_PROTO) != 0)) {
if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto", proto);
switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "long", profile->name);
switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host);
switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "to", "%s%s%s@%s", proto, "+", to_user, to_host);
switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto-specific-event-name", event);
switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str);
switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "event_type", "presence");
switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str);
switch_event_fire(&sevent);
}
} else {
if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO);

View File

@ -1139,7 +1139,13 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_url_encode(my_contact_str, path_encoded + 20, path_encoded_len - 20);
reg_desc = "Registered(AUTO-NAT-2.0)";
exptime = 30;
switch_snprintf(contact_str + strlen(contact_str), sizeof(contact_str) - strlen(contact_str), "%s", path_encoded);
/* place fs_path (the encoded path) inside the <...> of the contact string, if possible */
if (contact_str[strlen(contact_str) - 1] == '>') {
switch_snprintf(contact_str + strlen(contact_str) - 1, sizeof(contact_str) - strlen(contact_str) + 1, "%s>", path_encoded);
} else {
switch_snprintf(contact_str + strlen(contact_str), sizeof(contact_str) - strlen(contact_str), "%s", path_encoded);
}
free(path_encoded);
} else {
if (*received_data && sofia_test_pflag(profile, PFLAG_RECIEVED_IN_NAT_REG_CONTACT)) {

View File

@ -111,6 +111,7 @@ void ei_encode_switch_event_headers(ei_x_buff * ebuf, switch_event_t *event)
for (hp = event->headers; hp; hp = hp->next) {
ei_x_encode_tuple_header(ebuf, 2);
_ei_x_encode_string(ebuf, hp->name);
switch_url_decode(hp->value);
_ei_x_encode_string(ebuf, hp->value);
}

View File

@ -778,7 +778,7 @@ static switch_status_t handle_msg_bind(listener_t *listener, erlang_msg * msg, e
binding->process.pid = msg->from;
binding->listener = listener;
switch_thread_rwlock_wrlock(globals.listener_rwlock);
switch_thread_rwlock_wrlock(globals.bindings_rwlock);
for (ptr = bindings.head; ptr && ptr->next; ptr = ptr->next);
@ -789,7 +789,7 @@ static switch_status_t handle_msg_bind(listener_t *listener, erlang_msg * msg, e
}
switch_xml_set_binding_sections(bindings.search_binding, switch_xml_get_binding_sections(bindings.search_binding) | section);
switch_thread_rwlock_unlock(globals.listener_rwlock);
switch_thread_rwlock_unlock(globals.bindings_rwlock);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "sections %d\n", switch_xml_get_binding_sections(bindings.search_binding));

View File

@ -90,7 +90,7 @@ static void remove_binding(listener_t *listener, erlang_pid * pid)
{
struct erlang_binding *ptr, *lst = NULL;
switch_thread_rwlock_wrlock(globals.listener_rwlock);
switch_thread_rwlock_wrlock(globals.bindings_rwlock);
switch_xml_set_binding_sections(bindings.search_binding, SWITCH_XML_SECTION_MAX);
@ -100,7 +100,7 @@ static void remove_binding(listener_t *listener, erlang_pid * pid)
if (ptr->next) {
bindings.head = ptr->next;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removed all (only?) listeners\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removed all (only?) binding\n");
bindings.head = NULL;
break;
}
@ -111,13 +111,13 @@ static void remove_binding(listener_t *listener, erlang_pid * pid)
lst->next = NULL;
}
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removed listener\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removed binding\n");
} else {
switch_xml_set_binding_sections(bindings.search_binding, switch_xml_get_binding_sections(bindings.search_binding) | ptr->section);
}
}
switch_thread_rwlock_unlock(globals.listener_rwlock);
switch_thread_rwlock_unlock(globals.bindings_rwlock);
}
@ -381,6 +381,8 @@ static switch_xml_t erlang_fetch(const char *sectionstr, const char *tag_name, c
section = switch_xml_parse_section_string((char *) sectionstr);
switch_thread_rwlock_rdlock(globals.bindings_rwlock);
for (ptr = bindings.head; ptr; ptr = ptr->next) {
if (ptr->section != section)
continue;
@ -417,6 +419,8 @@ static switch_xml_t erlang_fetch(const char *sectionstr, const char *tag_name, c
switch_mutex_unlock(ptr->listener->sock_mutex);
}
switch_thread_rwlock_unlock(globals.bindings_rwlock);
ei_x_free(&buf);
if (!p) {
@ -532,6 +536,7 @@ static switch_status_t notify_new_session(listener_t *listener, session_elem_t *
session_element->uuid_str);
}
switch_event_destroy(&call_event);
ei_x_free(&lbuf);
return SWITCH_STATUS_SUCCESS;
}
@ -1637,6 +1642,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_erlang_event_load)
memset(&prefs, 0, sizeof(prefs));
switch_thread_rwlock_create(&globals.listener_rwlock, pool);
switch_thread_rwlock_create(&globals.bindings_rwlock, pool);
switch_mutex_init(&globals.fetch_reply_mutex, SWITCH_MUTEX_DEFAULT, pool);
switch_mutex_init(&globals.listener_count_mutex, SWITCH_MUTEX_UNNESTED, pool);
switch_core_hash_init(&globals.fetch_reply_hash, pool);

View File

@ -161,6 +161,7 @@ struct api_command_struct {
struct globals_struct {
switch_thread_rwlock_t *listener_rwlock;
switch_thread_rwlock_t *bindings_rwlock;
switch_event_node_t *node;
switch_mutex_t *ref_mutex;
switch_mutex_t *fetch_reply_mutex;

View File

@ -0,0 +1,110 @@
FREESWITCH-MIB DEFINITIONS ::= BEGIN
IMPORTS
OBJECT-TYPE, MODULE-IDENTITY,
Integer32, Gauge32, Counter32, Counter64, TimeTicks,
enterprises,
FROM SNMPv2-SMI
DisplayString
FROM SNMPv2-TC
;
freeswitch MODULE-IDENTITY
LAST-UPDATED "201101170000Z"
ORGANIZATION "www.freeswitch.org"
CONTACT-INFO
"Primary contact: Anthony Minessale II
Email: anthm@freeswitch.org"
DESCRIPTION
"This file defines the private FreeSWITCH SNMP MIB extensions."
REVISION "201101170000Z"
DESCRIPTION
"First draft by daniel.swarbrick@seventhsignal.de"
::= { enterprises 27880 }
core OBJECT IDENTIFIER ::= { freeswitch 1 }
mod-sofia OBJECT IDENTIFIER ::= { freeswitch 1001 }
mod-skinny OBJECT IDENTIFIER ::= { freeswitch 1002 }
identity OBJECT IDENTIFIER ::= { core 1 }
versionString OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"FreeSWITCH version as a string"
::= { identity 1 }
uuid OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"FreeSWITCH core UUID"
::= { identity 2 }
systemStats OBJECT IDENTIFIER ::= { core 2 }
uptime OBJECT-TYPE
SYNTAX TimeTicks
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"FreeSWITCH process uptime in hundredths of seconds"
::= { systemStats 1 }
sessionsSinceStartup OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of sessions since FreeSWITCH process was started"
::= { systemStats 2 }
currentSessions OBJECT-TYPE
SYNTAX Gauge32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Currently active sessions"
::= { systemStats 3 }
maxSessions OBJECT-TYPE
SYNTAX Gauge32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Maximum permissible active sessions"
::= { systemStats 4 }
currentCalls OBJECT-TYPE
SYNTAX Gauge32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Currently active calls"
::= { systemStats 5 }
sessionsPerSecond OBJECT-TYPE
SYNTAX Gauge32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Current sessions per second"
::= { systemStats 6 }
maxSessionsPerSecond OBJECT-TYPE
SYNTAX Gauge32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Maximum permissible sessions per second"
::= { systemStats 7 }
END

View File

@ -0,0 +1,7 @@
include ../../../../build/modmake.rules
LOCAL_CFLAGS=-I `net-snmp-config --cflags`
LOCAL_LDFLAGS=`net-snmp-config --agent-libs`
LOCAL_OBJS=subagent.o
local_depend: $(LOCAL_OBJS)

View File

@ -0,0 +1,138 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Swarbrick <daniel.swarbrick@seventhsignal.de>
* Stefan Knoblich <s.knoblich@axsentis.de>
*
* mod_snmp.c -- SNMP AgentX Subagent Module
*
*/
#include <switch.h>
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include "subagent.h"
static struct {
switch_memory_pool_t *pool;
int shutdown;
} globals;
SWITCH_MODULE_LOAD_FUNCTION(mod_snmp_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_snmp_shutdown);
SWITCH_MODULE_RUNTIME_FUNCTION(mod_snmp_runtime);
SWITCH_MODULE_DEFINITION(mod_snmp, mod_snmp_load, mod_snmp_shutdown, mod_snmp_runtime);
static int snmp_callback_log(int major, int minor, void *serverarg, void *clientarg)
{
struct snmp_log_message *slm = (struct snmp_log_message *) serverarg;
switch_log_printf(SWITCH_CHANNEL_LOG, slm->priority, "%s", slm->msg);
return SNMP_ERR_NOERROR;
}
static switch_state_handler_table_t state_handlers = {
/*.on_init */ NULL,
/*.on_routing */ NULL,
/*.on_execute */ NULL,
/*.on_hangup */ NULL,
/*.on_exchange_media */ NULL,
/*.on_soft_execute */ NULL,
/*.on_consume_media */ NULL,
/*.on_hibernate */ NULL,
/*.on_reset */ NULL,
/*.on_park */ NULL,
/*.on_reporting */ NULL
};
static switch_status_t load_config(switch_memory_pool_t *pool)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
memset(&globals, 0, sizeof(globals));
globals.pool = pool;
return status;
}
SWITCH_MODULE_LOAD_FUNCTION(mod_snmp_load)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
load_config(pool);
switch_core_add_state_handler(&state_handlers);
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
/* Register callback function so we get Net-SNMP logging handled by FreeSWITCH */
snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_LOGGING, snmp_callback_log, NULL);
snmp_enable_calllog();
netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PERSIST_STATE, 1);
netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE, 1);
init_agent("mod_snmp");
init_subagent();
init_snmp("mod_snmp");
return status;
}
SWITCH_MODULE_RUNTIME_FUNCTION(mod_snmp_runtime)
{
/* block on select() */
agent_check_and_process(1);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_snmp_shutdown)
{
globals.shutdown = 1;
switch_core_remove_state_handler(&state_handlers);
snmp_shutdown("mod_snmp");
return SWITCH_STATUS_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
*/

View File

@ -0,0 +1,189 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Swarbrick <daniel.swarbrick@seventhsignal.de>
* Stefan Knoblich <s.knoblich@axsentis.de>
*
* mod_snmp.c -- SNMP AgentX Subagent Module
*
*/
#include <switch.h>
#include <switch_version.h>
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include "subagent.h"
static oid identity_oid[] = { 1,3,6,1,4,1,27880,1,1 };
static oid systemStats_oid[] = { 1,3,6,1,4,1,27880,1,2 };
/* identity sub-IDs - these must match MIB */
enum {
versionString_oid = 1,
uuid_oid
};
/* systemStats sub-IDs - these must match MIB */
enum {
uptime_oid = 1,
sessionsSinceStartup_oid,
currentSessions_oid,
maxSessions_oid,
currentCalls_oid,
sessionsPerSecond_oid,
maxSessionsPerSecond_oid
};
void init_subagent(void)
{
DEBUGMSGTL(("init_nstAgentSubagentObject", "Initializing\n"));
netsnmp_register_handler(netsnmp_create_handler_registration("identity", handle_identity, identity_oid, OID_LENGTH(identity_oid), HANDLER_CAN_RONLY));
netsnmp_register_handler(netsnmp_create_handler_registration("systemStats", handle_systemStats, systemStats_oid, OID_LENGTH(systemStats_oid), HANDLER_CAN_RONLY));
}
int handle_identity(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests)
{
static char const version[] = SWITCH_VERSION_FULL;
char uuid[40] = "";
netsnmp_request_info *request = NULL;
oid subid;
switch(reqinfo->mode) {
case MODE_GET:
for (request = requests; request; request = request->next) {
subid = request->requestvb->name[OID_LENGTH(systemStats_oid)];
switch (subid) {
case versionString_oid:
snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR, (u_char *) &version, strlen(version));
break;
case uuid_oid:
strncpy(uuid, switch_core_get_uuid(), sizeof(uuid));
snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR, (u_char *) &uuid, strlen(uuid));
break;
default:
snmp_log(LOG_WARNING, "Unregistered OID-suffix requested (%d)\n", (int) subid);
netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT);
}
}
break;
case MODE_GETNEXT:
snmp_log(LOG_ERR, "MODE_GETNEXT not supported (yet)\n");
break;
default:
/* we should never get here, so this is a really bad error */
snmp_log(LOG_ERR, "Unknown mode (%d) in handle_versionString\n", reqinfo->mode );
return SNMP_ERR_GENERR;
}
return SNMP_ERR_NOERROR;
}
int handle_systemStats(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests)
{
netsnmp_request_info *request = NULL;
oid subid;
switch_time_t uptime;
uint32_t int_val;
switch(reqinfo->mode) {
case MODE_GET:
for (request = requests; request; request = request->next) {
subid = request->requestvb->name[OID_LENGTH(systemStats_oid)];
switch (subid) {
case uptime_oid:
uptime = switch_core_uptime() / 10000;
snmp_set_var_typed_value(requests->requestvb, ASN_TIMETICKS, (u_char *) &uptime, sizeof(uptime));
break;
case sessionsSinceStartup_oid:
int_val = switch_core_session_id() - 1;
snmp_set_var_typed_value(requests->requestvb, ASN_COUNTER, (u_char *) &int_val, sizeof(int_val));
break;
case currentSessions_oid:
int_val = switch_core_session_count();
snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val));
break;
case maxSessions_oid:
switch_core_session_ctl(SCSC_MAX_SESSIONS, &int_val);;
snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val));
break;
case currentCalls_oid:
/*
* This is zero for now, since there is no convenient way to get total call
* count (not to be confused with session count), without touching the
* database.
*/
int_val = 0;
snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val));
break;
case sessionsPerSecond_oid:
switch_core_session_ctl(SCSC_LAST_SPS, &int_val);
snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val));
break;
case maxSessionsPerSecond_oid:
switch_core_session_ctl(SCSC_SPS, &int_val);
snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val));
break;
default:
snmp_log(LOG_WARNING, "Unregistered OID-suffix requested (%d)\n", (int) subid);
netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT);
}
}
break;
case MODE_GETNEXT:
snmp_log(LOG_ERR, "MODE_GETNEXT not supported (yet)\n");
break;
default:
/* we should never get here, so this is a really bad error */
snmp_log(LOG_ERR, "Unknown mode (%d) in handle_systemStats\n", reqinfo->mode);
return SNMP_ERR_GENERR;
}
return SNMP_ERR_NOERROR;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
*/

View File

@ -0,0 +1,8 @@
#ifndef subagent_H
#define subagent_H
void init_subagent(void);
Netsnmp_Node_Handler handle_identity;
Netsnmp_Node_Handler handle_systemStats;
#endif /* subagent_H */

View File

@ -584,7 +584,11 @@ static void launch_write_stream_thread(shout_context_t *context)
}
#define TC_BUFFER_SIZE 1024 * 32
#define MPGERROR() {err = "MPG123 Error at __FILE__:__LINE__."; mpg123err = mpg123_strerror(context->mh); goto error; }
#define CONCAT_LOCATION(_x,_y) _x ":" #_y
#define MAKE_LOCATION(_x,_y) CONCAT_LOCATION(_x,_y)
#define HERE MAKE_LOCATION(__FILE__, __LINE__)
#define MPGERROR() {err = "MPG123 Error at " HERE "."; mpg123err = mpg123_strerror(context->mh); goto error; }
static switch_status_t shout_file_open(switch_file_handle_t *handle, const char *path)
{
shout_context_t *context;

View File

@ -340,7 +340,7 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
switch_yield(globals.delay * 1000000);
}
destUrl = switch_mprintf("%s?uuid=%s", globals.urls[globals.url_index], switch_core_session_get_uuid(session));
destUrl = switch_mprintf("%s?uuid=%s%s", globals.urls[globals.url_index], a_prefix, switch_core_session_get_uuid(session));
curl_easy_setopt(curl_handle, CURLOPT_URL, destUrl);
if (!strncasecmp(destUrl, "https", 5)) {

View File

@ -833,7 +833,7 @@ SWITCH_DECLARE(switch_status_t) switch_socket_recvfrom(switch_sockaddr_t *from,
*/
}
if (r == 35) {
if (r == 35 || r == 730035) {
r = SWITCH_STATUS_BREAK;
}

View File

@ -151,13 +151,21 @@ static void check_ip(void)
SWITCH_STANDARD_SCHED_FUNC(heartbeat_callback)
{
send_heartbeat();
check_ip();
/* reschedule this task */
task->runtime = switch_epoch_time_now(NULL) + 20;
}
SWITCH_STANDARD_SCHED_FUNC(check_ip_callback)
{
check_ip();
/* reschedule this task */
task->runtime = switch_epoch_time_now(NULL) + 60;
}
SWITCH_DECLARE(switch_status_t) switch_core_set_console(const char *console)
{
if ((runtime.console = fopen(console, "a")) == 0) {
@ -1357,6 +1365,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc
switch_scheduler_add_task(switch_epoch_time_now(NULL), heartbeat_callback, "heartbeat", "core", 0, NULL, SSHF_NONE | SSHF_NO_DEL);
switch_scheduler_add_task(switch_epoch_time_now(NULL), check_ip_callback, "check_ip", "core", 0, NULL, SSHF_NONE | SSHF_NO_DEL | SSHF_OWN_THREAD);
switch_uuid_get(&uuid);
switch_uuid_format(runtime.uuid_str, &uuid);

View File

@ -391,10 +391,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_write(switch_file_handle_t *fh,
if ((status = fh->file_interface->file_write(fh, fh->pre_buffer_data, &blen)) != SWITCH_STATUS_SUCCESS) {
*len = 0;
}
fh->samples_out += blen;
}
}
fh->samples_out += orig_len;
return status;
} else {
switch_status_t status;

View File

@ -2755,6 +2755,26 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
}
}
}
if (session) {
switch_channel_set_variable(originate_status[i].peer_channel, "originating_leg_uuid", switch_core_session_get_uuid(session));
}
if ((vvar = switch_channel_get_variable_dup(originate_status[i].peer_channel, "execute_on_originate", SWITCH_FALSE))) {
char *app = switch_core_session_strdup(originate_status[i].peer_session, vvar);
char *arg = NULL;
if (strstr(app, "::")) {
switch_core_session_execute_application_async(originate_status[i].peer_session, app, arg);
} else {
if ((arg = strchr(app, ' '))) {
*arg++ = '\0';
}
switch_core_session_execute_application(originate_status[i].peer_session, app, arg);
}
}
}
if (table) {
@ -2773,7 +2793,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
*cause = SWITCH_CAUSE_SUCCESS;
goto outer_for;
}
if (!switch_core_session_running(originate_status[i].peer_session)) {
if (originate_status[i].per_channel_delay_start) {
switch_channel_set_flag(originate_status[i].peer_channel, CF_BLOCK_STATE);

View File

@ -372,6 +372,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
switch_event_t *event;
int divisor = 0;
int file_flags = SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT;
int restart_limit_on_dtmf = 0;
const char *prefix;
prefix = switch_channel_get_variable(channel, "sound_prefix");
@ -528,6 +529,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
if (switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
asis = 1;
}
restart_limit_on_dtmf = switch_true(switch_channel_get_variable(channel, "record_restart_limit_on_dtmf"));
if ((p = switch_channel_get_variable(channel, "RECORD_TITLE"))) {
vval = switch_core_session_strdup(session, p);
@ -637,6 +640,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
*/
if (switch_channel_has_dtmf(channel)) {
if (limit && restart_limit_on_dtmf) {
start = switch_epoch_time_now(NULL);
}
if (!args->input_callback && !args->buf && !args->dmachine) {
status = SWITCH_STATUS_BREAK;
break;

View File

@ -32,6 +32,7 @@
*/
//#define DEBUG_2833
//#define RTP_DEBUG_WRITE_DELTA
//#define DEBUG_MISSED_SEQ
#include <switch.h>
#include <switch_stun.h>
#undef PACKAGE_NAME
@ -245,6 +246,9 @@ struct switch_rtp {
switch_time_t send_time;
switch_byte_t auto_adj_used;
uint8_t pause_jb;
uint16_t last_seq;
switch_time_t last_read_time;
switch_size_t last_flush_packet_count;
};
struct switch_rtcp_senderinfo {
@ -256,6 +260,180 @@ struct switch_rtcp_senderinfo {
unsigned oc:32;
};
typedef enum {
RESULT_CONTINUE,
RESULT_GOTO_END,
RESULT_GOTO_RECVFROM,
RESULT_GOTO_TIMERCHECK
} handle_rfc2833_result_t;
static handle_rfc2833_result_t handle_rfc2833(switch_rtp_t *rtp_session, switch_size_t bytes, int *do_cng)
{
#ifdef DEBUG_2833
if (rtp_session->dtmf_data.in_digit_sanity && !(rtp_session->dtmf_data.in_digit_sanity % 100)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sanity %d\n", rtp_session->dtmf_data.in_digit_sanity);
}
#endif
if (rtp_session->dtmf_data.in_digit_sanity && !--rtp_session->dtmf_data.in_digit_sanity) {
rtp_session->dtmf_data.last_digit = 0;
rtp_session->dtmf_data.in_digit_ts = 0;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed DTMF sanity check.\n");
}
/* RFC2833 ... like all RFC RE: VoIP, guaranteed to drive you to insanity!
We know the real rules here, but if we enforce them, it's an interop nightmare so,
we put up with as much as we can so we don't have to deal with being punished for
doing it right. Nice guys finish last!
*/
if (bytes > rtp_header_len && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) &&
!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833) && rtp_session->recv_te && rtp_session->recv_msg.header.pt == rtp_session->recv_te) {
switch_size_t len = bytes - rtp_header_len;
unsigned char *packet = (unsigned char *) rtp_session->recv_msg.body;
int end;
uint16_t duration;
char key;
uint16_t in_digit_seq;
uint32_t ts;
if (!(packet[0] || packet[1] || packet[2] || packet[3]) && len >= 8) {
packet += 4;
len -= 4;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "DTMF payload offset by 4 bytes.\n");
}
if (!(packet[0] || packet[1] || packet[2] || packet[3])) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed DTMF payload check.\n");
rtp_session->dtmf_data.last_digit = 0;
rtp_session->dtmf_data.in_digit_ts = 0;
}
end = packet[1] & 0x80 ? 1 : 0;
duration = (packet[2] << 8) + packet[3];
key = switch_rfc2833_to_char(packet[0]);
in_digit_seq = ntohs((uint16_t) rtp_session->recv_msg.header.seq);
ts = htonl(rtp_session->recv_msg.header.ts);
if (in_digit_seq < rtp_session->dtmf_data.in_digit_seq) {
if (rtp_session->dtmf_data.in_digit_seq - in_digit_seq > 100) {
rtp_session->dtmf_data.in_digit_seq = 0;
}
}
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "packet[%d]: %02x %02x %02x %02x\n", (int) len, (unsigned) packet[0], (unsigned)
packet[1], (unsigned) packet[2], (unsigned) packet[3]);
#endif
if (in_digit_seq > rtp_session->dtmf_data.in_digit_seq) {
rtp_session->dtmf_data.in_digit_seq = in_digit_seq;
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "read: %c %u %u %u %u %d %d %s\n",
key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq,
ts, duration, rtp_session->recv_msg.header.m, end, end && !rtp_session->dtmf_data.in_digit_ts ? "ignored" : "");
#endif
if (!rtp_session->dtmf_data.in_digit_queued && (rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION) &&
rtp_session->dtmf_data.in_digit_ts) {
switch_dtmf_t dtmf = { key, switch_core_min_dtmf_duration(0) };
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Early Queuing digit %c:%d\n", dtmf.digit, dtmf.duration / 8);
#endif
switch_rtp_queue_rfc2833_in(rtp_session, &dtmf);
rtp_session->dtmf_data.in_digit_queued = 1;
}
/* only set sanity if we do NOT ignore the packet */
if (rtp_session->dtmf_data.in_digit_ts) {
rtp_session->dtmf_data.in_digit_sanity = 2000;
}
if (rtp_session->dtmf_data.last_duration > duration &&
rtp_session->dtmf_data.last_duration > 0xFC17 && ts == rtp_session->dtmf_data.in_digit_ts) {
rtp_session->dtmf_data.flip++;
}
if (end) {
if (rtp_session->dtmf_data.in_digit_ts) {
switch_dtmf_t dtmf = { key, duration };
if (ts > rtp_session->dtmf_data.in_digit_ts) {
dtmf.duration += (ts - rtp_session->dtmf_data.in_digit_ts);
}
if (rtp_session->dtmf_data.flip) {
dtmf.duration += rtp_session->dtmf_data.flip * 0xFFFF;
rtp_session->dtmf_data.flip = 0;
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "you're welcome!\n");
#endif
}
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "done digit=%c ts=%u start_ts=%u dur=%u ddur=%u\n",
dtmf.digit, ts, rtp_session->dtmf_data.in_digit_ts, duration, dtmf.duration);
#endif
if (!(rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION) && !rtp_session->dtmf_data.in_digit_queued) {
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Queuing digit %c:%d\n", dtmf.digit, dtmf.duration / 8);
#endif
switch_rtp_queue_rfc2833_in(rtp_session, &dtmf);
}
rtp_session->dtmf_data.last_digit = rtp_session->dtmf_data.first_digit;
rtp_session->dtmf_data.in_digit_ts = 0;
rtp_session->dtmf_data.in_digit_sanity = 0;
rtp_session->dtmf_data.in_digit_queued = 0;
*do_cng = 1;
} else {
if (!switch_rtp_ready(rtp_session)) {
return RESULT_GOTO_END;
}
switch_cond_next();
return RESULT_GOTO_RECVFROM;
}
} else if (!rtp_session->dtmf_data.in_digit_ts) {
rtp_session->dtmf_data.in_digit_ts = ts;
rtp_session->dtmf_data.first_digit = key;
rtp_session->dtmf_data.in_digit_sanity = 2000;
}
rtp_session->dtmf_data.last_duration = duration;
} else {
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "drop: %c %u %u %u %u %d %d\n",
key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq, ts, duration, rtp_session->recv_msg.header.m, end);
#endif
switch_cond_next();
return RESULT_GOTO_RECVFROM;
}
}
if (bytes && rtp_session->dtmf_data.in_digit_ts) {
if (!switch_rtp_ready(rtp_session)) {
return RESULT_GOTO_END;
}
if (!rtp_session->dtmf_data.in_interleaved && rtp_session->recv_msg.header.pt != rtp_session->recv_te) {
/* Drat, they are sending audio still as well as DTMF ok fine..... *sigh* */
rtp_session->dtmf_data.in_interleaved = 1;
}
if (rtp_session->dtmf_data.in_interleaved || (rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION)) {
if (rtp_session->recv_msg.header.pt == rtp_session->recv_te) {
return RESULT_GOTO_RECVFROM;
}
} else {
*do_cng = 1;
return RESULT_GOTO_TIMERCHECK;
}
}
return RESULT_CONTINUE;
}
static int global_init = 0;
static int rtp_common_write(switch_rtp_t *rtp_session,
rtp_msg_t *send_msg, void *data, uint32_t datalen, switch_payload_t payload, uint32_t timestamp, switch_frame_flag_t *flags);
@ -2157,6 +2335,15 @@ static void do_flush(switch_rtp_t *rtp_session)
bytes = sizeof(rtp_msg_t);
status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock_input, 0, (void *) &rtp_session->recv_msg, &bytes);
if (bytes) {
int do_cng = 0;
/* Make sure to handle RFC2833 packets, even if we're flushing the packets */
if (bytes > rtp_header_len && rtp_session->recv_te && rtp_session->recv_msg.header.pt == rtp_session->recv_te) {
handle_rfc2833(rtp_session, bytes, &do_cng);
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "*** RTP packet handled in flush loop ***\n");
#endif
}
flushed++;
@ -2195,7 +2382,52 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
*bytes = sizeof(rtp_msg_t);
status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock_input, 0, (void *) &rtp_session->recv_msg, bytes);
ts = ntohl(rtp_session->recv_msg.header.ts);
if (*bytes ) {
uint16_t seq = ntohs((uint16_t) rtp_session->recv_msg.header.seq);
if (rtp_session->last_seq && rtp_session->last_seq+1 != seq) {
#ifdef DEBUG_MISSED_SEQ
switch_size_t flushed_packets_diff = rtp_session->stats.inbound.flush_packet_count - rtp_session->last_flush_packet_count;
switch_size_t num_missed = (switch_size_t)seq - (rtp_session->last_seq+1);
if (num_missed == 1) { /* We missed one packet */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missed one RTP frame with sequence [%d]%s. Time since last read [%d]\n",
rtp_session->last_seq+1, (flushed_packets_diff == 1) ? " (flushed by FS)" : " (missed)",
rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0);
} else { /* We missed multiple packets */
if (flushed_packets_diff == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Missed %d RTP frames from sequence [%d] to [%d] (missed). Time since last read [%d]\n",
num_missed, rtp_session->last_seq+1, seq-1,
rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0);
} else if (flushed_packets_diff == num_missed) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Missed %d RTP frames from sequence [%d] to [%d] (flushed by FS). Time since last read [%d]\n",
num_missed, rtp_session->last_seq+1, seq-1,
rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0);
} else if (num_missed > flushed_packets_diff) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Missed %d RTP frames from sequence [%d] to [%d] (%d packets flushed by FS, %d packets missed)."
" Time since last read [%d]\n",
num_missed, rtp_session->last_seq+1, seq-1,
flushed_packets_diff, num_missed-flushed_packets_diff,
rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Missed %d RTP frames from sequence [%d] to [%d] (%d packets flushed by FS). Time since last read [%d]\n",
num_missed, rtp_session->last_seq+1, seq-1,
flushed_packets_diff, rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0);
}
}
#endif
}
rtp_session->last_seq = seq;
}
rtp_session->last_flush_packet_count = rtp_session->stats.inbound.flush_packet_count;
rtp_session->last_read_time = switch_micro_time_now();
if (*bytes && (!rtp_session->recv_te || rtp_session->recv_msg.header.pt != rtp_session->recv_te) &&
ts && !rtp_session->jb && !rtp_session->pause_jb && ts == rtp_session->last_cng_ts) {
/* we already sent this frame..... */
@ -2494,13 +2726,6 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
}
}
if (rtp_session->recv_msg.header.pt != 13 &&
rtp_session->recv_msg.header.pt != rtp_session->recv_te &&
(!rtp_session->cng_pt || rtp_session->recv_msg.header.pt != rtp_session->cng_pt) &&
rtp_session->recv_msg.header.pt != rtp_session->payload) {
/* drop frames of incorrect payload number and return CNG frame instead */
return_cng_frame();
}
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP) && rtp_session->rtcp_read_pollfd) {
rtcp_poll_status = switch_poll(rtp_session->rtcp_read_pollfd, 1, &rtcp_fdr, 0);
@ -2579,6 +2804,15 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
goto end;
}
if (bytes && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_UDPTL) &&
rtp_session->recv_msg.header.pt != 13 &&
rtp_session->recv_msg.header.pt != rtp_session->recv_te &&
(!rtp_session->cng_pt || rtp_session->recv_msg.header.pt != rtp_session->cng_pt) &&
rtp_session->recv_msg.header.pt != rtp_session->payload) {
/* drop frames of incorrect payload number and return CNG frame instead */
return_cng_frame();
}
if (!bytes && (io_flags & SWITCH_IO_FLAG_NOBLOCK)) {
rtp_session->missed_count = 0;
ret = 0;
@ -2835,173 +3069,20 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
bytes = sbytes;
}
#ifdef DEBUG_2833
if (rtp_session->dtmf_data.in_digit_sanity && !(rtp_session->dtmf_data.in_digit_sanity % 100)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sanity %d\n", rtp_session->dtmf_data.in_digit_sanity);
}
#endif
if (rtp_session->dtmf_data.in_digit_sanity && !--rtp_session->dtmf_data.in_digit_sanity) {
rtp_session->dtmf_data.last_digit = 0;
rtp_session->dtmf_data.in_digit_ts = 0;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed DTMF sanity check.\n");
}
/* RFC2833 ... like all RFC RE: VoIP, guaranteed to drive you to insanity!
We know the real rules here, but if we enforce them, it's an interop nightmare so,
we put up with as much as we can so we don't have to deal with being punished for
doing it right. Nice guys finish last!
*/
if (bytes > rtp_header_len && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) &&
!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833) && rtp_session->recv_msg.header.pt == rtp_session->recv_te) {
switch_size_t len = bytes - rtp_header_len;
unsigned char *packet = (unsigned char *) rtp_session->recv_msg.body;
int end;
uint16_t duration;
char key;
uint16_t in_digit_seq;
uint32_t ts;
if (!(packet[0] || packet[1] || packet[2] || packet[3]) && len >= 8) {
packet += 4;
len -= 4;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "DTMF payload offset by 4 bytes.\n");
}
if (!(packet[0] || packet[1] || packet[2] || packet[3])) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed DTMF payload check.\n");
rtp_session->dtmf_data.last_digit = 0;
rtp_session->dtmf_data.in_digit_ts = 0;
}
end = packet[1] & 0x80 ? 1 : 0;
duration = (packet[2] << 8) + packet[3];
key = switch_rfc2833_to_char(packet[0]);
in_digit_seq = ntohs((uint16_t) rtp_session->recv_msg.header.seq);
ts = htonl(rtp_session->recv_msg.header.ts);
if (in_digit_seq < rtp_session->dtmf_data.in_digit_seq) {
if (rtp_session->dtmf_data.in_digit_seq - in_digit_seq > 100) {
rtp_session->dtmf_data.in_digit_seq = 0;
}
}
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "packet[%d]: %02x %02x %02x %02x\n", (int) len, (unsigned) packet[0], (unsigned)
packet[1], (unsigned) packet[2], (unsigned) packet[3]);
#endif
if (in_digit_seq > rtp_session->dtmf_data.in_digit_seq) {
rtp_session->dtmf_data.in_digit_seq = in_digit_seq;
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "read: %c %u %u %u %u %d %d %s\n",
key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq,
ts, duration, rtp_session->recv_msg.header.m, end, end && !rtp_session->dtmf_data.in_digit_ts ? "ignored" : "");
#endif
if (!rtp_session->dtmf_data.in_digit_queued && (rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION) &&
rtp_session->dtmf_data.in_digit_ts) {
switch_dtmf_t dtmf = { key, switch_core_min_dtmf_duration(0) };
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Early Queuing digit %c:%d\n", dtmf.digit, dtmf.duration / 8);
#endif
switch_rtp_queue_rfc2833_in(rtp_session, &dtmf);
rtp_session->dtmf_data.in_digit_queued = 1;
}
/* only set sanity if we do NOT ignore the packet */
if (rtp_session->dtmf_data.in_digit_ts) {
rtp_session->dtmf_data.in_digit_sanity = 2000;
}
if (rtp_session->dtmf_data.last_duration > duration &&
rtp_session->dtmf_data.last_duration > 0xFC17 && ts == rtp_session->dtmf_data.in_digit_ts) {
rtp_session->dtmf_data.flip++;
}
if (end) {
if (rtp_session->dtmf_data.in_digit_ts) {
switch_dtmf_t dtmf = { key, duration };
if (ts > rtp_session->dtmf_data.in_digit_ts) {
dtmf.duration += (ts - rtp_session->dtmf_data.in_digit_ts);
}
if (rtp_session->dtmf_data.flip) {
dtmf.duration += rtp_session->dtmf_data.flip * 0xFFFF;
rtp_session->dtmf_data.flip = 0;
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "you're welcome!\n");
#endif
}
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "done digit=%c ts=%u start_ts=%u dur=%u ddur=%u\n",
dtmf.digit, ts, rtp_session->dtmf_data.in_digit_ts, duration, dtmf.duration);
#endif
if (!(rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION) && !rtp_session->dtmf_data.in_digit_queued) {
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Queuing digit %c:%d\n", dtmf.digit, dtmf.duration / 8);
#endif
switch_rtp_queue_rfc2833_in(rtp_session, &dtmf);
}
rtp_session->dtmf_data.last_digit = rtp_session->dtmf_data.first_digit;
rtp_session->dtmf_data.in_digit_ts = 0;
rtp_session->dtmf_data.in_digit_sanity = 0;
rtp_session->dtmf_data.in_digit_queued = 0;
do_cng = 1;
} else {
if (!switch_rtp_ready(rtp_session)) {
goto end;
}
switch_cond_next();
goto recvfrom;
}
} else if (!rtp_session->dtmf_data.in_digit_ts) {
rtp_session->dtmf_data.in_digit_ts = ts;
rtp_session->dtmf_data.first_digit = key;
rtp_session->dtmf_data.in_digit_sanity = 2000;
}
rtp_session->dtmf_data.last_duration = duration;
} else {
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "drop: %c %u %u %u %u %d %d\n",
key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq, ts, duration, rtp_session->recv_msg.header.m, end);
#endif
switch_cond_next();
goto recvfrom;
}
}
if (rtp_session->dtmf_data.in_digit_ts) {
}
if (bytes && rtp_session->dtmf_data.in_digit_ts) {
if (!switch_rtp_ready(rtp_session)) {
goto end;
}
if (!rtp_session->dtmf_data.in_interleaved && rtp_session->recv_msg.header.pt != rtp_session->recv_te) {
/* Drat, they are sending audio still as well as DTMF ok fine..... *sigh* */
rtp_session->dtmf_data.in_interleaved = 1;
}
if (rtp_session->dtmf_data.in_interleaved || (rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION)) {
if (rtp_session->recv_msg.header.pt == rtp_session->recv_te) {
goto recvfrom;
}
} else {
return_cng_frame();
}
/* Handle incoming RFC2833 packets */
switch (handle_rfc2833(rtp_session, bytes, &do_cng)) {
case RESULT_GOTO_END:
goto end;
case RESULT_GOTO_RECVFROM:
goto recvfrom;
case RESULT_GOTO_TIMERCHECK:
goto timer_check;
case RESULT_CONTINUE:
goto result_continue;
}
result_continue:
timer_check:
if (do_cng) {

View File

@ -57,6 +57,9 @@
WorkingDirectory="INSTALLLOCATION"/>
<RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/>
<RegistryValue Root="HKCU" Key="Software\FreeSWITCH\FreeSWITCH" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
<CreateFolder Directory="INSTALLLOCATION">
<Permission User="Authenticated Users" GenericAll="yes" />
</CreateFolder>
</Component>
<Component Id="FSCliShortcut" Guid="D209546C-C728-4d8f-BDB2-29AED8824282">
<Shortcut Id="FSCliStartMenuShortcut"
@ -65,6 +68,9 @@
Target="[INSTALLLOCATION]fs_cli.exe"
WorkingDirectory="INSTALLLOCATION"/>
<RegistryValue Root="HKCU" Key="Software\FreeSWITCH\FS_CLI" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
<CreateFolder Directory="INSTALLLOCATION">
<Permission User="Authenticated Users" GenericAll="yes" />
</CreateFolder>
</Component>
</DirectoryRef>