From f3082c7d75926e77062bc83c0318979e89ad0857 Mon Sep 17 00:00:00 2001
From: Moises Silva <moy@sangoma.com>
Date: Mon, 17 Jan 2011 19:15:02 -0500
Subject: [PATCH 01/54] freetdm: enable ec only upon SIGEVENT_PROGRESS_MEDIA

---
 libs/freetdm/src/ftdm_io.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c
index 6bfa37576c..c13fe76447 100644
--- a/libs/freetdm/src/ftdm_io.c
+++ b/libs/freetdm/src/ftdm_io.c
@@ -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,6 +5546,13 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
 		}
 		break;
 
+	case FTDM_SIGEVENT_PROGRESS_MEDIA:
+		{
+			ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Enabling echo cancellation on progress media\n");
+			ftdm_set_echocancel_call_begin(sigmsg->channel);
+		}
+		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 ... */

From de49305ad501b4bba758679be7b5e80b68eba1cf Mon Sep 17 00:00:00 2001
From: Travis Cross <tc@traviscross.com>
Date: Tue, 18 Jan 2011 04:23:45 +0000
Subject: [PATCH 02/54] let vmain-key and operator-key be set empty

The defaults for these keys are empty.  This change allows them to be
set empty in the XML config without error.
---
 src/mod/applications/mod_voicemail/mod_voicemail.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c
index 1799e5c7dc..76870f75b9 100644
--- a/src/mod/applications/mod_voicemail/mod_voicemail.c
+++ b/src/mod/applications/mod_voicemail/mod_voicemail.c
@@ -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,

From 7438e24d1ab38317d73ace94150573fb84778f59 Mon Sep 17 00:00:00 2001
From: cypromis <michal.bielicki@seventhsignal.de>
Date: Tue, 18 Jan 2011 10:32:45 +0100
Subject: [PATCH 03/54] fix a fedora dep and fix python path to be variable in
 sopec file

---
 freeswitch.spec | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/freeswitch.spec b/freeswitch.spec
index 66db65c698..cb83ffbeb1 100644
--- a/freeswitch.spec
+++ b/freeswitch.spec
@@ -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,6 +89,9 @@ BuildRequires: libtool >= 1.5.17
 BuildRequires: ncurses-devel
 BuildRequires: openssl-devel
 BuildRequires: perl
+%if %{_vendor} == redhat && 0%{?fedora} <= 8
+BuildRequires: perl-ExtUtils-Embed
+%endif
 BuildRequires: pkgconfig
 BuildRequires: termcap
 BuildRequires: unixODBC-devel
@@ -893,7 +896,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
 

From af0dc500ae8639d2b19c9a1a55937e7bb6f27db2 Mon Sep 17 00:00:00 2001
From: cypromis <michal.bielicki@seventhsignal.de>
Date: Tue, 18 Jan 2011 11:20:12 +0100
Subject: [PATCH 04/54] more fedora fixes

---
 freeswitch.spec | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/freeswitch.spec b/freeswitch.spec
index cb83ffbeb1..c434af6728 100644
--- a/freeswitch.spec
+++ b/freeswitch.spec
@@ -89,11 +89,13 @@ BuildRequires: libtool >= 1.5.17
 BuildRequires: ncurses-devel
 BuildRequires: openssl-devel
 BuildRequires: perl
-%if %{_vendor} == redhat && 0%{?fedora} <= 8
+% 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
@@ -954,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

From 54879c381e287b6cf0344c08086bf9d8faf686de Mon Sep 17 00:00:00 2001
From: cypromis <michal.bielicki@seventhsignal.de>
Date: Tue, 18 Jan 2011 11:21:35 +0100
Subject: [PATCH 05/54] added rpm building for callie soundfiles

---
 build/buildsounds-callie.sh         |  15 ++
 freeswitch-sounds-en-us-callie.spec | 319 ++++++++++++++++++++++++++++
 2 files changed, 334 insertions(+)
 create mode 100755 build/buildsounds-callie.sh
 create mode 100644 freeswitch-sounds-en-us-callie.spec

diff --git a/build/buildsounds-callie.sh b/build/buildsounds-callie.sh
new file mode 100755
index 0000000000..06099e6c5e
--- /dev/null
+++ b/build/buildsounds-callie.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+sounds_location=$1
+for rate in 32000 16000 8000
+do 
+    for i in ascii base256 conference currency digits 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
diff --git a/freeswitch-sounds-en-us-callie.spec b/freeswitch-sounds-en-us-callie.spec
new file mode 100644
index 0000000000..2dbb91a94e
--- /dev/null
+++ b/freeswitch-sounds-en-us-callie.spec
@@ -0,0 +1,319 @@
+##############################################################################
+# 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
+
+%if %{is_rhel5}0
+%BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+%endif
+
+%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
+
+# copy buildsounds-callie.sh script to working dir
+%{__install} -m 0750 build/buildsounds-callie.sh ./us/callie
+
+##############################################################################
+# 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/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/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/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/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/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/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/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/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
+

From 10b38944f6e51f33e3d0092ea1dcf3e88538a5a7 Mon Sep 17 00:00:00 2001
From: cypromis <michal.bielicki@seventhsignal.de>
Date: Tue, 18 Jan 2011 11:40:37 +0100
Subject: [PATCH 06/54] updated sounds version in version file

---
 build/sounds_version.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/build/sounds_version.txt b/build/sounds_version.txt
index cb0c481b13..20cb29cbd7 100644
--- a/build/sounds_version.txt
+++ b/build/sounds_version.txt
@@ -1,3 +1,3 @@
-en-us-callie 1.0.13
+en-us-callie 1.0.14
 ru-RU-elena 1.0.12
 

From 90e87a481145242bf661de4a96a7ccda1476034e Mon Sep 17 00:00:00 2001
From: Michal Bielicki <michal.bielicki@seventhsignal.de>
Date: Tue, 18 Jan 2011 15:27:57 +0300
Subject: [PATCH 07/54] this file is not needed anymore, included in spec file
 for sounds

---
 build/buildsounds-callie.sh | 15 ---------------
 1 file changed, 15 deletions(-)
 delete mode 100755 build/buildsounds-callie.sh

diff --git a/build/buildsounds-callie.sh b/build/buildsounds-callie.sh
deleted file mode 100755
index 06099e6c5e..0000000000
--- a/build/buildsounds-callie.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-sounds_location=$1
-for rate in 32000 16000 8000
-do 
-    for i in ascii base256 conference currency digits 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

From b683bb6585165c29ef883b41b97400d8ebc550df Mon Sep 17 00:00:00 2001
From: Michal Bielicki <michal.bielicki@seventhsignal.de>
Date: Tue, 18 Jan 2011 17:58:36 +0300
Subject: [PATCH 08/54] final version I hope

---
 freeswitch-sounds-en-us-callie.spec | 32 +++++++++++++++++++++++------
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/freeswitch-sounds-en-us-callie.spec b/freeswitch-sounds-en-us-callie.spec
index 2dbb91a94e..c4764570f5 100644
--- a/freeswitch-sounds-en-us-callie.spec
+++ b/freeswitch-sounds-en-us-callie.spec
@@ -46,10 +46,7 @@ BuildArch: noarch
 BuildRequires: sox
 Requires: freeswitch
 Requires: freeswitch-sounds-en-us-callie-48000
-
-%if %{is_rhel5}0
-%BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-%endif
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
 %description
 FreeSWITCH 48kHz en-us Callie prompts plus, during the installation,
@@ -111,9 +108,24 @@ FreeSWITCH Callie prompts package that pulls in the 8KHz, 16KHz,
 
 %prep
 %setup -b0 -q -n en
+mkdir -p ./usr/callie
+# create buildsounds-callie.sh script in working dir
+echo  '#!/bin/bash
 
-# copy buildsounds-callie.sh script to working dir
-%{__install} -m 0750 build/buildsounds-callie.sh ./us/callie
+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
@@ -179,6 +191,7 @@ cd %{_prefix}/sounds/en/us/callie
 %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
@@ -190,6 +203,7 @@ cd %{_prefix}/sounds/en/us/callie
 %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
@@ -204,6 +218,7 @@ cd %{_prefix}/sounds/en/us/callie
 %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
@@ -215,6 +230,7 @@ cd %{_prefix}/sounds/en/us/callie
 %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
@@ -229,6 +245,7 @@ cd %{_prefix}/sounds/en/us/callie
 %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
@@ -240,6 +257,7 @@ cd %{_prefix}/sounds/en/us/callie
 %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
@@ -254,6 +272,7 @@ cd %{_prefix}/sounds/en/us/callie
 %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
@@ -265,6 +284,7 @@ cd %{_prefix}/sounds/en/us/callie
 %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

From 190bd61d8a74678135396f28940655114d9b6513 Mon Sep 17 00:00:00 2001
From: Michal Bielicki <michal.bielicki@seventhsignal.de>
Date: Tue, 18 Jan 2011 17:58:53 +0300
Subject: [PATCH 09/54] typo in freeswitch.spec

---
 freeswitch.spec | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/freeswitch.spec b/freeswitch.spec
index c434af6728..7fb9f80d8e 100644
--- a/freeswitch.spec
+++ b/freeswitch.spec
@@ -89,7 +89,7 @@ BuildRequires: libtool >= 1.5.17
 BuildRequires: ncurses-devel
 BuildRequires: openssl-devel
 BuildRequires: perl
-% 0%{?fedora_version} >= 8
+%if 0%{?fedora_version} >= 8
 BuildRequires: perl-ExtUtils-Embed
 %endif
 BuildRequires: pkgconfig

From 1db40e60e4675ce363855ba429ceadd90e800f1c Mon Sep 17 00:00:00 2001
From: Moises Silva <moy@sangoma.com>
Date: Tue, 18 Jan 2011 11:28:37 -0500
Subject: [PATCH 10/54] freetdm: improved logic to enable/disable EC on call
 start/stop          - MFC-R2 requires tone signaling that gets screwed
 sometimes            if the EC is enabled during call setup.          - EC is
 now enabled only when switching to a state requiring          media (UP and
 PROGRESS_MEDIA)          - The logic is aware of EC persist option in Wanpipe
          - Improved logging in ftmod_wanpipe to print EC state on startup

---
 libs/freetdm/src/ftdm_io.c                    | 69 ++++++++++++-------
 libs/freetdm/src/ftdm_state.c                 | 10 +--
 libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c    |  3 -
 .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c   |  9 ++-
 libs/freetdm/src/include/private/ftdm_core.h  | 11 +++
 libs/freetdm/src/include/private/ftdm_types.h |  9 +--
 6 files changed, 70 insertions(+), 41 deletions(-)

diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c
index c13fe76447..b5f9fab93d 100644
--- a/libs/freetdm/src/ftdm_io.c
+++ b/libs/freetdm/src/ftdm_io.c
@@ -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,
@@ -5548,25 +5548,44 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
 
 	case FTDM_SIGEVENT_PROGRESS_MEDIA:
 		{
-			ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Enabling echo cancellation on progress media\n");
-			ftdm_set_echocancel_call_begin(sigmsg->channel);
+			/* 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;
 
diff --git a/libs/freetdm/src/ftdm_state.c b/libs/freetdm/src/ftdm_state.c
index 574d85845b..de62c0f0e7 100644
--- a/libs/freetdm/src/ftdm_state.c
+++ b/libs/freetdm/src/ftdm_state.c
@@ -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));
diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
index 434417726b..6e2b292ce7 100644
--- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
+++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
@@ -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));
 
diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
index 1f2ad84d72..7bcb69cd9e 100644
--- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
+++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
@@ -230,6 +230,8 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
 		ftdm_channel_t *chan;
 		ftdm_socket_t sockfd = FTDM_INVALID_SOCKET;
 		const char *dtmf = "none";
+		const char *hwec_str = "none";
+		const char *hwec_idle = "none";
 		if (!strncasecmp(span->name, "smg_prid_nfas", 8) && span->trunk_type == FTDM_TRUNK_T1 && x == 24) {
 #ifdef LIBSANGOMA_VERSION
 			sockfd = __tdmv_api_open_span_chan(spanno, x);
@@ -271,6 +273,8 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
 			|| type == FTDM_CHAN_TYPE_B) {
 				int err;
 				
+				hwec_str = "unavailable";
+				hwec_idle = "enabled";
 				dtmf = "software";
 
 				err = sangoma_tdm_get_hw_coding(chan->sockfd, &tdm_api);
@@ -289,6 +293,7 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
 
 				err = sangoma_tdm_get_hw_ec(chan->sockfd, &tdm_api);
 				if (err > 0) {
+					hwec_str = "available";
 					ftdm_channel_set_feature(chan, FTDM_CHANNEL_FEATURE_HWEC);
 				}
 				
@@ -296,6 +301,7 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
 				err = sangoma_tdm_get_hwec_persist_status(chan->sockfd, &tdm_api);
 				if (err == 0) {
 					ftdm_channel_set_feature(chan, FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE);
+					hwec_idle = "disabled";
 				}
 #else
 				if (span->trunk_type ==  FTDM_TRUNK_BRI || span->trunk_type ==  FTDM_TRUNK_BRI_PTMP) {
@@ -365,7 +371,8 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
 				ftdm_copy_string(chan->chan_number, number, sizeof(chan->chan_number));
 			}
 			configured++;
-			ftdm_log_chan(chan, FTDM_LOG_INFO, "Configured wanpipe device 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);
diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h
index 4fd8ec64ea..fbe42d33da 100644
--- a/libs/freetdm/src/include/private/ftdm_core.h
+++ b/libs/freetdm/src/include/private/ftdm_core.h
@@ -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)
diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h
index 3bc986d7f6..9e8df1f5f2 100644
--- a/libs/freetdm/src/include/private/ftdm_types.h
+++ b/libs/freetdm/src/include/private/ftdm_types.h
@@ -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)

From 0a38d7761e1099b4e369da8948f22ac7c0c8d184 Mon Sep 17 00:00:00 2001
From: Moises Silva <moy@sangoma.com>
Date: Tue, 18 Jan 2011 12:44:41 -0500
Subject: [PATCH 11/54] freetdm: set explicit numbers for channel commands to
 aid debugging

---
 libs/freetdm/src/include/freetdm.h | 114 ++++++++++++++---------------
 1 file changed, 57 insertions(+), 57 deletions(-)

diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h
index 2666a26df2..142dff888a 100644
--- a/libs/freetdm/src/include/freetdm.h
+++ b/libs/freetdm/src/include/freetdm.h
@@ -574,84 +574,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;
 

From 07fa8a4a72460bf77eac238de0b634896f8d90ca Mon Sep 17 00:00:00 2001
From: Moises Silva <moy@sangoma.com>
Date: Tue, 18 Jan 2011 13:13:30 -0500
Subject: [PATCH 12/54] freetdm: fix windows ftmod_wanpipe bug on link
 connect/disconnect

---
 libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
index 1f2ad84d72..d3e2116413 100644
--- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
+++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
@@ -1257,20 +1257,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(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(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;
 

From 51985ca69a1f050b3c724043e01582500882882c Mon Sep 17 00:00:00 2001
From: Moises Silva <moy@sangoma.com>
Date: Tue, 18 Jan 2011 13:15:04 -0500
Subject: [PATCH 13/54] freetdm: fix FTDM_IS_DCHAN macro

---
 libs/freetdm/src/include/freetdm.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h
index 142dff888a..517d6b931d 100644
--- a/libs/freetdm/src/include/freetdm.h
+++ b/libs/freetdm/src/include/freetdm.h
@@ -171,7 +171,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 || \

From 9a545bd0c9534eb6e6f7579a1b5f0e57d0a7ee6c Mon Sep 17 00:00:00 2001
From: Moises Silva <moy@sangoma.com>
Date: Tue, 18 Jan 2011 13:21:31 -0500
Subject: [PATCH 14/54] freetdm: doh

---
 libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
index be4e37047f..e2b08255ac 100644
--- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
+++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
@@ -1267,11 +1267,11 @@ static __inline__ ftdm_status_t wanpipe_channel_process_event(ftdm_channel_t *fc
 			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; */
-				ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Ignoring wanpipe link connected event\n");
+				ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Ignoring wanpipe link connected event\n");
 				break;
 			default:
 				/* *event_id = FTDM_OOB_ALARM_TRAP; */
-				ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Ignoring wanpipe link disconnected event\n");
+				ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Ignoring wanpipe link disconnected event\n");
 				break;
 			};
 			/* The WP_API_EVENT_ALARM event should be used to clear alarms */

From 137de401218c834262b0941e8b47de600a2c9052 Mon Sep 17 00:00:00 2001
From: Moises Silva <moy@sangoma.com>
Date: Tue, 18 Jan 2011 14:09:42 -0500
Subject: [PATCH 15/54] freetdm: ftmod_r2 - change warning to notice for hangup
 cause mapping

---
 libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
index 6e2b292ce7..0217a5172a 100644
--- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
+++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
@@ -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;
 }
 

From c64f4753b3003a1b091678850f272669926ff12c Mon Sep 17 00:00:00 2001
From: David Yat Sin <dyatsin@sangoma.com>
Date: Tue, 18 Jan 2011 14:36:30 -0500
Subject: [PATCH 16/54] freetdm: added missing cause enums from Q.850

---
 libs/freetdm/src/include/freetdm.h | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h
index 517d6b931d..8d67df3edc 100644
--- a/libs/freetdm/src/include/freetdm.h
+++ b/libs/freetdm/src/include/freetdm.h
@@ -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,

From 163dd056605065b2f8221e95a75e422c0f034f05 Mon Sep 17 00:00:00 2001
From: Moises Silva <moy@sangoma.com>
Date: Tue, 18 Jan 2011 16:10:14 -0500
Subject: [PATCH 17/54] freetdm: add ftdm_call_utils.h to the installed headers

---
 libs/freetdm/Makefile.am | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libs/freetdm/Makefile.am b/libs/freetdm/Makefile.am
index 2ab5c29e18..96f1c9a10f 100644
--- a/libs/freetdm/Makefile.am
+++ b/libs/freetdm/Makefile.am
@@ -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

From 54c0d6f7c41d3bc882ff339af8c01545e03606a9 Mon Sep 17 00:00:00 2001
From: Moises Silva <moy@sangoma.com>
Date: Wed, 19 Jan 2011 11:38:27 -0500
Subject: [PATCH 18/54] freetdm: workaround for Visual C++ 9.0 failing to
 compile ftdm feature macros

---
 libs/freetdm/src/include/private/ftdm_core.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h
index fbe42d33da..7cf0934f57 100644
--- a/libs/freetdm/src/include/private/ftdm_core.h
+++ b/libs/freetdm/src/include/private/ftdm_core.h
@@ -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)
 
 /*!

From bd39ad2269d302748fd55e96431b221ba6c7be6b Mon Sep 17 00:00:00 2001
From: Brian West <brian@freeswitch.org>
Date: Wed, 19 Jan 2011 11:33:01 -0600
Subject: [PATCH 19/54] FS-2995: sigh... mr collins you said you fixed this

---
 conf/lang/en/dir/sounds.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/conf/lang/en/dir/sounds.xml b/conf/lang/en/dir/sounds.xml
index 2bdc1492ec..15ecec304a 100644
--- a/conf/lang/en/dir/sounds.xml
+++ b/conf/lang/en/dir/sounds.xml
@@ -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>

From afc027473f7fc8a3ec233fb1848f728fc94f56b6 Mon Sep 17 00:00:00 2001
From: Brian West <brian@freeswitch.org>
Date: Wed, 19 Jan 2011 11:35:48 -0600
Subject: [PATCH 20/54] FS-2989: Places ;fs_path= within the contact string
 <...> when using NDLB-connectile-dysfunction-2.0, instead of just appending
 to the end of the contact string.

---
 src/mod/endpoints/mod_sofia/sofia_reg.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c
index f644ff772b..631cbdb14b 100644
--- a/src/mod/endpoints/mod_sofia/sofia_reg.c
+++ b/src/mod/endpoints/mod_sofia/sofia_reg.c
@@ -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)) {

From ea9021a24a6ce0606a2c12f3cab8f2bf0fc12db3 Mon Sep 17 00:00:00 2001
From: Brian West <brian@freeswitch.org>
Date: Wed, 19 Jan 2011 11:38:36 -0600
Subject: [PATCH 21/54] FS-2998: prefix-a-leg not respected for url submission

---
 src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c b/src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c
index a439ab8203..78d97ce259 100644
--- a/src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c
+++ b/src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c
@@ -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)) {

From 1fcffcfbc3fe6c2f21e5767fc760fdbc0c89aa68 Mon Sep 17 00:00:00 2001
From: David Yat Sin <dyatsin@sangoma.com>
Date: Wed, 19 Jan 2011 14:18:23 -0500
Subject: [PATCH 22/54] added documentation

---
 libs/freetdm/docs/io_modules.txt | 13 +++++++++++++
 1 file changed, 13 insertions(+)
 create mode 100644 libs/freetdm/docs/io_modules.txt

diff --git a/libs/freetdm/docs/io_modules.txt b/libs/freetdm/docs/io_modules.txt
new file mode 100644
index 0000000000..a164bbb249
--- /dev/null
+++ b/libs/freetdm/docs/io_modules.txt
@@ -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. 
+
+

From 6fd468043b284ee30085cf86be16ba99725d6462 Mon Sep 17 00:00:00 2001
From: David Yat Sin <dyatsin@sangoma.com>
Date: Wed, 19 Jan 2011 14:46:28 -0500
Subject: [PATCH 23/54] freetdm: fix for closing d-channel when channel is
 already closed by freetdm core

---
 libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
index f2afd1cf9c..e7053c1d43 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
@@ -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;
 }
 

From 0fdc272b25c7918359ae5b0f27277ff1926bcb75 Mon Sep 17 00:00:00 2001
From: Moises Silva <moy@sangoma.com>
Date: Wed, 19 Jan 2011 15:53:01 -0500
Subject: [PATCH 24/54] freetdm: open wanpipe devices as non-exclusive if
 possible

---
 libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
index e2b08255ac..3b384cdf32 100644
--- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
+++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
@@ -239,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) {

From 9bb344783d39da5dc3e57d48b59f551ba9a2fa4d Mon Sep 17 00:00:00 2001
From: Moises Silva <moy@sangoma.com>
Date: Wed, 19 Jan 2011 16:25:33 -0500
Subject: [PATCH 25/54] freetdm: remove collision event string

---
 libs/freetdm/src/include/freetdm.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h
index 8d67df3edc..aed40541a3 100644
--- a/libs/freetdm/src/include/freetdm.h
+++ b/libs/freetdm/src/include/freetdm.h
@@ -430,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)

From 978cb111e7971eceb238d396124e10424b148a6c Mon Sep 17 00:00:00 2001
From: David Yat Sin <dyatsin@sangoma.com>
Date: Wed, 19 Jan 2011 16:35:55 -0500
Subject: [PATCH 26/54] freetdm - improved default bearer-cap code

---
 .../ftmod_sangoma_isdn_support.c              | 29 ++++++++++++-------
 1 file changed, 19 insertions(+), 10 deletions(-)

diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c
index 9c1b7baf79..64147b7d75 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c
@@ -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;
 	}

From 1da8339ffb5719ba92ececeb27b6c335f3e6b4aa Mon Sep 17 00:00:00 2001
From: David Yat Sin <dyatsin@sangoma.com>
Date: Thu, 20 Jan 2011 10:42:28 -0500
Subject: [PATCH 27/54] freetdm: added support for early-media-override

---
 .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.c   |  3 ++
 .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.h   | 14 +++++---
 .../ftmod_sangoma_isdn_cfg.c                  | 25 +++++++++++++-
 .../ftmod_sangoma_isdn_stack_hndl.c           | 33 +++++++++++++++----
 4 files changed, 63 insertions(+), 12 deletions(-)

diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
index e7053c1d43..df528ae9c1 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
@@ -676,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 */
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
index 58fcc07040..80dc73f0fa 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
@@ -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;
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c
index aad68e15d1..afba96accc 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c
@@ -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);
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c
index 7b7c748c7a..0b52011d42 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c
@@ -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) {

From d743baefedfbe679a647013adc2718defef90718 Mon Sep 17 00:00:00 2001
From: David Yat Sin <dyatsin@sangoma.com>
Date: Thu, 20 Jan 2011 11:03:13 -0500
Subject: [PATCH 28/54] freetdm: Fix for defaulting to wrong codec

---
 .../src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c  | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c
index afba96accc..bd5b13bfec 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c
@@ -389,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;

From 70700617d3d6bd45904a81be443fe28aa7fd0387 Mon Sep 17 00:00:00 2001
From: Anthony Minessale <anthm@freeswitch.org>
Date: Thu, 20 Jan 2011 13:52:00 -0600
Subject: [PATCH 29/54] add execute_on_originate var '<app> <arg>' to run in
 origination thread or '<app>::<arg>' to run async. also originating_leg_uuid
 variable to show the uuid of the originating leg on an outbound channel

---
 src/switch_ivr_originate.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c
index d156c700fd..78743e6420 100644
--- a/src/switch_ivr_originate.c
+++ b/src/switch_ivr_originate.c
@@ -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);

From fd984d03bb629d08ac4192c5a1d3432e94ceb3d5 Mon Sep 17 00:00:00 2001
From: Anthony Minessale <anthm@freeswitch.org>
Date: Thu, 20 Jan 2011 17:52:54 -0600
Subject: [PATCH 30/54] D'oh Over zealous packet eating

---
 src/switch_rtp.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/switch_rtp.c b/src/switch_rtp.c
index 4e5450d7e8..3ce7a07e60 100644
--- a/src/switch_rtp.c
+++ b/src/switch_rtp.c
@@ -2494,7 +2494,8 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
 			}
 		}
 
-		if (rtp_session->recv_msg.header.pt != 13 && 
+		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) {

From 1c95ad98cd1c0e966b738796e74923db8919b754 Mon Sep 17 00:00:00 2001
From: Joao Mesquita <jmesquita@freeswitch.org>
Date: Thu, 20 Jan 2011 22:43:50 -0300
Subject: [PATCH 31/54] Export the variables to the b leg as well

---
 src/mod/applications/mod_dptools/mod_dptools.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c
index 41417255bb..5a3be0328d 100755
--- a/src/mod/applications/mod_dptools/mod_dptools.c
+++ b/src/mod/applications/mod_dptools/mod_dptools.c
@@ -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");

From 7fbc47f83a5bf455b6ece49deb7771d144bbce4c Mon Sep 17 00:00:00 2001
From: Jeff Lenk <jeff@jefflenk.com>
Date: Fri, 21 Jan 2011 09:09:53 -0600
Subject: [PATCH 32/54] FS-2973 Fix possible segfaults and memory leak during
 unload, and add new setting odbc-retries

---
 conf/autoload_configs/easyroute.conf.xml           |  3 +++
 src/mod/applications/mod_easyroute/mod_easyroute.c | 13 +++++++++++--
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/conf/autoload_configs/easyroute.conf.xml b/conf/autoload_configs/easyroute.conf.xml
index 7cd490942f..350a50989b 100644
--- a/conf/autoload_configs/easyroute.conf.xml
+++ b/conf/autoload_configs/easyroute.conf.xml
@@ -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 )
diff --git a/src/mod/applications/mod_easyroute/mod_easyroute.c b/src/mod/applications/mod_easyroute/mod_easyroute.c
index 481df958cf..75b4712f2d 100644
--- a/src/mod/applications/mod_easyroute/mod_easyroute.c
+++ b/src/mod/applications/mod_easyroute/mod_easyroute.c
@@ -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);

From 2e18c5b4d9fc583b76b4c8e4470579b1a21845ae Mon Sep 17 00:00:00 2001
From: Moises Silva <moy@sangoma.com>
Date: Fri, 21 Jan 2011 10:51:34 -0500
Subject: [PATCH 33/54] freetdm: added threaded media to the TODO

---
 libs/freetdm/TODO | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/libs/freetdm/TODO b/libs/freetdm/TODO
index 6b8ef8f826..6b4cf71f5f 100644
--- a/libs/freetdm/TODO
+++ b/libs/freetdm/TODO
@@ -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.
+

From 74de704973086d5cf360578ad9eac5977cfa4770 Mon Sep 17 00:00:00 2001
From: Mathieu Rene <mrene@avgs.ca>
Date: Fri, 21 Jan 2011 11:32:14 -0500
Subject: [PATCH 34/54] FS-2942 - At least display __FILE__ and __LINE__
 properly so we can have more data

---
 src/mod/formats/mod_shout/mod_shout.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/mod/formats/mod_shout/mod_shout.c b/src/mod/formats/mod_shout/mod_shout.c
index a4965c4d67..1542be485c 100644
--- a/src/mod/formats/mod_shout/mod_shout.c
+++ b/src/mod/formats/mod_shout/mod_shout.c
@@ -584,7 +584,8 @@ 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 STR(_x) #_x
+#define MPGERROR() {err = "MPG123 Error at " __FILE__ " : " STR(__LINE__) "."; 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;

From 1561ad2ca695058c79183c07c59fe1dab825deff Mon Sep 17 00:00:00 2001
From: Mathieu Rene <mrene@avgs.ca>
Date: Fri, 21 Jan 2011 11:38:56 -0500
Subject: [PATCH 35/54] extra spaces </ocd>

---
 src/mod/formats/mod_shout/mod_shout.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/mod/formats/mod_shout/mod_shout.c b/src/mod/formats/mod_shout/mod_shout.c
index 1542be485c..0b73c66b4f 100644
--- a/src/mod/formats/mod_shout/mod_shout.c
+++ b/src/mod/formats/mod_shout/mod_shout.c
@@ -585,7 +585,7 @@ static void launch_write_stream_thread(shout_context_t *context)
 
 #define TC_BUFFER_SIZE 1024 * 32
 #define STR(_x) #_x
-#define MPGERROR() {err = "MPG123 Error at " __FILE__ " : " STR(__LINE__) "."; mpg123err = mpg123_strerror(context->mh); goto error; }
+#define MPGERROR() {err = "MPG123 Error at " __FILE__ ":" STR(__LINE__) "."; 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;

From c91b409caa37a115a46f60f7b3725d7dd1b3c50e Mon Sep 17 00:00:00 2001
From: Mathieu Rene <mrene@avgs.ca>
Date: Fri, 21 Jan 2011 11:53:20 -0500
Subject: [PATCH 36/54] Tricky preprocessor... try again

---
 src/mod/formats/mod_shout/mod_shout.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/mod/formats/mod_shout/mod_shout.c b/src/mod/formats/mod_shout/mod_shout.c
index 0b73c66b4f..377cfe520c 100644
--- a/src/mod/formats/mod_shout/mod_shout.c
+++ b/src/mod/formats/mod_shout/mod_shout.c
@@ -584,8 +584,11 @@ static void launch_write_stream_thread(shout_context_t *context)
 }
 
 #define TC_BUFFER_SIZE 1024 * 32
-#define STR(_x) #_x
-#define MPGERROR() {err = "MPG123 Error at " __FILE__ ":" STR(__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;

From 6e2b1bd328607b2f0d5175b57389dfd2c3c62066 Mon Sep 17 00:00:00 2001
From: Daniel Swarbrick <daniel@seventhsignal.de>
Date: Fri, 21 Jan 2011 21:05:01 +0100
Subject: [PATCH 37/54] initial checkin of mod_snmp

---
 .../event_handlers/mod_snmp/FREESWITCH-MIB    | 110 ++++++++++
 src/mod/event_handlers/mod_snmp/Makefile      |   7 +
 src/mod/event_handlers/mod_snmp/mod_snmp.c    | 138 +++++++++++++
 src/mod/event_handlers/mod_snmp/subagent.c    | 189 ++++++++++++++++++
 src/mod/event_handlers/mod_snmp/subagent.h    |   8 +
 5 files changed, 452 insertions(+)
 create mode 100644 src/mod/event_handlers/mod_snmp/FREESWITCH-MIB
 create mode 100644 src/mod/event_handlers/mod_snmp/Makefile
 create mode 100644 src/mod/event_handlers/mod_snmp/mod_snmp.c
 create mode 100644 src/mod/event_handlers/mod_snmp/subagent.c
 create mode 100644 src/mod/event_handlers/mod_snmp/subagent.h

diff --git a/src/mod/event_handlers/mod_snmp/FREESWITCH-MIB b/src/mod/event_handlers/mod_snmp/FREESWITCH-MIB
new file mode 100644
index 0000000000..9584c8bac3
--- /dev/null
+++ b/src/mod/event_handlers/mod_snmp/FREESWITCH-MIB
@@ -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
diff --git a/src/mod/event_handlers/mod_snmp/Makefile b/src/mod/event_handlers/mod_snmp/Makefile
new file mode 100644
index 0000000000..1d8827daf1
--- /dev/null
+++ b/src/mod/event_handlers/mod_snmp/Makefile
@@ -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)
diff --git a/src/mod/event_handlers/mod_snmp/mod_snmp.c b/src/mod/event_handlers/mod_snmp/mod_snmp.c
new file mode 100644
index 0000000000..040e82b602
--- /dev/null
+++ b/src/mod/event_handlers/mod_snmp/mod_snmp.c
@@ -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:
+ */
diff --git a/src/mod/event_handlers/mod_snmp/subagent.c b/src/mod/event_handlers/mod_snmp/subagent.c
new file mode 100644
index 0000000000..8a9f2dac21
--- /dev/null
+++ b/src/mod/event_handlers/mod_snmp/subagent.c
@@ -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:
+ */
diff --git a/src/mod/event_handlers/mod_snmp/subagent.h b/src/mod/event_handlers/mod_snmp/subagent.h
new file mode 100644
index 0000000000..8a57d8a9f7
--- /dev/null
+++ b/src/mod/event_handlers/mod_snmp/subagent.h
@@ -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 */

From accc28528009361b4b1e268431d6e2b94112020a Mon Sep 17 00:00:00 2001
From: Moises Silva <moy@sangoma.com>
Date: Fri, 21 Jan 2011 15:29:07 -0500
Subject: [PATCH 38/54] freetdm: ftmod_wanpipe dummy for disabling echotrain

---
 libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
index 3b384cdf32..e08fd61f3b 100644
--- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
+++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
@@ -664,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

From 1cf79386c80712311c656a166b9dec5847857266 Mon Sep 17 00:00:00 2001
From: Anthony Minessale <anthm@freeswitch.org>
Date: Fri, 21 Jan 2011 14:27:51 -0600
Subject: [PATCH 39/54] FS-2917

---
 src/switch_core.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/src/switch_core.c b/src/switch_core.c
index b531111a6d..43fb36d705 100644
--- a/src/switch_core.c
+++ b/src/switch_core.c
@@ -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);
 

From 3dd9d5c0a399757059c60d9d8c751b97383da676 Mon Sep 17 00:00:00 2001
From: Anthony Minessale <anthm@freeswitch.org>
Date: Fri, 21 Jan 2011 14:35:23 -0600
Subject: [PATCH 40/54] FS-3007

---
 src/mod/endpoints/mod_sofia/sofia_presence.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c
index 94fef61181..19125c600b 100644
--- a/src/mod/endpoints/mod_sofia/sofia_presence.c
+++ b/src/mod/endpoints/mod_sofia/sofia_presence.c
@@ -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);

From 3fa3e11ca23f788841e00aef8342e1718675477d Mon Sep 17 00:00:00 2001
From: Michael Jerris <mike@jerris.com>
Date: Fri, 21 Jan 2011 16:03:19 -0500
Subject: [PATCH 41/54] FS-3002: handle 2833 in do_flush instead of dropping
 valid dtmf

---
 src/switch_apr.c |   2 +-
 src/switch_rtp.c | 409 ++++++++++++++++++++++++++++-------------------
 2 files changed, 245 insertions(+), 166 deletions(-)

diff --git a/src/switch_apr.c b/src/switch_apr.c
index 4c99662f45..3798d6e2dc 100644
--- a/src/switch_apr.c
+++ b/src/switch_apr.c
@@ -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;
 	}
 
diff --git a/src/switch_rtp.c b/src/switch_rtp.c
index 3ce7a07e60..faf2868f48 100644
--- a/src/switch_rtp.c
+++ b/src/switch_rtp.c
@@ -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..... */
@@ -2836,173 +3068,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) {

From e0ed0008b1712d00f21d8fedce32eeb531e5da82 Mon Sep 17 00:00:00 2001
From: Brian West <brian@freeswitch.org>
Date: Fri, 21 Jan 2011 15:08:26 -0600
Subject: [PATCH 42/54] Fix ZRTP

---
 src/switch_rtp.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/src/switch_rtp.c b/src/switch_rtp.c
index faf2868f48..4acadfe2ff 100644
--- a/src/switch_rtp.c
+++ b/src/switch_rtp.c
@@ -2726,14 +2726,6 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
 			}
 		}
 
-		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 (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);
@@ -2812,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;

From f5dafc9911eb892e0ac557bc892638cc9fb67014 Mon Sep 17 00:00:00 2001
From: Daniel Swarbrick <daniel@seventhsignal.de>
Date: Fri, 21 Jan 2011 23:42:30 +0100
Subject: [PATCH 43/54] add mod_snmp to modules.conf.in and modules.conf.xml
 (commented out)

---
 build/modules.conf.in                  | 1 +
 conf/autoload_configs/modules.conf.xml | 1 +
 2 files changed, 2 insertions(+)

diff --git a/build/modules.conf.in b/build/modules.conf.in
index 2be000f6b3..84a9e9a74d 100644
--- a/build/modules.conf.in
+++ b/build/modules.conf.in
@@ -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
diff --git a/conf/autoload_configs/modules.conf.xml b/conf/autoload_configs/modules.conf.xml
index b7100bd304..2e7ebfabe5 100644
--- a/conf/autoload_configs/modules.conf.xml
+++ b/conf/autoload_configs/modules.conf.xml
@@ -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"/> -->

From 4eccdfef58a64652ae2a1f0a7a1f11ae55346420 Mon Sep 17 00:00:00 2001
From: Andrew Thompson <andrew@hijacked.us>
Date: Fri, 21 Jan 2011 21:47:46 -0500
Subject: [PATCH 44/54] mod_erlang_event: Don't urlencode events (and destroy
 an event after use)

---
 src/mod/event_handlers/mod_erlang_event/ei_helpers.c       | 1 +
 src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/src/mod/event_handlers/mod_erlang_event/ei_helpers.c b/src/mod/event_handlers/mod_erlang_event/ei_helpers.c
index a99b52074c..db4f7780e0 100644
--- a/src/mod/event_handlers/mod_erlang_event/ei_helpers.c
+++ b/src/mod/event_handlers/mod_erlang_event/ei_helpers.c
@@ -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);
 	}
 
diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c
index 8d3c594b75..1a8bd00790 100644
--- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c
+++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c
@@ -532,6 +532,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;
 }

From 8d6d52e015411649e0591eb7ad667885523b99c3 Mon Sep 17 00:00:00 2001
From: Andrew Thompson <andrew@hijacked.us>
Date: Fri, 21 Jan 2011 21:50:02 -0500
Subject: [PATCH 45/54] mod_conference Add energy level to
 conference_add_event_member_data

This is useful when you want to find the energy a member joined with
without having to pull the XML list
---
 src/mod/applications/mod_conference/mod_conference.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c
index 2d9341a598..7f7ee83795 100644
--- a/src/mod/applications/mod_conference/mod_conference.c
+++ b/src/mod/applications/mod_conference/mod_conference.c
@@ -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;
 }

From 9fe440b2fe63935331b148ffc1d3c7a5ddffa20b Mon Sep 17 00:00:00 2001
From: Andrew Thompson <andrew@hijacked.us>
Date: Fri, 21 Jan 2011 21:53:03 -0500
Subject: [PATCH 46/54] mod_erlang_event Add proper locking for the list of XML
 bindings

---
 .../event_handlers/mod_erlang_event/handle_msg.c    |  4 ++--
 .../mod_erlang_event/mod_erlang_event.c             | 13 +++++++++----
 .../mod_erlang_event/mod_erlang_event.h             |  1 +
 3 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/src/mod/event_handlers/mod_erlang_event/handle_msg.c b/src/mod/event_handlers/mod_erlang_event/handle_msg.c
index 9ae15277fd..87f91fc51b 100644
--- a/src/mod/event_handlers/mod_erlang_event/handle_msg.c
+++ b/src/mod/event_handlers/mod_erlang_event/handle_msg.c
@@ -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));
 
diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c
index 1a8bd00790..900b9655ff 100644
--- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c
+++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c
@@ -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) {
@@ -1638,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);
diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h
index dacfbd661b..121e7b4f95 100644
--- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h
+++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h
@@ -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;

From 5316bcd9dc648b3874ebddea75ed6f34431c7f35 Mon Sep 17 00:00:00 2001
From: Steve Underwood <steveu@coppice.org>
Date: Sat, 22 Jan 2011 13:36:16 +0800
Subject: [PATCH 47/54] Typo in the spandsp .pc.in file fixed

---
 libs/spandsp/spandsp.pc.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libs/spandsp/spandsp.pc.in b/libs/spandsp/spandsp.pc.in
index 86a50ff62a..1a91ba04e1 100644
--- a/libs/spandsp/spandsp.pc.in
+++ b/libs/spandsp/spandsp.pc.in
@@ -1,5 +1,5 @@
 prefix=@prefix@
-exec_prefix=@exec_prefix@
+exec_prefix=@prefix@
 libdir=@libdir@
 includedir=@includedir@
 

From 9adac7c6988df8436c634edaaa13ae39067f8df7 Mon Sep 17 00:00:00 2001
From: Stefan Knoblich <s.knoblich@axsentis.de>
Date: Sun, 23 Jan 2011 01:42:39 +0100
Subject: [PATCH 48/54] [fsxs] Remove APR and APR-UTIL libraries from fsxs LIBS
 variable.

"LIBS" in the final fsxs script will be empty now.
We still link against libfreeswitch when building a module,
but we don't explicitly list (some of) its dependency libs anymore
(this list was not complete anyway).

This fixes a bogus /path_to_source/expat.la entry in LIBS that
came from "apu-config --libs".

Tested on Gentoo x86_64 (binutils 2.20.1) and Centos 5.5 (binutils 2.17.50).

Tested-by: Stefan Knoblich <s.knoblich@axsentis.de>
Signed-off-by: Stefan Knoblich <s.knoblich@axsentis.de>
---
 Makefile.am | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile.am b/Makefile.am
index 8d35068c35..37a01d27fb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -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
 
 ##

From b88cd3457a847cf05564df51bd8a60036b15bfd8 Mon Sep 17 00:00:00 2001
From: Jeff Lenk <jeff@jefflenk.com>
Date: Sat, 22 Jan 2011 22:51:48 -0600
Subject: [PATCH 49/54] FS-3000 mod_conference: if more digits than the length
 of the correct pin the remaining digits are accounted for next retry

---
 .../mod_conference/mod_conference.c           | 32 +++++++++++--------
 1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c
index 7f7ee83795..e6a47bf1ec 100644
--- a/src/mod/applications/mod_conference/mod_conference.c
+++ b/src/mod/applications/mod_conference/mod_conference.c
@@ -5597,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;
 
@@ -5631,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)) {
@@ -5660,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--;
 			}

From 0e37dcb5db19592d28eb771edb4a0d394f5275ac Mon Sep 17 00:00:00 2001
From: Jeff Lenk <jeff@jefflenk.com>
Date: Sun, 23 Jan 2011 17:43:38 -0600
Subject: [PATCH 50/54] windows - tweak installer permissions

---
 w32/Setup/Product.wxs | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/w32/Setup/Product.wxs b/w32/Setup/Product.wxs
index 2f072aa8ca..1de2ec204d 100644
--- a/w32/Setup/Product.wxs
+++ b/w32/Setup/Product.wxs
@@ -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>
 

From 6294bc1620c94785f23bf6ae6966aaa67cf34c7f Mon Sep 17 00:00:00 2001
From: Anthony Minessale <anthm@freeswitch.org>
Date: Mon, 24 Jan 2011 09:41:53 -0600
Subject: [PATCH 51/54] have samples_out reflect what was written to the FH not
 the file even with buffering

---
 src/switch_core_file.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/switch_core_file.c b/src/switch_core_file.c
index c00756ffc6..19f23546f0 100644
--- a/src/switch_core_file.c
+++ b/src/switch_core_file.c
@@ -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;

From 7a1dcb69581ba593f3dc3868c94c1124c41e64f3 Mon Sep 17 00:00:00 2001
From: Anthony Minessale <anthm@freeswitch.org>
Date: Mon, 24 Jan 2011 09:43:16 -0600
Subject: [PATCH 52/54] add record_restart_time_limit_on_dtmf var

---
 src/switch_ivr_play_say.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/switch_ivr_play_say.c b/src/switch_ivr_play_say.c
index 523dfdeb02..4e9e7b95ca 100644
--- a/src/switch_ivr_play_say.c
+++ b/src/switch_ivr_play_say.c
@@ -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;

From 6e4c30ea377728107e0747d614565eca964fa1d3 Mon Sep 17 00:00:00 2001
From: Anthony Minessale <anthm@freeswitch.org>
Date: Mon, 24 Jan 2011 09:49:27 -0600
Subject: [PATCH 53/54] update code in mod_celt to match API of 0.10.0

---
 src/mod/codecs/mod_celt/mod_celt.c | 34 +++++++++++-------------------
 1 file changed, 12 insertions(+), 22 deletions(-)

diff --git a/src/mod/codecs/mod_celt/mod_celt.c b/src/mod/codecs/mod_celt/mod_celt.c
index 37983f3683..8d36b6af12 100644
--- a/src/mod/codecs/mod_celt/mod_celt.c
+++ b/src/mod/codecs/mod_celt/mod_celt.c
@@ -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;

From a8f5bf60a87fb27420846bd9d9af5e61f1f947d6 Mon Sep 17 00:00:00 2001
From: Anthony Minessale <anthm@freeswitch.org>
Date: Mon, 24 Jan 2011 12:18:02 -0600
Subject: [PATCH 54/54] fix proper display of meta digit in log lines

---
 src/include/switch_utils.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h
index 2c4de14334..a1a93c6ac8 100644
--- a/src/include/switch_utils.h
+++ b/src/include/switch_utils.h
@@ -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)