Project "FreeSWITCH Source" received a push.

branch: master updated

       via: a53599b9b4cf991f9e5e3d8dd5ce7f249a41e039 (commit)
       via: 0bce777a4a06701798e426b13b8b7e0153836077 (commit)
       via: 17d521128014853b24f983307fc28317f11e950b (commit)
       via: e81e8096507dc39c8ba457f9641dc0a1c09900f7 (commit)
       via: 1341a75ad899d35f9003e4514cb5c8f724e0e7da (commit)
       via: 04bb74fcaeb72683754ed4b4d6df197a898887b7 (commit)
       via: 436413e0bb506a07758c60cdcf4a6be1adc0e575 (commit)
       via: 3fd7b8f2675b6198e9edbdf2359794d5dc134b0a (commit)
       via: a2c0da53f368f0b11340c3a72814c93b182753b7 (commit)
       via: 88d410d31485d13911f0958af5a73f1f6f49a454 (commit)
       via: 02234ae87db5fcca0168a140b5800618de65d3d9 (commit)
       via: 145884c94ce9bcb25aa14d45e6d689b0d4af75ed (commit)
       via: e6be62b0e14a1865f14617abde8eafdb667bbadb (commit)
       via: edfb1e9943b12a085ebb90190c5119721bee8550 (commit)
       via: 381738f70027fb4641f840d16597151eed8d7f67 (commit)
       via: acd6333e33b9ff9e0f1a424cb7dc5e5b1d063b6a (commit)
       via: d8b11ce63b908ae893feda5345ed712c9125623a (commit)
       via: b8afa79b4446b80336285d1ce0bb4293cb9e04ed (commit)
       via: 2582d71689191909fd8a62b5f5693ebd1b4dc8d1 (commit)
       via: c17da69d6773e2ac37bc256ad0669ea901525bec (commit)
       via: 3546654615f88058fb6769fe79e07162602fa4af (commit)
       via: 46215605f42bf534ab040e63b9bd84a6c34c3e05 (commit)
       via: 361178089943c14bb3f842d7ff5cd8950cbe2493 (commit)
       via: 1ee94c11c7b2fd46508eebb463ffd9a1cf9b19ce (commit)
       via: 6f9da9a070517ce30e9edec6a7d2536db0646c33 (commit)
       via: eeac03ef5028b565b28364752ef5a48307ca17d4 (commit)
       via: 8037b69f40413784631c59942b5d4fc856cff845 (commit)
       via: 67edc7c3215f6476452f3ff7ee82ba559c39656f (commit)
       via: 2adfc50af7958eea12c15e023bcf80b18a4c73f9 (commit)
       via: 0cbac4ad25ed3921262a7676397206f824aade32 (commit)
       via: 2401fec54b48d8dfb1ec5a2f33a092dac076c0f3 (commit)
       via: 330d741853f4f7c548b61dbcb717266a2bf24107 (commit)
       via: 93501b288b34a7d4f5287f7bc2b498a2321d73c5 (commit)
       via: df4a18dcba1ad6a3ac20f67982642e8fe0e35471 (commit)
       via: 0e841a5f14810514ee60562481c405d7fb560e72 (commit)
       via: a93623618b83fb08f2a0a728800f431856b29f92 (commit)
       via: 804fc61a6c28f85321614ab74ba3986e2cd7a771 (commit)
       via: 428ef9666734805fa7f97f8291c06252a4f1b798 (commit)
       via: f64b03bd8b25deb191fd456a1854b02fd73626fc (commit)
       via: 3830484155cfa3bd8ef09b88515e8afa6c251121 (commit)
       via: bcb2262fdc48b36bd2e6bfe45adcbaecd1d091ee (commit)
       via: f0a31e1bfff2d49d97bc0ee83627c426fa311bfc (commit)
       via: 526e6fe48cadc9418d64f2b639bad68d8883dcdd (commit)
       via: 8c12162a9d92ceac55c6305f2336efcf7157b923 (commit)
       via: bab7a2392f955facbb91d0f30512682e2b38773e (commit)
       via: 946ec62893014a5796d0d90b1fc62797d4102164 (commit)
       via: 1cc51046c5b5b61e86394b97996a2d7833244f90 (commit)
       via: 12c13e115b96e9e036bd65655c1f12a72a83510e (commit)
       via: cf83f9c381a6abb988efc41b8711271b4665b79e (commit)
       via: 080c5ae98167e590bebf698439c550bdb656925e (commit)
       via: 0806c3880104fff154802adb010713365ef6a0ed (commit)
       via: d4b5b07b2a76404ed8bf5adf8bc2bc9c0cbd9f04 (commit)
       via: 2b4f163826132cf55698008a22c065374320796a (commit)
       via: 7386b9f8f55e6b2648bcfb3f9dafaf62dccd772e (commit)
       via: 0d5fcf65a0fef932f32874da6f4bdddb69279c53 (commit)
       via: b3086c1d6b6f4900ec770e22878038ac565424d9 (commit)
       via: 1e09a4d2dafdd9a5ffa2ab606d2caebf52baf25f (commit)
       via: beb829053945926447ba0f970faf1a3326d83981 (commit)
       via: 294436486302d0547b34ba26e5fa402c4ebaa58f (commit)
       via: 998a04d2cfa361a4d600175809d5fef02374c720 (commit)
       via: e7d68a79dc7838d74e7b8985494dcde532910d32 (commit)
       via: 8f565277e3a9e814c12779f3d51f2527a081ef99 (commit)
       via: 20976da4114c2c5fc0213fa4cda91f7f4bf8a136 (commit)
       via: e37dd41e311986015393befed7160e27a6450933 (commit)
       via: b8b7266abb7a6c081ad1e1531aea69daf5d7509c (commit)
       via: f4481b05ab8ae1faf6eedb438085e688371e79c6 (commit)
       via: e9e33f5160fb5272c4f912dac6a29415215bba1c (commit)
       via: 36f6218b8bba3233cf3fb501b01a0288a08e9f00 (commit)
       via: 2ec2a9b0d335a8d6a30ab5a92448ac3ad63649ff (commit)
       via: 46f6c6e42d2775ccfecb8f445ebbaaf32ab34df7 (commit)
       via: b6ac001276961761b14a89270da02498b4d3e740 (commit)
       via: 2d190b37abe00999a2e76861b8c88f0053e0b78f (commit)
       via: dc436b82a52da05686ac178ad7854556e9688ed8 (commit)
       via: bdf678e401a8077aab06b9c04004c92ef6631e26 (commit)
       via: e79174cacf6abb943fe34840a5261b940b281c91 (commit)
       via: 33b74ca8c710a58d245ea8903f98e0e86cffe164 (commit)
       via: 68d08547f36777e2c091008b5e1207ca5b15e9e2 (commit)
       via: 41dc6f46db0140b171d5ae71bfe923e7605f0cff (commit)
       via: e5fb456f3bfddbf1e379c77030e8e4dd5549d12a (commit)
       via: 74a0cfd1e101413a3941c41d04ee01d8df2ae418 (commit)
       via: b55b4eeaeea1d1cebc5a44ffdd88b224898d5d8a (commit)
       via: f60fdf653dd2d7f8d3eaa6a9086e1f68bd993c59 (commit)
       via: 85913b70b43483d4d3d840d128549ddba75b56a6 (commit)
       via: 257bf9a46c44f76d8b38c90f288f364bcf1c6398 (commit)
       via: 4ae8282e6c6df0e296113e9b4b4a1383e1af8ad7 (commit)
       via: 89c5f3bf8226bf605336b66e7761fd9f753d935a (commit)
       via: 83dea0ee45a1eed53fe6c7bcac96410229c2fe3c (commit)
       via: 944b99687ea3e6f14f6eeb1f6daa97a6905fbb1d (commit)
       via: 57b0710bacb7cc58dee4262fe0c915048e47b7bc (commit)
       via: 673678509f0f3ea0464ea45798c0cdbc4843946b (commit)
       via: 10d696ebacedde5416e99f03911c928eea8889d1 (commit)
       via: 43dd776c3616f3735bd8b73d965f81e9d16dab79 (commit)
       via: fb66abfab4a74055c38cdc67da83e6e0175a4a0b (commit)
       via: ae4b2873b0e56090658953f503157166825b66bc (commit)
       via: 45ec088753031fc60b1b1abeb25536b7ac042374 (commit)
       via: 53aeb1c1a71e6546950721d9f79f4a6131eb3071 (commit)
       via: be370d45ebf5bc7fc329ef0b1abd48c2e38c8e9b (commit)
       via: 4371d3c804d890315ca623e2930286154d80a9a8 (commit)
       via: 7c3ee98d3375dcab851ed8f4eb4b3d6a991295b1 (commit)
       via: 1932b3fe3bc8de85098eaf9b810da9d3b027d865 (commit)
       via: a382990d9f23096d04812cea6d66f6c3f3994e89 (commit)
       via: becb94052ac619290e6825c4f985917134c6bce2 (commit)
       via: 231a7ffaa19886653705c217a73d8e25b705503c (commit)
       via: 0d276e7d7b7b52ac5510d139d8252fc10ad37298 (commit)
       via: 92f51bd60332511c5689c0993cf561f4a5493297 (commit)
       via: 9a8eea27feb6f300d5adeb078cad82974681bca7 (commit)
       via: 189db0e7ad0f4ef29ffa703114ff1d94a20d0b8f (commit)
       via: 1842798e95eeeed61604455ebcd5001bdf35eeb1 (commit)
       via: 155571d841effd7411686952da0d679af34bc0ac (commit)
       via: e1c17cffe0bfbf7c50a02acc9384679ef283a96b (commit)
       via: f37390f0a7f1ca636d54c23d6873510fcf26e91e (commit)
       via: 1388ed811a2369b26778c4cce158691f285c45b4 (commit)
       via: 23b387b7f5f4b13ca40c9d62ab06a04c66810e63 (commit)
       via: 00bba5790b9deeb34c7c40c289ac66ff59c9b39b (commit)
      from: 80cbfe6fa3f3e11852436d9fdbd44811775ac074 (commit)


= COMMIT LOG ===========================================================
committer: Michael S Collins
comments: 
Merge branch 'master' of git://git.freeswitch.org/freeswitch
committer: Anthony Minessale
comments: 
fix regression in rtp stack trying to avoid broken clients who send the wrong payload type, we were eating the stun packets in jingle calls

diff --git a/src/switch_rtp.c b/src/switch_rtp.c
index 200f4f0..faa79e3 100644
--- a/src/switch_rtp.c
+++ b/src/switch_rtp.c
@@ -2808,7 +2808,8 @@ 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) &&
+		if (bytes && rtp_session->recv_msg.header.version == 2 && 
+			!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) && 
committer: Brian West
comments: 
add make targets for mod_com_g729 mod_com_g729-activate mod_com_g729-install mod_com_g729-clean mod_com_g729-uninstall

diff --git a/.gitignore b/.gitignore
index c53d07d..2480b83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,45 +46,47 @@ core.*
 !/w32/Console/FreeSwitchConsole.vcproj.user
 !/w32/Setup/inno_setup/vcredist_x64.exe
 !/w32/Setup/inno_setup/vcredist_x86.exe
-/.version
-/AUTHORS
-/COPYING
-/ChangeLog
-/Makefile
-/Makefile.in
-/NEWS
-/README
-/TAGS
+.version
+AUTHORS
+COPYING
+ChangeLog
+Makefile
+Makefile.in
+NEWS
+README
+TAGS
 aclocal.m4
 autom4te.cache
-/build/Makefile
-/build/Makefile.in
-/build/config/compile
-/build/config/config.guess
-/build/config/depcomp
-/build/config/install-sh
-/build/config/ltmain.sh
-/build/config/missing
-/build/freeswitch.pc
-/build/getlib.sh
-/build/getsounds.sh
-/build/modmake.rules
+build/Makefile
+build/Makefile.in
+build/config/compile
+build/config/config.guess
+build/config/depcomp
+build/config/install-sh
+build/config/ltmain.sh
+build/config/missing
+build/freeswitch.pc
+build/getlib.sh
+build/getsounds.sh
+build/modmake.rules
+build/getg729.sh
 config.cache
 config.log
 config.status
-/configure
+configure
 configure.lineno
-/freeswitch
-/fs_cli
-/fs_encode
-/fs_ivrd
-/libtool
-/modules.conf
-/quiet_libtool
-/tone2wav
-/scripts/fsxs
-/scripts/gentls_cert
-/a.out.dSYM
+freeswitch
+fs_cli
+fs_encode
+fs_ivrd
+libtool
+noreg
+modules.conf
+quiet_libtool
+tone2wav
+scripts/fsxs
+scripts/gentls_cert
+a.out.dSYM
 src/mod/applications/mod_easyroute/Makefile
 src/mod/applications/mod_lcr/Makefile
 src/mod/applications/mod_nibblebill/Makefile
@@ -102,6 +104,7 @@ src/mod/say/mod_say_th/Makefile
 src/mod/say/mod_say_zh/Makefile
 libs/curl/lib/ca-bundle.h
 libs/g729/
+libs/fsg729-*-installer
 src/mod/codecs/mod_com_g729/
 src/mod/languages/mod_lua/mod_lua_wrap.cpp.orig
 src/mod/languages/mod_perl/mod_perl_wrap.cpp.orig
diff --git a/build/getg729.sh.in b/build/getg729.sh.in
new file mode 100755
index 0000000..c8a7227
--- /dev/null
+++ b/build/getg729.sh.in
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+TAR=@TAR@
+ZCAT=@ZCAT@
+WGET=@WGET@
+CURL=@CURL@
+
+if [ -f "$WGET" ] ; then
+    DOWNLOAD_CMD=$WGET
+else
+    if [ -f "$CURL" ] ; then
+        DOWNLOAD_CMD="$CURL -O"
+    fi
+fi
+
+base=http://files.freeswitch.org/g729/
+tarfile=$1
+url=`echo $tarfile | grep "://"`
+
+if [ ! -z $url ] ; then
+    base=$tarfile/
+    tarfile=$2
+fi
+
+if [ ! -f $tarfile ] ; then
+    $DOWNLOAD_CMD $base$tarfile
+    if [ ! -f $tarfile ] ; then
+	echo cannot find $tarfile
+	exit 1
+    fi
+fi
+
+exit 0
+
diff --git a/build/modules.conf.in b/build/modules.conf.in
index 8d3dfaa..63a0ab4 100644
--- a/build/modules.conf.in
+++ b/build/modules.conf.in
@@ -42,6 +42,7 @@ codecs/mod_amr
 #codecs/mod_silk
 #codecs/mod_codec2
 codecs/mod_g729
+#codecs/mod_com_g729
 codecs/mod_h26x
 codecs/mod_bv
 codecs/mod_ilbc
diff --git a/configure.in b/configure.in
index d91cf11..a0c9418 100644
--- a/configure.in
+++ b/configure.in
@@ -730,6 +730,8 @@ AC_PATH_PROGS(WGET, wget)
 AC_PATH_PROGS(CURL, curl)
 GETLIB="cd $switch_srcdir/libs && ${SHELL} $switch_builddir/build/getlib.sh"
 AC_SUBST(GETLIB)
+GETG729="cd $switch_srcdir/libs && ${SHELL} $switch_builddir/build/getg729.sh"
+AC_SUBST(GETG729)
 GETSOUNDS="${SHELL} $switch_builddir/build/getsounds.sh"
 AC_SUBST(GETSOUNDS)
 
@@ -916,6 +918,7 @@ AC_CONFIG_FILES([Makefile
 		src/mod/applications/mod_osp/Makefile
 		src/mod/applications/mod_stress/Makefile
 		src/mod/applications/mod_hash/Makefile
+		src/mod/codecs/mod_com_g729/Makefile
 		src/mod/endpoints/mod_portaudio/Makefile
 		src/mod/endpoints/mod_skinny/Makefile
 		src/mod/endpoints/mod_skypopen/Makefile
@@ -930,6 +933,7 @@ AC_CONFIG_FILES([Makefile
 		src/include/switch_am_config.h
 		build/getsounds.sh
 		build/getlib.sh
+		build/getg729.sh
 		build/freeswitch.pc
 		build/modmake.rules
 		libs/xmlrpc-c/include/xmlrpc-c/config.h
@@ -1023,6 +1027,7 @@ AC_OUTPUT
 ##
 ## Registering for ClueCon
 ##
+if ! test -f noreg ; then
 echo ""
 echo ""
 echo $ECHO_N "Registering you for ClueCon http://www.cluecon.com $ECHO_C" 1>&6
@@ -1040,6 +1045,7 @@ sleep 1
 AC_MSG_RESULT([ See you in August. ;-)])
 sleep 2
 echo ""
+fi
 
 ##
 ## Configuration summary
diff --git a/src/mod/Makefile.am b/src/mod/Makefile.am
index e655cf7..5af782d 100644
--- a/src/mod/Makefile.am
+++ b/src/mod/Makefile.am
@@ -21,7 +21,7 @@ $(OUR_MODULES) $(OUR_CLEAN_MODULES) $(OUR_INSTALL_MODULES) $(OUR_UNINSTALL_MODUL
 		fi ; \
 	fi ; \
 	if test -z "$$target" ; then target="all" ; fi ; \
-	if ! test -f $$moddir/$$modname.c && ! test -f $$moddir/$$modname.cpp ;	\
+	if ! test -f $$moddir/$$modname.c && ! test -f $$moddir/$$modname.cpp && test $$modname != "mod_com_g729" ;	\
 	then echo ; echo "WARNING $$modname is not a valid FreeSWITCH module dir, skipping it..." ; else \
 		echo ;\
 		echo making $$target $$modname ;\
@@ -35,6 +35,9 @@ $(OUR_MODULES) $(OUR_CLEAN_MODULES) $(OUR_INSTALL_MODULES) $(OUR_UNINSTALL_MODUL
 	fi; \
 	test -z "$$fail" ;
 
+mod_com_g729-activate:
+	cd $(switch_builddir)/src/mod/codecs/mod_com_g729 && $(MAKE) $(AM_MAKEFLAGS) activate
+
 .DEFAULT:
 	@if test -z "`echo $@ | grep all`"; then  $(MAKE) $(AM_MAKEFLAGS) $@-all ; else echo Unknown target `echo $@ | sed -e 's|-all||'`; exit 1; fi
 
diff --git a/src/mod/codecs/mod_com_g729/Makefile.am b/src/mod/codecs/mod_com_g729/Makefile.am
new file mode 100644
index 0000000..7b63138
--- /dev/null
+++ b/src/mod/codecs/mod_com_g729/Makefile.am
@@ -0,0 +1,39 @@
+include $(top_srcdir)/build/modmake.rulesam
+
+MODNAME=mod_com_g729
+VERSION=193
+
+if ISLINUX
+
+G729INSTALLER = $(top_srcdir)/libs/fsg729-$(VERSION)-installer
+LICSERVER=/usr/sbin/freeswitch_licence_server
+VALIDATOR=$(bindir)/validator
+MOD=$(moddir)/mod_com_g729.so
+BUILT_SOURCES = $(G729INSTALLER)
+
+install: $(LICSERVER) $(VALIDATOR) $(MOD)
+
+$(LICSERVER) $(VALIDATOR) $(MOD): $(G729INSTALLER)
+	$(SHELL) $(G729INSTALLER) $(bindir) $(moddir) nobanner
+	$(ECHO)
+	$(ECHO)
+	$(ECHO) Now you can activate your license by running $(MAKE) mod_com_g729-activate
+	$(ECHO)
+	$(ECHO)
+
+$(G729INSTALLER):
+	rm -f $(top_srcdir)/libs/fsg729-*-installer*
+	$(GETG729) fsg729-$(VERSION)-installer
+	chmod 755 $(G729INSTALLER)
+
+clean:
+	rm -f $(top_srcdir)/libs/fsg729-*-installer*
+	rm -rf /tmp/fsg729
+
+activate: $(LICSERVER) $(VALIDATOR) $(MOD)
+	$(VALIDATOR)
+
+uninstall: clean
+	rm -f $(LICSERVER) $(VALIDATOR) $(MOD)
+
+endif
committer: Anthony Minessale
comments: 
don't encourage ppl to use vad on mod_dingaling

diff --git a/conf/jingle_profiles/client.xml b/conf/jingle_profiles/client.xml
index 66c3492..cac7069 100644
--- a/conf/jingle_profiles/client.xml
+++ b/conf/jingle_profiles/client.xml
@@ -24,7 +24,7 @@
     <!-- VAD choose one -->
     <!-- <param name="vad" value="in"/> -->
     <!-- <param name="vad" value="out"/> -->
-    <param name="vad" value="both"/>
+    <!--<param name="vad" value="both"/>-->
     <!--<param name="avatar" value="/path/to/tiny.jpg"/>-->
     <!--<param name="candidate-acl" value="wan.auto"/>-->
     <param name="local-network-acl" value="localnet.auto"/>
committer: Anthony Minessale
comments: 
fix race with media bug exiting from write frame while read frame is trying to use it

diff --git a/src/switch_core_io.c b/src/switch_core_io.c
index decb587..4e1c707 100644
--- a/src/switch_core_io.c
+++ b/src/switch_core_io.c
@@ -318,11 +318,24 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
 				switch_codec_t *use_codec = read_frame->codec;
 				if (do_bugs) {
 					switch_thread_rwlock_wrlock(session->bug_rwlock);
+					if (!session->bugs) {
+						do_bugs = 0;
+						switch_thread_rwlock_unlock(session->bug_rwlock);
+						goto done;
+					}
+
 					if (!switch_core_codec_ready(&session->bug_codec)) {
 						switch_core_codec_copy(read_frame->codec, &session->bug_codec, NULL);
 					}
 					use_codec = &session->bug_codec;
 					switch_thread_rwlock_unlock(session->bug_rwlock);
+
+					switch_thread_rwlock_wrlock(session->bug_rwlock);
+					if (!session->bugs) {
+						do_bugs = 0;
+					}
+					switch_thread_rwlock_unlock(session->bug_rwlock);
+					if (!do_bugs) goto done;
 				}
 
 				if (switch_test_flag(read_frame, SFF_PLC)) {
committer: Anthony Minessale
comments: 
FS-3050 FS-3051

diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c
index 76b1dcc..5109e0b 100644
--- a/src/mod/endpoints/mod_sofia/sofia_reg.c
+++ b/src/mod/endpoints/mod_sofia/sofia_reg.c
@@ -1543,6 +1543,8 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
 				}
 			}
 		} else {
+			switch_core_del_registration(to_user, reg_host, call_id);
+
 			if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_UNREGISTER) == SWITCH_STATUS_SUCCESS) {
 				switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name);
 				switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-user", to_user);
diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c
index ba92ebc..f54bd65 100644
--- a/src/switch_core_sqldb.c
+++ b/src/switch_core_sqldb.c
@@ -1625,7 +1625,7 @@ static char create_nat_sql[] =
 
 static char create_registrations_sql[] =
 	"CREATE TABLE registrations (\n"
-	"   user      VARCHAR(256),\n"
+	"   reg_user      VARCHAR(256),\n"
 	"   realm     VARCHAR(256),\n"
 	"   token     VARCHAR(256),\n"
 	"   url      TEXT,\n"
@@ -1635,7 +1635,7 @@ static char create_registrations_sql[] =
 	"   network_proto VARCHAR(256),\n"
 	"   hostname VARCHAR(256)\n"
 	");\n"
-	"create index regindex1 on registrations (user,real,hostname);\n";
+	"create index regindex1 on registrations (user,realm,hostname);\n";
 	
 
 SWITCH_DECLARE(switch_status_t) switch_core_add_registration(const char *user, const char *realm, const char *token, const char *url, uint32_t expires, 
@@ -1653,7 +1653,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_add_registration(const char *user, c
 	switch_cache_db_execute_sql(dbh, sql, NULL);
 	free(sql);
 
-	sql = switch_mprintf("insert into registrations (user,realm,token,url,expires,network_ip,network_port,network_proto,hostname) "
+	sql = switch_mprintf("insert into registrations (reg_user,realm,token,url,expires,network_ip,network_port,network_proto,hostname) "
 						 "values ('%q','%q','%q','%q',%ld,'%q','%q','%q','%q')",
 						 switch_str_nil(user),
 						 switch_str_nil(realm),
@@ -1685,7 +1685,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_del_registration(const char *user, c
 		return SWITCH_STATUS_FALSE;
 	}
 
-	sql = switch_mprintf("delete from registrations where user='%q' and realm='%q' and hostname='%q'", user, realm, switch_core_get_hostname());
+	sql = switch_mprintf("delete from registrations where reg_user='%q' and realm='%q' and hostname='%q'", user, realm, switch_core_get_hostname());
 
 	switch_cache_db_execute_sql(dbh, sql, NULL);
 	switch_cache_db_release_db_handle(&dbh);
@@ -1798,7 +1798,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_
 	switch_cache_db_test_reactive(dbh, "select hostname from complete", "DROP TABLE complete", create_complete_sql);
 	switch_cache_db_test_reactive(dbh, "select hostname from aliases", "DROP TABLE aliases", create_alias_sql);
 	switch_cache_db_test_reactive(dbh, "select hostname from nat", "DROP TABLE nat", create_nat_sql);
-	switch_cache_db_test_reactive(dbh, "delete from registrations where network_proto='tcp' or network_proto='tls'", 
+	switch_cache_db_test_reactive(dbh, "delete from registrations where reg_user='' or network_proto='tcp' or network_proto='tls'", 
 								  "DROP TABLE registrations", create_registrations_sql);
 
 
@@ -1816,7 +1816,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_
 			}
 			switch_cache_db_test_reactive(dbh, "select ikey from interfaces", "DROP TABLE interfaces", create_interfaces_sql);
 			switch_cache_db_test_reactive(dbh, "select hostname from tasks", "DROP TABLE tasks", create_tasks_sql);
-			switch_cache_db_test_reactive(dbh, "delete from registrations where network_proto='tcp' or network_proto='tls'", 
+			switch_cache_db_test_reactive(dbh, "delete from registrations where reg_user='' or network_proto='tcp' or network_proto='tls'", 
 										  "DROP TABLE registrations", create_registrations_sql);
 
 			if (runtime.odbc_dbtype == DBTYPE_DEFAULT) {
committer: Anthony Minessale
comments: 
clear unique headers on event_socket filters

diff --git a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c
index 1462e4e..2bb1d45 100644
--- a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c
+++ b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c
@@ -1783,6 +1783,7 @@ static switch_status_t parse_command(listener_t *listener, switch_event_t **even
 		switch_mutex_lock(listener->filter_mutex);
 		if (!listener->filters) {
 			switch_event_create_plain(&listener->filters, SWITCH_EVENT_CLONE);
+			switch_clear_flag(listener->filters, EF_UNIQ_HEADERS);
 		}
 
 		if (!strcasecmp(header_name, "delete") && header_val) {
committer: Marc Olivier Chouinard
comments: 
switch_channel: Add CS_NONE and correct variable name

diff --git a/src/switch_channel.c b/src/switch_channel.c
index f750496..9e3064b 100644
--- a/src/switch_channel.c
+++ b/src/switch_channel.c
@@ -184,7 +184,7 @@ struct switch_callstate_table {
 	const char *name;
 	switch_channel_callstate_t callstate;
 };
-static struct switch_callstate_table STATE_CHART[] = {
+static struct switch_callstate_table CALLSTATE_CHART[] = {
     {"DOWN", CCS_DOWN},
     {"DIALING", CCS_DIALING},
     {"RINGING", CCS_RINGING},
@@ -228,9 +228,9 @@ SWITCH_DECLARE(const char *) switch_channel_callstate2str(switch_channel_callsta
 	uint8_t x;
 	const char *str = "UNKNOWN";
 
-	for (x = 0; x < (sizeof(STATE_CHART) / sizeof(struct switch_cause_table)) - 1; x++) {
-		if (STATE_CHART[x].callstate == callstate) {
-			str = STATE_CHART[x].name;
+	for (x = 0; x < (sizeof(CALLSTATE_CHART) / sizeof(struct switch_cause_table)) - 1; x++) {
+		if (CALLSTATE_CHART[x].callstate == callstate) {
+			str = CALLSTATE_CHART[x].name;
 			break;
 		}
 	}
@@ -238,6 +238,7 @@ SWITCH_DECLARE(const char *) switch_channel_callstate2str(switch_channel_callsta
 	return str;
 }
 
+
 SWITCH_DECLARE(switch_call_cause_t) switch_channel_str2callstate(const char *str)
 {
 	uint8_t x;
@@ -246,9 +247,9 @@ SWITCH_DECLARE(switch_call_cause_t) switch_channel_str2callstate(const char *str
 	if (*str > 47 && *str < 58) {
 		callstate = atoi(str);
 	} else {
-		for (x = 0; x < (sizeof(STATE_CHART) / sizeof(struct switch_callstate_table)) - 1 && STATE_CHART[x].name; x++) {
-			if (!strcasecmp(STATE_CHART[x].name, str)) {
-				callstate = STATE_CHART[x].callstate;
+		for (x = 0; x < (sizeof(CALLSTATE_CHART) / sizeof(struct switch_callstate_table)) - 1 && CALLSTATE_CHART[x].name; x++) {
+			if (!strcasecmp(CALLSTATE_CHART[x].name, str)) {
+				callstate = CALLSTATE_CHART[x].callstate;
 				break;
 			}
 		}
@@ -1606,6 +1607,7 @@ static const char *state_names[] = {
 	"CS_HANGUP",
 	"CS_REPORTING",
 	"CS_DESTROY",
+	"CS_NONE",
 	NULL
 };
 
committer: Anthony Minessale
comments: 
add centralized registration db to core db and use it from mod_sofia

diff --git a/src/include/switch_core.h b/src/include/switch_core.h
index 69b0642..984b54f 100644
--- a/src/include/switch_core.h
+++ b/src/include/switch_core.h
@@ -2227,6 +2227,11 @@ SWITCH_DECLARE(const char *) switch_core_banner(void);
 SWITCH_DECLARE(switch_bool_t) switch_core_session_in_thread(switch_core_session_t *session);
 SWITCH_DECLARE(uint32_t) switch_default_ptime(const char *name, uint32_t number);
 
+SWITCH_DECLARE(switch_status_t) switch_core_add_registration(const char *user, const char *realm, const char *token, const char *url, uint32_t expires, 
+															 const char *network_ip, const char *network_port, const char *network_proto);
+SWITCH_DECLARE(switch_status_t) switch_core_del_registration(const char *user, const char *realm, const char *token);
+SWITCH_DECLARE(switch_status_t) switch_core_expire_registration(int force);
+
 SWITCH_END_EXTERN_C
 #endif
 /* For Emacs:
diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c
index f34042a..030cb8e 100644
--- a/src/mod/applications/mod_commands/mod_commands.c
+++ b/src/mod/applications/mod_commands/mod_commands.c
@@ -45,6 +45,149 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load);
 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_commands_shutdown);
 SWITCH_MODULE_DEFINITION(mod_commands, mod_commands_load, mod_commands_shutdown, NULL);
 
+
+struct cb_helper {
+	uint32_t row_process;
+	switch_stream_handle_t *stream;
+};
+
+static int url_callback(void *pArg, int argc, char **argv, char **columnNames)
+{
+	struct cb_helper *cb = (struct cb_helper *) pArg;
+
+	cb->row_process++;
+
+	if (!zstr(argv[0])) {
+		cb->stream->write_function(cb->stream, "%s,", argv[0]);
+	}
+
+	return 0;
+}
+
+static switch_status_t select_url(const char *user,
+					   const char *domain,
+					   const char *concat,
+					   const char *exclude_contact, 
+					   switch_stream_handle_t *stream)
+{
+	struct cb_helper cb;
+	char *sql, *errmsg = NULL;
+	switch_core_flag_t cflags = switch_core_flags();
+	switch_cache_db_handle_t *db = NULL;
+
+	if (!(cflags & SCF_USE_SQL)) {
+		stream->write_function(stream, "-ERR SQL DISABLED NO DATA AVAILABLE!\n");
+		return SWITCH_STATUS_SUCCESS;
+	}
+
+	if (switch_core_db_handle(&db) != SWITCH_STATUS_SUCCESS) {
+		stream->write_function(stream, "%s", "-ERR Databse Error!\n");
+		return SWITCH_STATUS_SUCCESS;
+	}
+
+	cb.row_process = 0;
+	cb.stream = stream;
+
+	if (exclude_contact) {
+		sql = switch_mprintf("select url, '%q' "
+							 "from registrations where user='%q' and realm='%q' "
+							 "and url not like '%%%s%%'", (concat != NULL) ? concat : "", user, domain, exclude_contact);
+	} else {
+		sql = switch_mprintf("select url, '%q' "
+							 "from registrations where user='%q' and realm='%q'",
+							 (concat != NULL) ? concat : "", user, domain);
+	}
+
+	switch_assert(sql);
+	switch_cache_db_execute_sql_callback(db, sql, url_callback, &cb, &errmsg);
+
+	if (errmsg) {
+		stream->write_function(stream, "-ERR SQL Error [%s]\n", errmsg);
+		free(errmsg);
+		errmsg = NULL;
+	}	
+
+	switch_safe_free(sql);
+
+	if (db) {
+		switch_cache_db_release_db_handle(&db);
+	}
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_STANDARD_API(reg_url_function)
+{
+	char *data;
+	char *user = NULL;
+	char *domain = NULL, *dup_domain = NULL;
+	char *concat = NULL;
+	const char *exclude_contact = NULL;
+	char *reply = "error/facility_not_subscribed";
+	switch_stream_handle_t mystream = { 0 };
+
+
+	if (!cmd) {
+		stream->write_function(stream, "%s", "");
+		return SWITCH_STATUS_SUCCESS;
+	}
+
+	if (session) {
+		switch_channel_t *channel = switch_core_session_get_channel(session);
+		exclude_contact = switch_channel_get_variable(channel, "sip_exclude_contact");
+	}
+
+	
+	data = strdup(cmd);
+	switch_assert(data);
+
+	user = data;
+	
+	if ((domain = strchr(user, '@'))) {
+		*domain++ = '\0';
+		if ((concat = strchr(domain, '/'))) {
+			*concat++ = '\0';
+		}
+	} else {
+		if ((concat = strchr(user, '/'))) {
+			*concat++ = '\0';
+		}
+	}
+
+	if (zstr(domain)) {
+		dup_domain = switch_core_get_variable_dup("domain");
+		domain = dup_domain;
+	}
+
+	if (!user) goto end;
+
+	
+	SWITCH_STANDARD_STREAM(mystream);
+	switch_assert(mystream.data);
+
+	select_url(user, domain, concat, exclude_contact, &mystream);
+	reply = mystream.data;
+
+
+ end:
+	
+	if (zstr(reply)) {
+		reply = "error/user_not_registered";
+	} else if (end_of(reply) == ',') {
+		end_of(reply) = '\0';
+	}
+
+	stream->write_function(stream, "%s", reply);
+	reply = NULL;
+
+	switch_safe_free(mystream.data);					
+
+	switch_safe_free(data);
+	switch_safe_free(dup_domain);
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
 SWITCH_STANDARD_API(banner_function)
 {
 	stream->write_function(stream, "%s", switch_core_banner());
@@ -3738,6 +3881,14 @@ SWITCH_STANDARD_API(show_function)
 				as = argv[3];
 			}
 		}
+	} else if (!strcasecmp(command, "registrations")) {
+		sprintf(sql, "select * from registrations where hostname='%s'", hostname);
+		if (argv[1] && !strcasecmp(argv[1], "count")) {
+			holder.justcount = 1;
+			if (argv[3] && !strcasecmp(argv[2], "as")) {
+				as = argv[3];
+			}
+		}
 	} else if (!strcasecmp(command, "channels") && argv[1] && !strcasecmp(argv[1], "like")) {
 		if (argv[2]) {
 			char *p;
@@ -4890,6 +5041,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
 	SWITCH_ADD_API(commands_api_interface, "tone_detect", "Start Tone Detection on a channel", tone_detect_session_function, TONE_DETECT_SYNTAX);
 	SWITCH_ADD_API(commands_api_interface, "unload", "Unload Module", unload_function, UNLOAD_SYNTAX);
 	SWITCH_ADD_API(commands_api_interface, "unsched_api", "Unschedule an api command", unsched_api_function, UNSCHED_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "reg_url", "", reg_url_function, "<user>@<realm>");
 	SWITCH_ADD_API(commands_api_interface, "url_decode", "url decode a string", url_decode_function, "<string>");
 	SWITCH_ADD_API(commands_api_interface, "url_encode", "url encode a string", url_encode_function, "<string>");
 	SWITCH_ADD_API(commands_api_interface, "user_data", "find user data", user_data_function, "<user>@<domain> [var|param|attr] <name>");
@@ -5000,6 +5152,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
 	switch_console_set_complete("add show management");
 	switch_console_set_complete("add show modules");
 	switch_console_set_complete("add show nat_map");
+	switch_console_set_complete("add show registrations");
 	switch_console_set_complete("add show say");
 	switch_console_set_complete("add show timer");
 	switch_console_set_complete("add shutdown");
diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c
index 07c285f..4853dff 100644
--- a/src/mod/endpoints/mod_sofia/mod_sofia.c
+++ b/src/mod/endpoints/mod_sofia/mod_sofia.c
@@ -3314,6 +3314,7 @@ static int contact_callback(void *pArg, int argc, char **argv, char **columnName
 
 	return 0;
 }
+
 static int sql2str_callback(void *pArg, int argc, char **argv, char **columnNames)
 {
 	struct cb_helper_sql2str *cbt = (struct cb_helper_sql2str *) pArg;
diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c
index 631cbdb..76b1dcc 100644
--- a/src/mod/endpoints/mod_sofia/sofia_reg.c
+++ b/src/mod/endpoints/mod_sofia/sofia_reg.c
@@ -877,6 +877,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
 	const char *agent = "unknown";
 	const char *pres_on_reg = NULL;
 	int send_pres = 0;
+	int is_tls = 0, is_tcp = 0;
 
 	delete_subs = sofia_test_pflag(profile, PFLAG_DEL_SUBS_ON_REG);
 
@@ -944,8 +945,6 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
 		char *path_encoded = NULL;
 		int path_encoded_len = 0;
 		const char *proto = "sip";
-		int is_tls = 0, is_tcp = 0;
-
 
 		if (switch_stristr("transport=tls", sip->sip_contact->m_url->url_params)) {
 			is_tls += 1;
@@ -1292,6 +1291,8 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
 		char guess_ip4[256];
 		const char *username = "unknown";
 		const char *realm = reg_host;
+		char *url = NULL;
+		char *contact = NULL;
 
 		if (auth_params) {
 			username = switch_event_get_header(auth_params, "sip_auth_username");
@@ -1327,7 +1328,15 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
 
 		switch_find_local_ip(guess_ip4, sizeof(guess_ip4), NULL, AF_INET);
 
+		contact = sofia_glue_get_url_from_contact(contact_str, 1);
+		url = switch_mprintf("sofia/%q/sip:%q", profile->name, sofia_glue_strip_proto(contact));
 		
+		switch_core_add_registration(to_user, reg_host, call_id, url, (long) switch_epoch_time_now(NULL) + (long) exptime + 60,
+									 network_ip, network_port_c, is_tls ? "tls" : is_tcp ? "tcp" : "udp");
+
+		switch_safe_free(url);
+		switch_safe_free(contact);
+
 		sql = switch_mprintf("insert into sip_registrations "
 							 "(call_id,sip_user,sip_host,presence_hosts,contact,status,rpid,expires,"
 							 "user_agent,server_user,server_host,profile_name,hostname,network_ip,network_port,sip_username,sip_realm,"
diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c
index 73890a1..ba92ebc 100644
--- a/src/switch_core_sqldb.c
+++ b/src/switch_core_sqldb.c
@@ -87,6 +87,7 @@ SWITCH_DECLARE(switch_status_t) _switch_core_db_handle(switch_cache_db_handle_t
 
 
 #define SQL_CACHE_TIMEOUT 120
+#define SQL_REG_TIMEOUT 15
 
 static void sql_close(time_t prune)
 {
@@ -906,7 +907,7 @@ SWITCH_DECLARE(switch_bool_t) switch_cache_db_test_reactive(switch_cache_db_hand
 
 static void *SWITCH_THREAD_FUNC switch_core_sql_db_thread(switch_thread_t *thread, void *obj)
 {
-	int sec = 0;
+	int sec = 0, reg_sec = 0;;
 
 	sql_manager.db_thread_running = 1;
 
@@ -916,6 +917,11 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_db_thread(switch_thread_t *threa
 			wake_thread(0);
 			sec = 0;
 		}
+
+		if (++reg_sec == SQL_REG_TIMEOUT) {
+			switch_core_expire_registration(0);
+			reg_sec = 0;
+		}
 		switch_yield(1000000);
 	}
 
@@ -1616,6 +1622,108 @@ static char create_nat_sql[] =
 	"   hostname VARCHAR(256)\n"
 	");\n";
 
+
+static char create_registrations_sql[] =
+	"CREATE TABLE registrations (\n"
+	"   user      VARCHAR(256),\n"
+	"   realm     VARCHAR(256),\n"
+	"   token     VARCHAR(256),\n"
+	"   url      TEXT,\n"
+	"   expires  INTEGER,\n"
+	"   network_ip VARCHAR(256),\n"
+	"   network_port VARCHAR(256),\n"
+	"   network_proto VARCHAR(256),\n"
+	"   hostname VARCHAR(256)\n"
+	");\n"
+	"create index regindex1 on registrations (user,real,hostname);\n";
+	
+
+SWITCH_DECLARE(switch_status_t) switch_core_add_registration(const char *user, const char *realm, const char *token, const char *url, uint32_t expires, 
+															 const char *network_ip, const char *network_port, const char *network_proto)
+{
+	switch_cache_db_handle_t *dbh;
+	char *sql;
+
+	if (switch_core_db_handle(&dbh) != SWITCH_STATUS_SUCCESS) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n");
+		return SWITCH_STATUS_FALSE;
+	}
+
+	sql = switch_mprintf("delete from registrations where hostname='%q' and (url='%q' or token='%q')", switch_core_get_hostname(), url, switch_str_nil(token));
+	switch_cache_db_execute_sql(dbh, sql, NULL);
+	free(sql);
+
+	sql = switch_mprintf("insert into registrations (user,realm,token,url,expires,network_ip,network_port,network_proto,hostname) "
+						 "values ('%q','%q','%q','%q',%ld,'%q','%q','%q','%q')",
+						 switch_str_nil(user),
+						 switch_str_nil(realm),
+						 switch_str_nil(token),
+						 switch_str_nil(url),
+						 expires,
+						 switch_str_nil(network_ip),
+						 switch_str_nil(network_port),
+						 switch_str_nil(network_proto),
+						 switch_core_get_hostname()
+						 );
+	
+	switch_cache_db_execute_sql(dbh, sql, NULL);
+	switch_cache_db_release_db_handle(&dbh);
+
+	free(sql);
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_DECLARE(switch_status_t) switch_core_del_registration(const char *user, const char *realm, const char *token)
+{
+
+	switch_cache_db_handle_t *dbh;
+	char *sql;
+
+	if (switch_core_db_handle(&dbh) != SWITCH_STATUS_SUCCESS) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n");
+		return SWITCH_STATUS_FALSE;
+	}
+
+	sql = switch_mprintf("delete from registrations where user='%q' and realm='%q' and hostname='%q'", user, realm, switch_core_get_hostname());
+
+	switch_cache_db_execute_sql(dbh, sql, NULL);
+	switch_cache_db_release_db_handle(&dbh);
+
+	free(sql);
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_DECLARE(switch_status_t) switch_core_expire_registration(int force)
+{
+	
+	switch_cache_db_handle_t *dbh;
+	char *sql;
+	switch_time_t now;
+
+	if (switch_core_db_handle(&dbh) != SWITCH_STATUS_SUCCESS) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n");
+		return SWITCH_STATUS_FALSE;
+	}
+
+	now = switch_epoch_time_now(NULL);
+
+	if (force) {
+		sql = switch_mprintf("delete from registrations where hostname='%q'", switch_core_get_hostname());
+	} else {
+		sql = switch_mprintf("delete from registrations where expires <= %ld and hostname='%q'", now, switch_core_get_hostname());
+	}
+
+	switch_cache_db_execute_sql(dbh, sql, NULL);
+	switch_cache_db_release_db_handle(&dbh);
+
+	free(sql);
+
+	return SWITCH_STATUS_SUCCESS;
+
+}
+
 switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_t manage)
 {
 	switch_threadattr_t *thd_attr;
@@ -1690,6 +1798,8 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_
 	switch_cache_db_test_reactive(dbh, "select hostname from complete", "DROP TABLE complete", create_complete_sql);
 	switch_cache_db_test_reactive(dbh, "select hostname from aliases", "DROP TABLE aliases", create_alias_sql);
 	switch_cache_db_test_reactive(dbh, "select hostname from nat", "DROP TABLE nat", create_nat_sql);
+	switch_cache_db_test_reactive(dbh, "delete from registrations where network_proto='tcp' or network_proto='tls'", 
+								  "DROP TABLE registrations", create_registrations_sql);
 
 
 	switch (dbh->type) {
@@ -1706,6 +1816,8 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_
 			}
 			switch_cache_db_test_reactive(dbh, "select ikey from interfaces", "DROP TABLE interfaces", create_interfaces_sql);
 			switch_cache_db_test_reactive(dbh, "select hostname from tasks", "DROP TABLE tasks", create_tasks_sql);
+			switch_cache_db_test_reactive(dbh, "delete from registrations where network_proto='tcp' or network_proto='tls'", 
+										  "DROP TABLE registrations", create_registrations_sql);
 
 			if (runtime.odbc_dbtype == DBTYPE_DEFAULT) {
 				switch_cache_db_execute_sql(dbh, "begin;delete from channels where hostname='';delete from channels where hostname='';commit;", &err);
committer: Anthony Minessale
comments: 
fix uuid_jitterbuffer edge case debugging a non-existant jb causing a seg

diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c
index 2a2ec63..07c285f 100644
--- a/src/mod/endpoints/mod_sofia/mod_sofia.c
+++ b/src/mod/endpoints/mod_sofia/mod_sofia.c
@@ -1366,7 +1366,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
 						if (s && !strcmp(s, "off")) {
 							s = NULL;
 						}
-						switch_rtp_debug_jitter_buffer(tech_pvt->rtp_session, s);
+						status = switch_rtp_debug_jitter_buffer(tech_pvt->rtp_session, s);
 						goto end;
 					}
 
diff --git a/src/switch_rtp.c b/src/switch_rtp.c
index 4df867a..200f4f0 100644
--- a/src/switch_rtp.c
+++ b/src/switch_rtp.c
@@ -1875,7 +1875,7 @@ static void jb_logger(const char *file, const char *func, int line, int level, c
 SWITCH_DECLARE(switch_status_t) switch_rtp_debug_jitter_buffer(switch_rtp_t *rtp_session, const char *name)
 {
 
-	if (!switch_rtp_ready(rtp_session)) {
+	if (!switch_rtp_ready(rtp_session) || !rtp_session->jb) {
 		return SWITCH_STATUS_FALSE;
 	}
 	
committer: Anthony Minessale
comments: 
fix file leaks in mod_commandline_tts

diff --git a/src/mod/asr_tts/mod_tts_commandline/mod_tts_commandline.c b/src/mod/asr_tts/mod_tts_commandline/mod_tts_commandline.c
index 6b261f1..0f3bc41 100644
--- a/src/mod/asr_tts/mod_tts_commandline/mod_tts_commandline.c
+++ b/src/mod/asr_tts/mod_tts_commandline/mod_tts_commandline.c
@@ -120,6 +120,11 @@ static switch_status_t tts_commandline_speech_close(switch_speech_handle_t *sh,
 	tts_commandline_t *info = (tts_commandline_t *) sh->private_info;
 	assert(info != NULL);
 
+	if (switch_test_flag(info->fh, SWITCH_FILE_OPEN)) {
+		switch_core_file_close(info->fh);
+		unlink(info->file);
+	}
+
 	return SWITCH_STATUS_SUCCESS;
 }
 
@@ -130,6 +135,11 @@ static switch_status_t tts_commandline_speech_feed_tts(switch_speech_handle_t *s
 
 	assert(info != NULL);
 
+	if (switch_test_flag(info->fh, SWITCH_FILE_OPEN)) {
+		switch_core_file_close(info->fh);
+		unlink(info->file);
+	}
+
 	message = switch_core_strdup(sh->memory_pool, globals.command);
 
 	tmp = switch_util_quote_shell_arg(text);
@@ -152,7 +162,7 @@ static switch_status_t tts_commandline_speech_feed_tts(switch_speech_handle_t *s
 	}
 
 	if (switch_core_file_open(info->fh, info->file, 0,	//number_of_channels,
-							  0,	//samples_per_second,
+							  info->rate,	//samples_per_second,
 							  SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open file: %s\n", info->file);
 		return SWITCH_STATUS_FALSE;
@@ -171,11 +181,14 @@ static switch_status_t tts_commandline_speech_read_tts(switch_speech_handle_t *s
 	assert(info != NULL);
 
 	if (switch_core_file_read(info->fh, data, &my_datalen) != SWITCH_STATUS_SUCCESS) {
-		*datalen = my_datalen * 2;
+		switch_core_file_close(info->fh);
+		unlink(info->file);
 		return SWITCH_STATUS_FALSE;
 	}
 	*datalen = my_datalen * 2;
 	if (datalen == 0) {
+		switch_core_file_close(info->fh);
+		unlink(info->file);
 		return SWITCH_STATUS_BREAK;
 	} else {
 		return SWITCH_STATUS_SUCCESS;
committer: Moises Silva
comments: 
Merge remote branch 'fsorig/master'
committer: Konrad Hammel
comments: 
freetdm: ss7 - bug fix for change in FreeTDM API

diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
index d38d25f..48579ad 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
@@ -366,7 +366,7 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
 		check_for_res_sus_flag(ftdmspan);
 
 		/* Poll for events, e.g HW DTMF */
-		switch (ftdm_span_poll_event(ftdmspan, 0)) {
+		switch (ftdm_span_poll_event(ftdmspan, 0, NULL)) {
 		/**********************************************************************/
 		case FTDM_SUCCESS:
 			while (ftdm_span_next_event(ftdmspan, &event) == FTDM_SUCCESS);
committer: Konrad Hammel
comments: 
Merge branch 'konrad.02-09-11'
committer: Konrad Hammel
comments: 
freetdm: ss7 - bug fix for configuration

diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
index 1b24e34..2f67d3f 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
@@ -1749,33 +1749,46 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
 	/* default the interface to paused state */
 	sngss7_set_flag(&sng_isup, SNGSS7_PAUSED);
 
-	/* trickle down the SPC to all sub entities */
-	lnkSet = &g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].lnkSets;
 
-	g_ftdm_sngss7_data.cfg.mtp3Link[lnkSet->lsId].spc = sng_isup.spc;
-	lnkSet = lnkSet->next;
 
+	/* trickle down the SPC to all sub entities */
+	lnkSet = &g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].lnkSets;
 	while (lnkSet->next != NULL) {
-		g_ftdm_sngss7_data.cfg.mtp3Link[lnkSet->lsId].spc = sng_isup.spc;
+	/**************************************************************************/
+		/* go through all the links and check if they belong to this linkset*/
+		i = 1;
+		while (g_ftdm_sngss7_data.cfg.mtp3Link[i].id != 0) {
+			/* check if this link is in the linkset */
+			if (g_ftdm_sngss7_data.cfg.mtp3Link[i].linkSetId == lnkSet->lsId) {
+				/* fill in the spc */
+				g_ftdm_sngss7_data.cfg.mtp3Link[i].spc = sng_isup.spc;
+			}
+	
+			i++;
+		}
+	
+		/* move to the next lnkSet */
 		lnkSet = lnkSet->next;
-	}
+	/**************************************************************************/
+	} /* while (lnkSet->next != NULL) */
 
 	/* pull values from the lower levels */
-	sng_isup.dpc = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].dpc;
-	sng_isup.switchType = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].switchType;
-	sng_isup.nwId = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].nwId;
-
 	sng_isap.switchType = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].switchType;
 
+	/* fill in the isap */
 	ftmod_ss7_fill_in_isap(&sng_isap);
 
-	sng_isup.isap = sng_isap.id;
+	/* pull values from the lower levels */
+	sng_isup.isap 		= sng_isap.id;
+	sng_isup.dpc 		= g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].dpc;
+	sng_isup.switchType	= g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].switchType;
+	sng_isup.nwId 		= g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].nwId;
 
+	/* fill in the isup interface */
 	ftmod_ss7_fill_in_isup_interface(&sng_isup);
 
 	/* setup the self mtp3 route */
 	i = sng_isup.mtpRouteId;
-
 	if(ftmod_ss7_fill_in_self_route(sng_isup.spc,
 									g_ftdm_sngss7_data.cfg.mtpRoute[i].linkType,
 									g_ftdm_sngss7_data.cfg.mtpRoute[i].switchType,
committer: Moises Silva
comments: 
freetdm: disallow completely core variables for freetdm outbound variables

diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c
index c0fdaa6..78874de 100755
--- a/libs/freetdm/mod_freetdm/mod_freetdm.c
+++ b/libs/freetdm/mod_freetdm/mod_freetdm.c
@@ -1055,28 +1055,18 @@ switch_io_routines_t freetdm_io_routines = {
 static const char* channel_get_variable(switch_core_session_t *session, switch_event_t *var_event, const char *variable_name)
 {
        const char *variable = NULL;
-
        if (var_event) {
                if ((variable = switch_event_get_header(var_event, variable_name))) {
                        return variable;
                }
        }
+
        if (session) {
                switch_channel_t *channel = switch_core_session_get_channel(session);
                if ((variable = switch_channel_get_variable(channel, variable_name))) {
                        return variable;
                }
        }
-
-
-	   // This is unsafe, I don't see anywhere in the whole code where this is called with NULL session anyway.
-	   // There is a new switch_core_get_variable_dup that will strdup it for you and then you must free it.
-	   // That messes up the abstraction completely so I am just commenting it out for you.....
-	   /*
-       if ((variable = switch_core_get_variable(variable_name))) {
-               return variable;
-       }
-	   */
        return NULL;
 }
 
committer: Anthony Minessale
comments: 
revert

diff --git a/src/mod/endpoints/mod_loopback/mod_loopback.c b/src/mod/endpoints/mod_loopback/mod_loopback.c
index b098ede..be9b499 100644
--- a/src/mod/endpoints/mod_loopback/mod_loopback.c
+++ b/src/mod/endpoints/mod_loopback/mod_loopback.c
@@ -637,13 +637,8 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
 		tech_pvt->other_tech_pvt &&
 		switch_test_flag(tech_pvt, TFLAG_BRIDGE) &&
 		switch_test_flag(tech_pvt->other_tech_pvt, TFLAG_BRIDGE) &&
-
 		switch_channel_test_flag(tech_pvt->channel, CF_BRIDGED) &&
 		switch_channel_test_flag(tech_pvt->other_channel, CF_BRIDGED) &&
-
-		!switch_channel_test_flag(tech_pvt->channel, CF_INNER_BRIDGE) &&
-		!switch_channel_test_flag(tech_pvt->other_channel, CF_INNER_BRIDGE) &&
-
 		switch_channel_test_flag(tech_pvt->channel, CF_ANSWERED) &&
 		switch_channel_test_flag(tech_pvt->other_channel, CF_ANSWERED) && !--tech_pvt->bowout_frame_count <= 0) {
 		const char *a_uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE);
committer: cypromis
comments: 
Merge remote branch 'origin/master'
committer: Moises Silva
comments: 
freetdm: use packet_len as the base length in tone generation

diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c
index 1e282d1..bd4e896 100644
--- a/libs/freetdm/src/ftdm_io.c
+++ b/libs/freetdm/src/ftdm_io.c
@@ -3588,7 +3588,7 @@ static FIO_READ_FUNCTION(ftdm_raw_read)
 }
 
 /* This function takes care of automatically generating DTMF or FSK tones when needed */
-static ftdm_status_t handle_tone_generation(ftdm_channel_t *ftdmchan, ftdm_size_t datalen)
+static ftdm_status_t handle_tone_generation(ftdm_channel_t *ftdmchan)
 {
 	/*
 	 * datalen: size in bytes of the chunk of data the user requested to read (this function 
@@ -3650,9 +3650,7 @@ static ftdm_status_t handle_tone_generation(ftdm_channel_t *ftdmchan, ftdm_size_
 	/* if we picked a buffer, time to read from it and write the linear data to the device */
 	if (buffer) {
 		uint8_t auxbuf[1024];
-		/* we initialize dlen to datalen, which is the size in bytes the 
-		 * user wants to read (typically chunks of 160 bytes, 20ms G.711) */
-		ftdm_size_t dlen = datalen;
+		ftdm_size_t dlen = ftdmchan->packet_len;
 		ftdm_size_t len, br, max = sizeof(auxbuf);
 		
 		/* if the codec is not linear, then data is really twice as much cuz
@@ -3662,10 +3660,10 @@ static ftdm_status_t handle_tone_generation(ftdm_channel_t *ftdmchan, ftdm_size_
 		}
 
 		/* we do not expect the user chunks to be bigger than auxbuf */
-		ftdm_assert(dlen <= sizeof(auxbuf), "Unexpected size for user data chunk size\n");
+		ftdm_assert((dlen <= sizeof(auxbuf)), "Unexpected size for user data chunk size\n");
 
 		/* dblen is the size in use for dtmf_buffer or fsk_buffer, and dlen is the size
-		 * of the read chunks of the user, we pick the smaller one */
+		 * of the io chunks to write, we pick the smaller one */
 		len = dblen > dlen ? dlen : dblen;
 
 		/* we can't read more than the size of our auxiliary buffer */
@@ -3770,7 +3768,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_read(ftdm_channel_t *ftdmchan, void *data
 			rdata[i] = ftdmchan->rxgain_table[rdata[i]];
 		}
 	}
-	handle_tone_generation(ftdmchan, *datalen);
+	handle_tone_generation(ftdmchan);
 
 	if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE) && ftdmchan->effective_codec != ftdmchan->native_codec) {
 		if (ftdmchan->native_codec == FTDM_CODEC_ULAW && ftdmchan->effective_codec == FTDM_CODEC_SLIN) {
committer: Konrad Hammel
comments: 
freetdm: ss7 - added hardware dtmf

diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
index 2f2e502..d38d25f 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
@@ -273,6 +273,7 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
 	ftdm_interrupt_t	*ftdm_sangoma_ss7_int[2];
 	ftdm_span_t 		*ftdmspan = (ftdm_span_t *) obj;
 	ftdm_channel_t 		*ftdmchan = NULL;
+	ftdm_event_t 		*event = NULL;
 	sngss7_event_data_t	*sngss7_event = NULL;
 	sngss7_span_data_t	*sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
 
@@ -363,6 +364,22 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
 
 		/* check each channel on the span to see if there is an un-procressed SUS/RES flag */
 		check_for_res_sus_flag(ftdmspan);
+
+		/* Poll for events, e.g HW DTMF */
+		switch (ftdm_span_poll_event(ftdmspan, 0)) {
+		/**********************************************************************/
+		case FTDM_SUCCESS:
+			while (ftdm_span_next_event(ftdmspan, &event) == FTDM_SUCCESS);
+			break;
+		/**********************************************************************/
+		case FTDM_TIMEOUT:
+			/* No events pending */
+			break;
+		/**********************************************************************/
+		default:
+			SS7_ERROR("%s:Failed to poll span event\n", ftdmspan->name);
+		/**********************************************************************/
+		} /* switch (ftdm_span_poll_event(span, 0)) */
 	} /* master while loop */
 
 	/* clear the IN_THREAD flag so that we know the thread is done */
committer: Anthony Minessale
comments: 
don't bow out on att_xfer bridge

diff --git a/src/mod/endpoints/mod_loopback/mod_loopback.c b/src/mod/endpoints/mod_loopback/mod_loopback.c
index be9b499..b098ede 100644
--- a/src/mod/endpoints/mod_loopback/mod_loopback.c
+++ b/src/mod/endpoints/mod_loopback/mod_loopback.c
@@ -637,8 +637,13 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
 		tech_pvt->other_tech_pvt &&
 		switch_test_flag(tech_pvt, TFLAG_BRIDGE) &&
 		switch_test_flag(tech_pvt->other_tech_pvt, TFLAG_BRIDGE) &&
+
 		switch_channel_test_flag(tech_pvt->channel, CF_BRIDGED) &&
 		switch_channel_test_flag(tech_pvt->other_channel, CF_BRIDGED) &&
+
+		!switch_channel_test_flag(tech_pvt->channel, CF_INNER_BRIDGE) &&
+		!switch_channel_test_flag(tech_pvt->other_channel, CF_INNER_BRIDGE) &&
+
 		switch_channel_test_flag(tech_pvt->channel, CF_ANSWERED) &&
 		switch_channel_test_flag(tech_pvt->other_channel, CF_ANSWERED) && !--tech_pvt->bowout_frame_count <= 0) {
 		const char *a_uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE);
committer: Moises Silva
comments: 
Merge remote branch 'fsorig/master'
committer: Konrad Hammel
comments: 
Merge branch 'master' of git.sangoma.com:/smg_freeswitch
committer: Konrad Hammel
comments: 
freetdm: ss7 - bug fix for SPC no longer being part sng_gen config

diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c
index 20bcc3a..df0414a 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c
@@ -352,22 +352,6 @@ int  ft_to_sngss7_cfg_all(void)
 		x++;
 	} /* while (g_ftdm_sngss7_data.cfg.mtpRoute[x].id != 0) */
 
-	if (g_ftdm_sngss7_data.cfg.mtpRoute[1].id != 0) {
-		if (!(g_ftdm_sngss7_data.cfg.mtpRoute[0].flags & SNGSS7_CONFIGURED)) {
-	
-			if (ftmod_ss7_mtp3_route_config(0)) {
-				SS7_CRITICAL("MTP3 ROUTE 0 configuration FAILED!\n");
-				return 1;
-			} else {
-				SS7_INFO("MTP3 ROUTE 0 configuration DONE!\n");
-			}
-	
-			/* set the SNGSS7_CONFIGURED flag */
-			g_ftdm_sngss7_data.cfg.mtpRoute[0].flags |= SNGSS7_CONFIGURED;
-		} /* if !SNGSS7_CONFIGURED */
-	}
-
-
 	x = 1;
 	while (g_ftdm_sngss7_data.cfg.isap[x].id != 0) {
 		/* check if this link has been configured already */
@@ -1161,10 +1145,10 @@ int ftmod_ss7_mtp3_route_config(int id)
 	cfg.t.cfg.s.snRout.swtchType		= k->linkType;				/* switch type */
 	cfg.t.cfg.s.snRout.upSwtch			= k->switchType;			/* user part switch type */
 	cfg.t.cfg.s.snRout.cmbLnkSetId		= k->cmbLinkSetId;			/* combined link set ID */
-	if (k->id == 0) {
-		cfg.t.cfg.s.snRout.dir		 		= LSN_RTE_UP;				/* direction */
+	if (k->dir == SNG_RTE_UP) {
+		cfg.t.cfg.s.snRout.dir		 	= LSN_RTE_UP;				/* direction */
 	} else {
-		cfg.t.cfg.s.snRout.dir		 		= LSN_RTE_DN;				/* direction */
+		cfg.t.cfg.s.snRout.dir		 	= LSN_RTE_DN;				/* direction */
 	}
 	cfg.t.cfg.s.snRout.rteToAdjSp		= 0;						/* flag indicating this route to adjacent SP */ 
 	cfg.t.cfg.s.snRout.ssf				= k->ssf;					/* sub service field */
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
index fe291fb..05c6351 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
@@ -83,6 +83,11 @@ typedef enum {
 } sng_ckt_type_t;
 
 typedef enum {
+	SNG_RTE_UP	= 0,
+	SNG_RTE_DN
+} sng_route_direction_t;
+
+typedef enum {
 	SNGSS7_LPA_FOR_COT		= (1 << 0),	/* send LPA when COT arrives */
 	SNGSS7_ACM_OBCI_BITA	= (1 << 10)	/* in-band indication */
 } sng_intf_options_t;
@@ -236,6 +241,7 @@ typedef struct sng_route {
 	uint32_t		ssf;
 	uint32_t		nwId;
 	uint32_t		isSTP;
+	uint32_t		dir;
 	uint32_t		t6;
 	uint32_t		t8;
 	uint32_t		t10;
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
index 46df990..1b24e34 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
@@ -2383,6 +2383,7 @@ static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route)
 	g_ftdm_sngss7_data.cfg.mtpRoute[i].nwId			= mtp3_route->nwId;
 	g_ftdm_sngss7_data.cfg.mtpRoute[i].lnkSets		= mtp3_route->lnkSets;
 	g_ftdm_sngss7_data.cfg.mtpRoute[i].ssf			= mtp3_route->ssf;
+	g_ftdm_sngss7_data.cfg.mtpRoute[i].dir			= SNG_RTE_DN;
 	if (mtp3_route->t6 != 0) {
 		g_ftdm_sngss7_data.cfg.mtpRoute[i].t6		= mtp3_route->t6;
 	} else {
@@ -2443,6 +2444,52 @@ static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route)
 }
 
 /******************************************************************************/
+static int ftmod_ss7_fill_in_self_route(int spc, int linkType, int switchType, int ssf)
+{
+	int i = 1;
+
+	while (g_ftdm_sngss7_data.cfg.mtpRoute[i].id != 0) {
+		if (g_ftdm_sngss7_data.cfg.mtpRoute[i].dpc == spc) {
+			/* we have a match so break out of this loop */
+			break;
+		}
+		/* move on to the next one */
+		i++;
+	}
+
+	if (g_ftdm_sngss7_data.cfg.mtpRoute[i].id == 0) {
+		g_ftdm_sngss7_data.cfg.mtpRoute[i].id = i;
+		SS7_DEBUG("found new mtp3 self route\n");
+	} else {
+		g_ftdm_sngss7_data.cfg.mtpRoute[i].id = i;
+		SS7_DEBUG("found existing mtp3 self route\n");
+	}
+
+	strncpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[i].name, "self-route", MAX_NAME_LEN-1);
+
+	g_ftdm_sngss7_data.cfg.mtpRoute[i].id			= i;
+	g_ftdm_sngss7_data.cfg.mtpRoute[i].dpc			= spc;
+	g_ftdm_sngss7_data.cfg.mtpRoute[i].linkType		= linkType;
+	g_ftdm_sngss7_data.cfg.mtpRoute[i].switchType	= switchType;
+	g_ftdm_sngss7_data.cfg.mtpRoute[i].cmbLinkSetId	= i;
+	g_ftdm_sngss7_data.cfg.mtpRoute[i].isSTP		= 0;
+	g_ftdm_sngss7_data.cfg.mtpRoute[i].ssf			= ssf;
+	g_ftdm_sngss7_data.cfg.mtpRoute[i].dir			= SNG_RTE_UP;
+	g_ftdm_sngss7_data.cfg.mtpRoute[i].t6			= 8;
+	g_ftdm_sngss7_data.cfg.mtpRoute[i].t8			= 12;
+	g_ftdm_sngss7_data.cfg.mtpRoute[i].t10			= 300;
+	g_ftdm_sngss7_data.cfg.mtpRoute[i].t11			= 300;
+	g_ftdm_sngss7_data.cfg.mtpRoute[i].t15			= 30;
+	g_ftdm_sngss7_data.cfg.mtpRoute[i].t16			= 20;
+	g_ftdm_sngss7_data.cfg.mtpRoute[i].t18			= 200;
+	g_ftdm_sngss7_data.cfg.mtpRoute[i].t19			= 690;
+	g_ftdm_sngss7_data.cfg.mtpRoute[i].t21			= 650; 
+	g_ftdm_sngss7_data.cfg.mtpRoute[i].t25			= 100;
+
+	return 0;
+}
+
+/******************************************************************************/
 static int ftmod_ss7_fill_in_nsap(sng_route_t *mtp3_route)
 {
 	int i;
@@ -2755,45 +2802,6 @@ static int ftmod_ss7_fill_in_isap(sng_isap_t *sng_isap)
 }
 
 /******************************************************************************/
-static int ftmod_ss7_fill_in_self_route(int spc, int linkType, int switchType, int ssf)
-{
-
-	if (g_ftdm_sngss7_data.cfg.mtpRoute[0].dpc == 0){
-		SS7_DEBUG("found new mtp3 self route\n");
-	} else if (g_ftdm_sngss7_data.cfg.mtpRoute[0].dpc == spc) {
-		SS7_DEBUG("found existing mtp3 self route\n");
-		return FTDM_SUCCESS;
-	} else {
-		SS7_ERROR("found new mtp3 self route but it does not match the route already configured (dpc=%d:spc=%d)\n",
-					g_ftdm_sngss7_data.cfg.mtpRoute[0].dpc,
-					spc);
-		return FTDM_FAIL;
-	}
-
-	strncpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[0].name, "self-route", MAX_NAME_LEN-1);
-
-	g_ftdm_sngss7_data.cfg.mtpRoute[0].id			= 0;
-	g_ftdm_sngss7_data.cfg.mtpRoute[0].dpc			= spc;
-	g_ftdm_sngss7_data.cfg.mtpRoute[0].linkType		= linkType;
-	g_ftdm_sngss7_data.cfg.mtpRoute[0].switchType	= switchType;
-	g_ftdm_sngss7_data.cfg.mtpRoute[0].cmbLinkSetId	= 0;
-	g_ftdm_sngss7_data.cfg.mtpRoute[0].isSTP		= 0;
-	g_ftdm_sngss7_data.cfg.mtpRoute[0].ssf			= ssf;
-	g_ftdm_sngss7_data.cfg.mtpRoute[0].t6			= 8;
-	g_ftdm_sngss7_data.cfg.mtpRoute[0].t8			= 12;
-	g_ftdm_sngss7_data.cfg.mtpRoute[0].t10			= 300;
-	g_ftdm_sngss7_data.cfg.mtpRoute[0].t11			= 300;
-	g_ftdm_sngss7_data.cfg.mtpRoute[0].t15			= 30;
-	g_ftdm_sngss7_data.cfg.mtpRoute[0].t16			= 20;
-	g_ftdm_sngss7_data.cfg.mtpRoute[0].t18			= 200;
-	g_ftdm_sngss7_data.cfg.mtpRoute[0].t19			= 690;
-	g_ftdm_sngss7_data.cfg.mtpRoute[0].t21			= 650; 
-	g_ftdm_sngss7_data.cfg.mtpRoute[0].t25			= 100;
-
-	return 0;
-}
-
-/******************************************************************************/
 static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan)
 {
 	sng_timeslot_t		timeslot;
committer: Moises Silva
comments: 
Merge branch 'master' of git.freeswitch.org:freeswitch
committer: Moises Silva
comments: 
freetdm: add code to troubleshoot crash on tone generation

diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c
index c9000de..1e282d1 100644
--- a/libs/freetdm/src/ftdm_io.c
+++ b/libs/freetdm/src/ftdm_io.c
@@ -2743,10 +2743,9 @@ static ftdm_status_t ftdmchan_activate_dtmf_buffer(ftdm_channel_t *ftdmchan)
 	if (!ftdmchan->dtmf_buffer) {
 		if (ftdm_buffer_create(&ftdmchan->dtmf_buffer, 1024, 3192, 0) != FTDM_SUCCESS) {
 			ftdm_log(FTDM_LOG_ERROR, "Failed to allocate DTMF Buffer!\n");
-			snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "buffer error");
 			return FTDM_FAIL;
 		} else {
-			ftdm_log(FTDM_LOG_DEBUG, "Created DTMF Buffer!\n");
+			ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Created DTMF buffer\n");
 		}
 	}
 
@@ -3588,8 +3587,17 @@ static FIO_READ_FUNCTION(ftdm_raw_read)
 	return status;
 }
 
-static ftdm_status_t handle_dtmf(ftdm_channel_t *ftdmchan, ftdm_size_t datalen)
+/* This function takes care of automatically generating DTMF or FSK tones when needed */
+static ftdm_status_t handle_tone_generation(ftdm_channel_t *ftdmchan, ftdm_size_t datalen)
 {
+	/*
+	 * datalen: size in bytes of the chunk of data the user requested to read (this function 
+	 *          is called from the ftdm_channel_read function)
+	 * dblen: size currently in use in any of the tone generation buffers (data available in the buffer)
+	 * gen_dtmf_buffer: buffer holding the raw ASCII digits that the user requested to generate
+	 * dtmf_buffer: raw linear tone data generated by teletone to be written to the devices
+	 * fsk_buffer: raw linear FSK modulated data for caller id
+	 */
 	ftdm_buffer_t *buffer = NULL;
 	ftdm_size_t dblen = 0;
 	int wrote = 0;
@@ -3604,7 +3612,7 @@ static ftdm_status_t handle_dtmf(ftdm_channel_t *ftdmchan, ftdm_size_t datalen)
 		}
 
 		if (ftdm_buffer_read(ftdmchan->gen_dtmf_buffer, digits, dblen) && !ftdm_strlen_zero_buf(digits)) {
-			ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generating DTMF [%s]\n", digits);	
+			ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generating DTMF [%s]\n", digits);
 		
 			cur = digits;
 
@@ -3618,7 +3626,7 @@ static ftdm_status_t handle_dtmf(ftdm_channel_t *ftdmchan, ftdm_size_t datalen)
 					ftdm_buffer_write(ftdmchan->dtmf_buffer, ftdmchan->tone_session.buffer, wrote * 2);
 					x++;
 				} else {
-					ftdm_log(FTDM_LOG_ERROR, "%d:%d Problem Adding DTMF SEQ [%s]\n", ftdmchan->span_id, ftdmchan->chan_id, digits);
+					ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Problem adding DTMF sequence [%s]\n", digits);
 					return FTDM_FAIL;
 				}
 			}
@@ -3631,6 +3639,7 @@ static ftdm_status_t handle_dtmf(ftdm_channel_t *ftdmchan, ftdm_size_t datalen)
 	
 
 	if (!ftdmchan->buffer_delay || --ftdmchan->buffer_delay == 0) {
+		/* time to pick a buffer, either the dtmf or fsk buffer */
 		if (ftdmchan->dtmf_buffer && (dblen = ftdm_buffer_inuse(ftdmchan->dtmf_buffer))) {
 			buffer = ftdmchan->dtmf_buffer;
 		} else if (ftdmchan->fsk_buffer && (dblen = ftdm_buffer_inuse(ftdmchan->fsk_buffer))) {
@@ -3638,22 +3647,41 @@ static ftdm_status_t handle_dtmf(ftdm_channel_t *ftdmchan, ftdm_size_t datalen)
 		}
 	}
 
+	/* if we picked a buffer, time to read from it and write the linear data to the device */
 	if (buffer) {
-		ftdm_size_t dlen = datalen;
 		uint8_t auxbuf[1024];
+		/* we initialize dlen to datalen, which is the size in bytes the 
+		 * user wants to read (typically chunks of 160 bytes, 20ms G.711) */
+		ftdm_size_t dlen = datalen;
 		ftdm_size_t len, br, max = sizeof(auxbuf);
 		
+		/* if the codec is not linear, then data is really twice as much cuz
+		   tone generation is done in linear (we assume anything different than linear is G.711) */
 		if (ftdmchan->native_codec != FTDM_CODEC_SLIN) {
 			dlen *= 2;
 		}
-		
+
+		/* we do not expect the user chunks to be bigger than auxbuf */
+		ftdm_assert(dlen <= sizeof(auxbuf), "Unexpected size for user data chunk size\n");
+
+		/* dblen is the size in use for dtmf_buffer or fsk_buffer, and dlen is the size
+		 * of the read chunks of the user, we pick the smaller one */
 		len = dblen > dlen ? dlen : dblen;
 
+		/* we can't read more than the size of our auxiliary buffer */
+		ftdm_assert((len <= sizeof(auxbuf)), "Unexpected size to read into auxbuf\n");
+
 		br = ftdm_buffer_read(buffer, auxbuf, len);		
+
+		/* the amount read can't possibly be bigger than what we requested */
+		ftdm_assert((br <= len), "Unexpected size read from tone generation buffer\n");
+
+		/* if we read less than the chunk size, we must fill in with silence the rest */
 		if (br < dlen) {
 			memset(auxbuf + br, 0, dlen - br);
 		}
 
+		/* finally we convert to the native format for the channel if necessary */
 		if (ftdmchan->native_codec != FTDM_CODEC_SLIN) {
 			if (ftdmchan->native_codec == FTDM_CODEC_ULAW) {
 				fio_slin2ulaw(auxbuf, max, &dlen);
@@ -3662,6 +3690,7 @@ static ftdm_status_t handle_dtmf(ftdm_channel_t *ftdmchan, ftdm_size_t datalen)
 			}
 		}
 		
+		/* write the tone to the channel */
 		return ftdm_raw_write(ftdmchan, auxbuf, &dlen);
 	} 
 
@@ -3741,7 +3770,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_read(ftdm_channel_t *ftdmchan, void *data
 			rdata[i] = ftdmchan->rxgain_table[rdata[i]];
 		}
 	}
-	handle_dtmf(ftdmchan, *datalen);
+	handle_tone_generation(ftdmchan, *datalen);
 
 	if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE) && ftdmchan->effective_codec != ftdmchan->native_codec) {
 		if (ftdmchan->native_codec == FTDM_CODEC_ULAW && ftdmchan->effective_codec == FTDM_CODEC_SLIN) {
@@ -3938,7 +3967,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *dat
 	if (!ftdmchan->buffer_delay && 
 		((ftdmchan->dtmf_buffer && ftdm_buffer_inuse(ftdmchan->dtmf_buffer)) ||
 		 (ftdmchan->fsk_buffer && ftdm_buffer_inuse(ftdmchan->fsk_buffer)))) {
-		/* read size writing DTMF ATM */
+		/* generating some kind of tone at the moment (see handle_tone_generation), 
+		 * we ignore user data ... */
 		goto done;
 	}
 
committer: Christopher Rienzo
comments: 
FS-3043 break during mod_unimrcp can hang session

diff --git a/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c b/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c
index 734ef21..d5bac5f 100644
--- a/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c
+++ b/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c
@@ -1363,7 +1363,7 @@ static switch_status_t speech_channel_stop(speech_channel_t *schannel)
 		}
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) %s stopped\n", schannel->name, speech_channel_type_to_string(schannel->type));
 	} else if (schannel->state == SPEECH_CHANNEL_DONE) {
-		speech_channel_set_state(schannel, SPEECH_CHANNEL_READY);
+		speech_channel_set_state_unlocked(schannel, SPEECH_CHANNEL_READY);
 	}
 
   done:
committer: Marc Olivier Chouinard
comments: 
mod_conference: Added to the Auto OutCall support to specify the conf profile to be used using variable : conference_auto_outcall_profile

diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c
index 961a140..0aee352 100644
--- a/src/mod/applications/mod_conference/mod_conference.c
+++ b/src/mod/applications/mod_conference/mod_conference.c
@@ -401,13 +401,14 @@ static switch_status_t conference_outcall(conference_obj_t *conference,
 										  char *bridgeto, uint32_t timeout, 
 										  char *flags, 
 										  char *cid_name, 
-										  char *cid_num, 
+										  char *cid_num,
+										  char *profile,
 										  switch_call_cause_t *cause,
 										  switch_call_cause_t *cancel_cause);
 static switch_status_t conference_outcall_bg(conference_obj_t *conference,
 											 char *conference_name,
 											 switch_core_session_t *session, char *bridgeto, uint32_t timeout, const char *flags, const char *cid_name,
-											 const char *cid_num, const char *call_uuid, switch_call_cause_t *cancel_cause);
+											 const char *cid_num, const char *call_uuid, const char *profile, switch_call_cause_t *cancel_cause);
 SWITCH_STANDARD_APP(conference_function);
 static void launch_conference_thread(conference_obj_t *conference);
 static void launch_conference_video_thread(conference_obj_t *conference);
@@ -2410,6 +2411,7 @@ static void conference_loop_output(conference_member_t *member)
 			const char *cid_num = switch_channel_get_variable(channel, "conference_auto_outcall_caller_id_number");
 			const char *toval = switch_channel_get_variable(channel, "conference_auto_outcall_timeout");
 			const char *flags = switch_channel_get_variable(channel, "conference_auto_outcall_flags");
+			const char *profile = switch_channel_get_variable(channel, "conference_auto_outcall_profile");
 			const char *ann = switch_channel_get_variable(channel, "conference_auto_outcall_announce");
 			const char *prefix = switch_channel_get_variable(channel, "conference_auto_outcall_prefix");
 			int to = 60;
@@ -2441,7 +2443,7 @@ static void conference_loop_output(conference_member_t *member)
 					char *dial_str = switch_mprintf("%s%s", switch_str_nil(prefix), argv[x]);
 					switch_assert(dial_str);
 					conference_outcall_bg(member->conference, NULL, NULL, dial_str, to, switch_str_nil(flags), cid_name, cid_num, NULL, 
-										  &member->conference->cancel_cause);
+										  profile, &member->conference->cancel_cause);
 					switch_safe_free(dial_str);
 				}
 				switch_safe_free(cpstr);
@@ -4264,9 +4266,9 @@ static switch_status_t conf_api_sub_dial(conference_obj_t *conference, switch_st
 	}
 
 	if (conference) {
-		conference_outcall(conference, NULL, NULL, argv[2], 60, NULL, argv[4], argv[3], &cause, NULL);
+		conference_outcall(conference, NULL, NULL, argv[2], 60, NULL, argv[4], argv[3], NULL, &cause, NULL);
 	} else {
-		conference_outcall(NULL, argv[0], NULL, argv[2], 60, NULL, argv[4], argv[3], &cause, NULL);
+		conference_outcall(NULL, argv[0], NULL, argv[2], 60, NULL, argv[4], argv[3], NULL, &cause, NULL);
 	}
 	stream->write_function(stream, "Call Requested: result: [%s]\n", switch_channel_cause2str(cause));
 
@@ -4289,9 +4291,9 @@ static switch_status_t conf_api_sub_bgdial(conference_obj_t *conference, switch_
 	switch_uuid_format(uuid_str, &uuid);
 
 	if (conference) {
-		conference_outcall_bg(conference, NULL, NULL, argv[2], 60, NULL, argv[4], argv[3], uuid_str, NULL);
+		conference_outcall_bg(conference, NULL, NULL, argv[2], 60, NULL, argv[4], argv[3], uuid_str, NULL, NULL);
 	} else {
-		conference_outcall_bg(NULL, argv[0], NULL, argv[2], 60, NULL, argv[4], argv[3], uuid_str, NULL);
+		conference_outcall_bg(NULL, argv[0], NULL, argv[2], 60, NULL, argv[4], argv[3], uuid_str, NULL, NULL);
 	}
 
 	stream->write_function(stream, "OK Job-UUID: %s\n", uuid_str);
@@ -4807,7 +4809,8 @@ static switch_status_t conference_outcall(conference_obj_t *conference,
 										  switch_core_session_t *session,
 										  char *bridgeto, uint32_t timeout, 
 										  char *flags, char *cid_name, 
-										  char *cid_num, 
+										  char *cid_num,
+										  char *profile,
 										  switch_call_cause_t *cause,
 										  switch_call_cause_t *cancel_cause)
 {
@@ -4817,6 +4820,7 @@ static switch_status_t conference_outcall(conference_obj_t *conference,
 	switch_channel_t *caller_channel = NULL;
 	char appdata[512];
 	int rdlock = 0;
+	switch_bool_t have_flags = SWITCH_FALSE;
 
 	*cause = SWITCH_CAUSE_NORMAL_CLEARING;
 
@@ -4902,13 +4906,16 @@ static switch_status_t conference_outcall(conference_obj_t *conference,
 			status = SWITCH_STATUS_MEMERR;
 			goto done;
 		}
-		/* add them to the conference */
+
 		if (flags && strcasecmp(flags, "none")) {
-			switch_snprintf(appdata, sizeof(appdata), "%s+flags{%s}", conference_name, flags);
-			switch_caller_extension_add_application(peer_session, extension, (char *) global_app_name, appdata);
-		} else {
-			switch_caller_extension_add_application(peer_session, extension, (char *) global_app_name, conference_name);
+			have_flags = SWITCH_TRUE;
 		}
+		/* add them to the conference */
+
+		switch_snprintf(appdata, sizeof(appdata), "%s%s%s%s%s%s", conference_name,
+				profile?"@":"", profile?profile:"",
+				have_flags?"+flags{":"", have_flags?flags:"", have_flags?"}":"");
+		switch_caller_extension_add_application(peer_session, extension, (char *) global_app_name, appdata);
 
 		switch_channel_set_caller_extension(peer_channel, extension);
 		switch_channel_set_state(peer_channel, CS_EXECUTE);
@@ -4940,6 +4947,7 @@ struct bg_call {
 	char *cid_num;
 	char *conference_name;
 	char *uuid;
+	char *profile;
 	switch_call_cause_t *cancel_cause;
 	switch_memory_pool_t *pool;
 };
@@ -4953,7 +4961,7 @@ static void *SWITCH_THREAD_FUNC conference_outcall_run(switch_thread_t *thread,
 		switch_event_t *event;
 
 		conference_outcall(call->conference, call->conference_name,
-						   call->session, call->bridgeto, call->timeout, call->flags, call->cid_name, call->cid_num, &cause, call->cancel_cause);
+						   call->session, call->bridgeto, call->timeout, call->flags, call->cid_name, call->cid_num, call->profile, &cause, call->cancel_cause);
 
 		if (call->conference && test_eflag(call->conference, EFLAG_BGDIAL_RESULT) &&
 			switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
@@ -4969,6 +4977,7 @@ static void *SWITCH_THREAD_FUNC conference_outcall_run(switch_thread_t *thread,
 		switch_safe_free(call->cid_num);
 		switch_safe_free(call->conference_name);
 		switch_safe_free(call->uuid);
+		switch_safe_free(call->profile);
 		if (call->pool) {
 			switch_core_destroy_memory_pool(&call->pool);
 		}
@@ -4981,7 +4990,7 @@ static void *SWITCH_THREAD_FUNC conference_outcall_run(switch_thread_t *thread,
 static switch_status_t conference_outcall_bg(conference_obj_t *conference,
 											 char *conference_name,
 											 switch_core_session_t *session, char *bridgeto, uint32_t timeout, const char *flags, const char *cid_name,
-											 const char *cid_num, const char *call_uuid, switch_call_cause_t *cancel_cause)
+											 const char *cid_num, const char *call_uuid, const char *profile, switch_call_cause_t *cancel_cause)
 {
 	struct bg_call *call = NULL;
 	switch_thread_t *thread;
@@ -5025,6 +5034,10 @@ static switch_status_t conference_outcall_bg(conference_obj_t *conference,
 		call->uuid = strdup(call_uuid);
 	}
 
+        if (profile) {
+                call->profile = strdup(profile);
+        }
+
 	switch_threadattr_create(&thd_attr, pool);
 	switch_threadattr_detach_set(thd_attr, 1);
 	switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
@@ -5750,7 +5763,7 @@ SWITCH_STANDARD_APP(conference_function)
 	/* if we're using "bridge:" make an outbound call and bridge it in */
 	if (!zstr(bridgeto) && strcasecmp(bridgeto, "none")) {
 		switch_call_cause_t cause;
-		if (conference_outcall(conference, NULL, session, bridgeto, 60, NULL, NULL, NULL, &cause, NULL) != SWITCH_STATUS_SUCCESS) {
+		if (conference_outcall(conference, NULL, session, bridgeto, 60, NULL, NULL, NULL, NULL, &cause, NULL) != SWITCH_STATUS_SUCCESS) {
 			goto done;
 		}
 	} else {
committer: Anthony Minessale
comments: 
take out default it seems to suck on 32 bit

diff --git a/conf/autoload_configs/switch.conf.xml b/conf/autoload_configs/switch.conf.xml
index 32cb76f..44893b9 100644
--- a/conf/autoload_configs/switch.conf.xml
+++ b/conf/autoload_configs/switch.conf.xml
@@ -25,7 +25,7 @@
     <param name="colorize-console" value="true"/>
 
     <!-- minimum idle CPU before refusing calls -->
-    <param name="min-idle-cpu" value="25"/>
+    <!--<param name="min-idle-cpu" value="25"/>-->
 
     <!--
 	Max number of sessions to allow at any given time.
committer: Moises Silva
comments: 
Merge remote branch 'smgfs/master'
committer: Anthony Minessale
comments: 
minor regression from 4ae8282e6c6df0e296113e9b4b4a1383e1af8ad7 (sofia_contact with no args from cli caused seg)

diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c
index c683203..2a2ec63 100644
--- a/src/mod/endpoints/mod_sofia/mod_sofia.c
+++ b/src/mod/endpoints/mod_sofia/mod_sofia.c
@@ -3458,7 +3458,7 @@ SWITCH_STANDARD_API(sofia_contact_function)
 {
 	char *data;
 	char *user = NULL;
-	char *domain = NULL;
+	char *domain = NULL, *dup_domain = NULL;
 	char *concat = NULL;
 	char *profile_name = NULL;
 	char *p;
@@ -3501,7 +3501,8 @@ SWITCH_STANDARD_API(sofia_contact_function)
 	}
 
 	if (zstr(domain)) {
-		domain = switch_core_get_variable_pdup("domain", switch_core_session_get_pool(session));
+		dup_domain = switch_core_get_variable_dup("domain");
+		domain = dup_domain;
 	}
 
 	if (!user) goto end;
@@ -3567,6 +3568,7 @@ SWITCH_STANDARD_API(sofia_contact_function)
 	switch_safe_free(mystream.data);					
 
 	switch_safe_free(data);
+	switch_safe_free(dup_domain);
 
 	return SWITCH_STATUS_SUCCESS;
 }
committer: Anthony Minessale
comments: 
reset signal_bond variable back to its original value on failed dial in att_xfer

diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c
index f7bf86b..9a1258a 100755
--- a/src/mod/applications/mod_dptools/mod_dptools.c
+++ b/src/mod/applications/mod_dptools/mod_dptools.c
@@ -1864,6 +1864,7 @@ SWITCH_STANDARD_APP(att_xfer_function)
 
 	if (switch_ivr_originate(session, &peer_session, &cause, data, 0, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL)
 		!= SWITCH_STATUS_SUCCESS || !peer_session) {
+		switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, bond);
 		goto end;
 	}
 
@@ -1878,6 +1879,7 @@ SWITCH_STANDARD_APP(att_xfer_function)
 
 	if (zstr(bond) && switch_channel_down(peer_channel)) {
 		switch_core_session_rwunlock(peer_session);
+		switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, bond);
 		goto end;
 	}
 
committer: David Yat Sin
comments: 
Fixes to support QSIG over T1

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 bd5b13b..9fe2819 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
@@ -84,6 +84,8 @@ static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span
 				signal_data->switchtype = SNGISDN_SWITCH_4ESS;
 			} else if (!strcasecmp(switch_name, "dms100")) {
 				signal_data->switchtype = SNGISDN_SWITCH_DMS100;
+			} else if (!strcasecmp(switch_name, "qsig")) {
+				signal_data->switchtype = SNGISDN_SWITCH_QSIG;
 			} else {
 				ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported switchtype %s for trunktype:%s\n", span->name, switch_name, ftdm_trunk_type2str(span->trunk_type));
 				return FTDM_FAIL;
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c
index a52a624..1bd2753 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c
@@ -667,25 +667,33 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
 	cfg.t.cfg.s.inDLSAP.maxBSrvCnt = 2;
 	cfg.t.cfg.s.inDLSAP.maxDSrvCnt = 2;
 #endif /* ISDN_SRV */
-	
-	if (signal_data->signalling == SNGISDN_SIGNALING_NET) {
-		cfg.t.cfg.s.inDLSAP.ackOpt = TRUE;
-		cfg.t.cfg.s.inDLSAP.intType = NETWORK;
-		cfg.t.cfg.s.inDLSAP.clrGlr = FALSE;			/* in case of glare, do not clear local call */
-		cfg.t.cfg.s.inDLSAP.statEnqOpt = TRUE;
 
-		if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN ||
-			signal_data->switchtype == SNGISDN_SWITCH_INSNET) {
-			cfg.t.cfg.s.inDLSAP.rstOpt = FALSE;
-		} else {
-			cfg.t.cfg.s.inDLSAP.rstOpt = TRUE;
-		}
-	} else {
-		cfg.t.cfg.s.inDLSAP.ackOpt = FALSE;
-		cfg.t.cfg.s.inDLSAP.intType = USER;
+	if (signal_data->switchtype == SNGISDN_SWITCH_QSIG) {
+		cfg.t.cfg.s.inDLSAP.ackOpt = TRUE;
+		cfg.t.cfg.s.inDLSAP.intType = SYM_USER;
 		cfg.t.cfg.s.inDLSAP.clrGlr = TRUE;			/* in case of glare, clear local call */
 		cfg.t.cfg.s.inDLSAP.statEnqOpt = FALSE;
 		cfg.t.cfg.s.inDLSAP.rstOpt = FALSE;
+	} else {
+		if (signal_data->signalling == SNGISDN_SIGNALING_NET) {
+			cfg.t.cfg.s.inDLSAP.ackOpt = TRUE;
+			cfg.t.cfg.s.inDLSAP.intType = NETWORK;
+			cfg.t.cfg.s.inDLSAP.clrGlr = FALSE;			/* in case of glare, do not clear local call */
+			cfg.t.cfg.s.inDLSAP.statEnqOpt = TRUE;
+
+			if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN ||
+				signal_data->switchtype == SNGISDN_SWITCH_INSNET) {
+				cfg.t.cfg.s.inDLSAP.rstOpt = FALSE;
+			} else {
+				cfg.t.cfg.s.inDLSAP.rstOpt = TRUE;
+			}
+		} else {
+			cfg.t.cfg.s.inDLSAP.ackOpt = FALSE;
+			cfg.t.cfg.s.inDLSAP.intType = USER;
+			cfg.t.cfg.s.inDLSAP.clrGlr = TRUE;			/* in case of glare, clear local call */
+			cfg.t.cfg.s.inDLSAP.statEnqOpt = FALSE;
+			cfg.t.cfg.s.inDLSAP.rstOpt = FALSE;
+		}
 	}
 
 	/* Override the restart options if user selected that option */
committer: David Yat Sin
comments: 
Fixes to support QSIG over T1

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 bd5b13b..9fe2819 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
@@ -84,6 +84,8 @@ static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span
 				signal_data->switchtype = SNGISDN_SWITCH_4ESS;
 			} else if (!strcasecmp(switch_name, "dms100")) {
 				signal_data->switchtype = SNGISDN_SWITCH_DMS100;
+			} else if (!strcasecmp(switch_name, "qsig")) {
+				signal_data->switchtype = SNGISDN_SWITCH_QSIG;
 			} else {
 				ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported switchtype %s for trunktype:%s\n", span->name, switch_name, ftdm_trunk_type2str(span->trunk_type));
 				return FTDM_FAIL;
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c
index a52a624..1bd2753 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c
@@ -667,25 +667,33 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
 	cfg.t.cfg.s.inDLSAP.maxBSrvCnt = 2;
 	cfg.t.cfg.s.inDLSAP.maxDSrvCnt = 2;
 #endif /* ISDN_SRV */
-	
-	if (signal_data->signalling == SNGISDN_SIGNALING_NET) {
-		cfg.t.cfg.s.inDLSAP.ackOpt = TRUE;
-		cfg.t.cfg.s.inDLSAP.intType = NETWORK;
-		cfg.t.cfg.s.inDLSAP.clrGlr = FALSE;			/* in case of glare, do not clear local call */
-		cfg.t.cfg.s.inDLSAP.statEnqOpt = TRUE;
 
-		if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN ||
-			signal_data->switchtype == SNGISDN_SWITCH_INSNET) {
-			cfg.t.cfg.s.inDLSAP.rstOpt = FALSE;
-		} else {
-			cfg.t.cfg.s.inDLSAP.rstOpt = TRUE;
-		}
-	} else {
-		cfg.t.cfg.s.inDLSAP.ackOpt = FALSE;
-		cfg.t.cfg.s.inDLSAP.intType = USER;
+	if (signal_data->switchtype == SNGISDN_SWITCH_QSIG) {
+		cfg.t.cfg.s.inDLSAP.ackOpt = TRUE;
+		cfg.t.cfg.s.inDLSAP.intType = SYM_USER;
 		cfg.t.cfg.s.inDLSAP.clrGlr = TRUE;			/* in case of glare, clear local call */
 		cfg.t.cfg.s.inDLSAP.statEnqOpt = FALSE;
 		cfg.t.cfg.s.inDLSAP.rstOpt = FALSE;
+	} else {
+		if (signal_data->signalling == SNGISDN_SIGNALING_NET) {
+			cfg.t.cfg.s.inDLSAP.ackOpt = TRUE;
+			cfg.t.cfg.s.inDLSAP.intType = NETWORK;
+			cfg.t.cfg.s.inDLSAP.clrGlr = FALSE;			/* in case of glare, do not clear local call */
+			cfg.t.cfg.s.inDLSAP.statEnqOpt = TRUE;
+
+			if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN ||
+				signal_data->switchtype == SNGISDN_SWITCH_INSNET) {
+				cfg.t.cfg.s.inDLSAP.rstOpt = FALSE;
+			} else {
+				cfg.t.cfg.s.inDLSAP.rstOpt = TRUE;
+			}
+		} else {
+			cfg.t.cfg.s.inDLSAP.ackOpt = FALSE;
+			cfg.t.cfg.s.inDLSAP.intType = USER;
+			cfg.t.cfg.s.inDLSAP.clrGlr = TRUE;			/* in case of glare, clear local call */
+			cfg.t.cfg.s.inDLSAP.statEnqOpt = FALSE;
+			cfg.t.cfg.s.inDLSAP.rstOpt = FALSE;
+		}
 	}
 
 	/* Override the restart options if user selected that option */
committer: Anthony Minessale
comments: 
FS-3040/FS-1742: use 1 sql query for message count in a way that is portable and doesn't segfault

diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c
index 80b011e..894e49a 100644
--- a/src/mod/applications/mod_voicemail/mod_voicemail.c
+++ b/src/mod/applications/mod_voicemail/mod_voicemail.c
@@ -1011,6 +1011,11 @@ typedef struct msg_cnt_callback msg_cnt_callback_t;
 static int message_count_callback(void *pArg, int argc, char **argv, char **columnNames)
 {
 	msg_cnt_callback_t *cbt = (msg_cnt_callback_t *) pArg;
+
+	if (argc < 3 || zstr(argv[0]) || zstr(argv[1]) || zstr(argv[2])) {
+		return -1;
+	}
+
 	if (atoi(argv[0]) == 1) {	/* UnRead */
 		if (!strcasecmp(argv[1], "A_URGENT")) {	/* Urgent */
 			cbt->total_new_urgent_messages = atoi(argv[2]);
@@ -1263,7 +1268,7 @@ static void message_count(vm_profile_t *profile, const char *id_in, const char *
 {
 	char msg_count[80] = "";
 	msg_cnt_callback_t cbt = { 0 };
-	char sql[256];
+	char *sql;
 	char *myid = NULL;
 
 
@@ -1277,11 +1282,20 @@ static void message_count(vm_profile_t *profile, const char *id_in, const char *
 
 	myid = resolve_id(id_in, domain_name, "message-count");
 
-	switch_snprintf(sql, sizeof(sql),
-					"select read_epoch=0, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' group by read_epoch=0,read_flags;",
-					myid, domain_name, myfolder);
+	sql = switch_mprintf(
+						 "select 1, read_flags, count(read_epoch) from voicemail_msgs where "
+						 "username='%q' and domain='%q' and in_folder='%q' and read_epoch=0 "
+						 "group by read_flags "
+						 "union "
+						 "select 0, read_flags, count(read_epoch) from voicemail_msgs where "
+						 "username='%q' and domain='%q' and in_folder='%q' and read_epoch<>0 "
+						 "group by read_flags;",
+
+						 myid, domain_name, myfolder,
+						 myid, domain_name, myfolder);
 
 	vm_execute_sql_callback(profile, profile->mutex, sql, message_count_callback, &cbt);
+	free(sql);
 
 	*total_new_messages = cbt.total_new_messages + cbt.total_new_urgent_messages;
 	*total_new_urgent_messages = cbt.total_new_urgent_messages;
committer: Anthony Minessale
comments: 
3 regresions from this now, rolling it back

diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c
index bea8214..80b011e 100644
--- a/src/mod/applications/mod_voicemail/mod_voicemail.c
+++ b/src/mod/applications/mod_voicemail/mod_voicemail.c
@@ -1277,13 +1277,9 @@ static void message_count(vm_profile_t *profile, const char *id_in, const char *
 
 	myid = resolve_id(id_in, domain_name, "message-count");
 
-	switch_snprintf(sql, sizeof(sql), "select 1, read_flags, count(read_epoch) from voicemail_msgs where "
-					"username='%s' and domain='%s' and in_folder='%s' "
-					"and read_epoch=0 group by read_flags union select 0, read_flags, count(read_epoch) from voicemail_msgs where username='%s' "
-					"and domain='%s' and in_folder='%s' and read_epoch<>0 group by read_flags;", 
-					myid, domain_name, myfolder, myid, domain_name, myfolder);
-					
-				   
+	switch_snprintf(sql, sizeof(sql),
+					"select read_epoch=0, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' group by read_epoch=0,read_flags;",
+					myid, domain_name, myfolder);
 
 	vm_execute_sql_callback(profile, profile->mutex, sql, message_count_callback, &cbt);
 
committer: David Yat Sin
comments: 
Merge branch 'master' of git.sangoma.com:smg_freeswitch
committer: David Yat Sin
comments: 
freetdm: allow reception of FACILITY msg in any channel state when transparent facility is enabled

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 578677a..bcc7d93 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
@@ -801,6 +801,23 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event)
 
 	ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing FACILITY IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
 
+	if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) {
+		/* If Facility decoding is disabled, we do not care about current call state, just pass event up to user */
+		ftdm_sigmsg_t sigev;
+		if (facEvnt->facElmt.facStr.pres) {
+			get_facility_ie_str(ftdmchan, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len-2);
+		}
+		memset(&sigev, 0, sizeof(sigev));
+		sigev.chan_id = ftdmchan->chan_id;
+		sigev.span_id = ftdmchan->span_id;
+		sigev.channel = ftdmchan;
+		
+		sigev.event_id = FTDM_SIGEVENT_FACILITY;
+		ftdm_span_send_signal(ftdmchan->span, &sigev);
+		ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+		return;
+	}
+
 	switch (ftdmchan->state) {
 		case FTDM_CHANNEL_STATE_GET_CALLERID:
 			/* Update the caller ID Name */
committer: Moises Silva
comments: 
Merge remote branch 'fsorig/master'
committer: Moises Silva
comments: 
freetdm: do not expect result_cb to be set to make the interface cleaner

diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c
index 0f92f59..c9000de 100644
--- a/libs/freetdm/src/ftdm_io.c
+++ b/libs/freetdm/src/ftdm_io.c
@@ -37,9 +37,6 @@
  *
  */
 
-#ifdef MOYTEST
-crap
-#endif
 #define _GNU_SOURCE
 #include "private/ftdm_core.h"
 #include <stdarg.h>
@@ -2509,10 +2506,12 @@ FT_DECLARE(ftdm_status_t) _ftdm_call_place(const char *file, const char *func, i
 	}
 
 	/* we have a locked channel and are not afraid of using it! */
-	status = hunting->result_cb(fchan, caller_data);
-	if (status != FTDM_SUCCESS) {
-		status = FTDM_ECANCELED;
-		goto done;
+	if (hunting->result_cb) {
+		status = hunting->result_cb(fchan, caller_data);
+		if (status != FTDM_SUCCESS) {
+			status = FTDM_ECANCELED;
+			goto done;
+		}
 	}
 
 	ftdm_channel_set_caller_data(fchan, caller_data);
committer: Daniel Swarbrick
comments: 
major factor of pgsql field handling

diff --git a/conf/autoload_configs/cdr_pg_csv.conf.xml b/conf/autoload_configs/cdr_pg_csv.conf.xml
index 427bf2d..4fec817 100644
--- a/conf/autoload_configs/cdr_pg_csv.conf.xml
+++ b/conf/autoload_configs/cdr_pg_csv.conf.xml
@@ -16,10 +16,25 @@
 
     <!-- This is like the info app but after the call is hung up -->
     <!--<param name="debug" value="true"/>-->
-
-    <param name="default-template" value="example"/>
   </settings>
-  <templates>
-    <template name="example">"${local_ip_v4}","${caller_id_name}","${caller_id_number}","${destination_number}","${context}","${start_stamp}","${answer_stamp}","${end_stamp}","${duration}","${billsec}","${hangup_cause}","${uuid}","${bleg_uuid}","${accountcode}","${read_codec}","${write_codec}","${sip_hangup_disposition}","${ani}"</template>
-  </templates>
+  <schema>
+    <field var="local_ip_v4"/>
+    <field var="caller_id_name"/>
+    <field var="caller_id_number"/>
+    <field var="destination_number"/>
+    <field var="context"/>
+    <field var="start_stamp"/>
+    <field var="answer_stamp"/>
+    <field var="end_stamp"/>
+    <field var="duration" quote="false"/>
+    <field var="billsec" quote="false"/>
+    <field var="hangup_cause"/>
+    <field var="uuid"/>
+    <field var="bleg_uuid"/>
+    <field var="accountcode"/>
+    <field var="read_codec"/>
+    <field var="write_codec"/>
+    <!-- <field var="sip_hangup_disposition"/> -->
+    <!-- <field var="ani"/> -->
+  </schema>
 </configuration>
diff --git a/src/mod/event_handlers/mod_cdr_pg_csv/mod_cdr_pg_csv.c b/src/mod/event_handlers/mod_cdr_pg_csv/mod_cdr_pg_csv.c
index 1ec56bd..51194f4 100644
--- a/src/mod/event_handlers/mod_cdr_pg_csv/mod_cdr_pg_csv.c
+++ b/src/mod/event_handlers/mod_cdr_pg_csv/mod_cdr_pg_csv.c
@@ -59,28 +59,34 @@ typedef struct {
 	switch_mutex_t *mutex;
 } cdr_fd_t;
 
-const char *default_template =
-	"\"${local_ip_v4}\",\"${caller_id_name}\",\"${caller_id_number}\",\"${destination_number}\",\"${context}\",\"${start_stamp}\","
-	"\"${answer_stamp}\",\"${end_stamp}\",\"${duration}\",\"${billsec}\",\"${hangup_cause}\",\"${uuid}\",\"${bleg_uuid}\",\"${accountcode}\","
-	"\"${read_codec}\",\"${write_codec}\"";
+typedef struct {
+	char *col_name;
+	char *var_name;
+	switch_bool_t quote;
+	switch_bool_t not_null;
+} cdr_field_t;
+
+typedef struct {
+	char *columns;
+	cdr_field_t fields[1];
+} db_schema_t;
 
 static struct {
 	switch_memory_pool_t *pool;
 	switch_hash_t *fd_hash;
-	switch_hash_t *template_hash;
 	int shutdown;
 	char *db_info;
 	char *db_table;
+	db_schema_t *db_schema;
 	PGconn *db_connection;
+	switch_mutex_t *db_mutex;
 	int db_online;
 	cdr_leg_t legs;
 	char *spool_dir;
 	spool_format_t spool_format;
 	int rotate;
 	int debug;
-	char *default_template;
-	switch_mutex_t *db_mutex;
-} globals = { 0 };
+} globals;
 
 static switch_xml_config_enum_item_t config_opt_cdr_leg_enum[] = {
         {"a", CDR_LEG_A},
@@ -110,7 +116,6 @@ static switch_xml_config_item_t config_settings[] = {
 	/* key, type, flags, ptr, default_value, data, syntax, helptext */
 	SWITCH_CONFIG_ITEM_STRING_STRDUP("db-info", CONFIG_RELOADABLE, &globals.db_info, "dbname=cdr", NULL, NULL),
 	SWITCH_CONFIG_ITEM_STRING_STRDUP("db-table", CONFIG_RELOADABLE, &globals.db_table, "cdr", NULL, NULL),
-	SWITCH_CONFIG_ITEM_STRING_STRDUP("default-template", CONFIG_RELOADABLE, &globals.default_template, "default", NULL, NULL),
 	SWITCH_CONFIG_ITEM("legs", SWITCH_CONFIG_ENUM, CONFIG_RELOADABLE, &globals.legs, (void *) CDR_LEG_A, &config_opt_cdr_leg_enum, "a|b|ab", NULL),
 	SWITCH_CONFIG_ITEM("spool-format", SWITCH_CONFIG_ENUM, CONFIG_RELOADABLE, &globals.spool_format, (void *) SPOOL_FORMAT_CSV, &config_opt_spool_format_enum, "csv|sql", "Disk spool format to use if SQL insert fails."),
 	SWITCH_CONFIG_ITEM("rotate-on-hup", SWITCH_CONFIG_BOOL, CONFIG_RELOADABLE, &globals.rotate, SWITCH_FALSE, NULL, NULL, NULL),
@@ -239,135 +244,13 @@ static void spool_cdr(const char *path, const char *log_line)
 	switch_safe_free(log_line_lf);
 }
 
-static switch_status_t insert_cdr(const char * const template, const char * const cdr)
+static switch_status_t insert_cdr(const char *values)
 {
-	char *columns, *values;
-	char *p, *q;
-	unsigned vlen;
-	char *nullValues, *temp, *tp;
-	int nullCounter = 0, charCounter = 0;
 	char *sql = NULL, *path = NULL;
 	PGresult *res;
 
-	if (!template || !*template || !cdr || !*cdr) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Bad parameter\n");
-		return SWITCH_STATUS_FALSE;
-	}
-
-	/* Build comma-separated list of field names by dropping $ { } ; chars */
-	switch_strdup(columns, template);
-	for (p = columns, q = columns; *p; ++p) {
-		switch (*p) {
-			case '$': case '"': case '{': case '}': case ';':
-				break;
-			default:
-				*q++ = *p;
-		}
-	}
-	*q = '\0';
-
-	/*
-	 * In the expanded vars, replace double quotes (") with single quotes (')
-	 * for correct PostgreSQL syntax, and replace semi-colon with space to
-	 * prevent SQL injection attacks
-	 */
-	switch_strdup(values, cdr);
-	for (p = values; *p; ++p) {
-		switch(*p) {
-			case '"':
-				*p = '\'';
-				break;
-			case ';':
-				*p = ' ';
-				break;
-		}
-	}
-	vlen = p - values;
-
-	/*
-	 * Patch for changing empty strings ('') in the expanded variables to
-	 * PostgreSQL null
-	 */
-	for (p = values; *p; ++p) {
-		if (*p == ',') {
-			if (charCounter == 0) {
-				nullCounter++;
-			}
-			charCounter = 0;
-		} else if (*p != ' ' && *p != '\'') {
-			charCounter++;
-		}
-	}
-
-	if (charCounter == 0) {
-		nullCounter++;
-	}
-
-	nullCounter *= 4;
-	vlen += nullCounter;
-	switch_zmalloc(nullValues, strlen(values) + nullCounter + 1);
-	charCounter = 0;
-	temp = nullValues;
-	tp = nullValues;
-
-	for (p = values; *p; ++tp, ++p) {
-		if (*p == ',') {
-			if (charCounter == 0) {
-				temp++;
-				*temp = 'n';
-				temp++;
-				if (temp == tp) tp++;
-				*temp = 'u';
-				temp++;
-				if (temp == tp) tp++;
-				*temp = 'l';
-				temp++;
-				if (temp == tp) tp++;
-				*temp = 'l';
-				temp++;
-				while (temp != tp) {
-					*temp = ' ';
-					temp++;
-				}
-			}
-			charCounter = 0;
-			temp = tp;
-		} else if (*p != ' ' && *p != '\'') {
-			charCounter++;
-		}
-		*tp = *p;
-	}
-
-	if (charCounter == 0) {
-		temp++;
-		*temp = 'n';
-		temp++;
-		if (temp == tp) tp++;
-		*temp = 'u';
-		temp++;
-		if (temp == tp) tp++;
-		*temp = 'l';
-		temp++;
-		if (temp == tp) tp++;
-		*temp = 'l';
-		temp++;
-		while (temp != tp) {
-			*temp = ' ';
-			temp++;
-		}
-	}
-
-	charCounter = 0;
-	temp = tp;
-	*tp = 0;
-	tp = values;
-	values = nullValues;
-	switch_safe_free(tp);
-
-	sql = switch_mprintf("INSERT INTO %s (%s) VALUES (%s);", globals.db_table, columns, values);
+	sql = switch_mprintf("INSERT INTO %s (%s) VALUES (%s);", globals.db_table, globals.db_schema->columns, values);
 	assert(sql);
-	switch_safe_free(columns);
-	switch_safe_free(values);
 
 	if (globals.debug) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Query: \"%s\"\n", sql);
@@ -415,7 +298,7 @@ static switch_status_t insert_cdr(const char * const template, const char * cons
 	} else {
 		path = switch_mprintf("%s%scdr-spool.csv", globals.spool_dir, SWITCH_PATH_SEPARATOR);
 		assert(path);
-		spool_cdr(path, cdr);
+		spool_cdr(path, values);
 	}
 
 	switch_safe_free(path);
@@ -428,8 +311,10 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
 {
 	switch_channel_t *channel = switch_core_session_get_channel(session);
 	switch_status_t status = SWITCH_STATUS_SUCCESS;
-	const char *template_str = NULL;
-	char *expanded_vars = NULL;
+	char *values = NULL, *tmp = NULL, *pq_var = NULL;
+	const char *var = NULL;
+	cdr_field_t *cdr_field = NULL;
+	switch_size_t len, offset;
 
 	if (globals.shutdown) {
 		return SWITCH_STATUS_SUCCESS;
@@ -465,24 +350,40 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
 		}
 	}
 
-	template_str = (const char *) switch_core_hash_find(globals.template_hash, globals.default_template);
+	switch_zmalloc(values, 1);
+	offset = 0;
 
-	if (!template_str) {
-		template_str = default_template;
-	}
+	for (cdr_field = globals.db_schema->fields; cdr_field->var_name; cdr_field++) {
+		if ((var = switch_channel_get_variable(channel, cdr_field->var_name))) {
+			/* Allocate sufficient buffer for PQescapeString */
+			len = strlen(var);
+			tmp = switch_core_session_alloc(session, len * 2 + 1);
+			PQescapeString(tmp, var, len);
+			var = tmp;
+		}
 
-	expanded_vars = switch_channel_expand_variables(channel, template_str);
+		if (cdr_field->quote) {
+			if ((cdr_field->not_null == SWITCH_FALSE) && zstr(var)) {
+				pq_var = switch_mprintf("null,", var);
+			} else {
+				pq_var = switch_mprintf("'%s',", var);
+			}
+		} else {
+			pq_var = switch_mprintf("%s,", var);
+		}
 
-	if (!expanded_vars) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error expanding CDR variables.\n");
-		return SWITCH_STATUS_FALSE;
+		/* Resize values buffer to accomodate next var */
+		len = strlen(pq_var);
+		tmp = realloc(values, offset + len);
+		values = tmp;
+		memcpy(values + offset, pq_var, len);
+		switch_safe_free(pq_var);
+		offset += len;
 	}
+	*(values + --offset) = '\0';
 
-	insert_cdr(template_str, expanded_vars);
-
-	if (expanded_vars != template_str) {
-		switch_safe_free(expanded_vars);
-	}
+	insert_cdr(values);
+	switch_safe_free(values);
 
 	return status;
 }
@@ -532,9 +433,13 @@ static switch_state_handler_table_t state_handlers = {
 
 static switch_status_t load_config(switch_memory_pool_t *pool)
 {
-	char *cf = "cdr_pg_csv.conf";
-	switch_xml_t cfg, xml, settings, param;
 	switch_status_t status = SWITCH_STATUS_SUCCESS;
+	char *cf = "cdr_pg_csv.conf", *ptr;
+	switch_xml_t cfg, xml, schema, field;
+	const char *attr;
+	int num_fields = 0;
+	switch_size_t len = 0;
+	cdr_field_t *cdr_field;
 
 	if (globals.db_online) {
 		PQfinish(globals.db_connection);
@@ -544,32 +449,69 @@ static switch_status_t load_config(switch_memory_pool_t *pool)
 
 	memset(&globals, 0, sizeof(globals));
 	switch_core_hash_init(&globals.fd_hash, pool);
-	switch_core_hash_init(&globals.template_hash, pool);
 	switch_mutex_init(&globals.db_mutex, SWITCH_MUTEX_NESTED, pool);
 
 	globals.pool = pool;
 
-	switch_core_hash_insert(globals.template_hash, "default", default_template);
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding default template.\n");
-	globals.legs = CDR_LEG_A;
-
-	if (switch_xml_config_parse_module_settings("cdr_pg_csv.conf", SWITCH_FALSE, config_settings) != SWITCH_STATUS_SUCCESS) {
+	if (switch_xml_config_parse_module_settings(cf, SWITCH_FALSE, config_settings) != SWITCH_STATUS_SUCCESS) {
 		return SWITCH_STATUS_FALSE;
 	}
 
 	if ((xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
-		if ((settings = switch_xml_child(cfg, "templates"))) {
-			for (param = switch_xml_child(settings, "template"); param; param = param->next) {
-				char *var = (char *) switch_xml_attr(param, "name");
-				if (var) {
-					char *tpl;
-					tpl = switch_core_strdup(pool, param->txt);
-
-					switch_core_hash_insert(globals.template_hash, var, tpl);
-					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding template %s.\n", var);
+		if ((schema = switch_xml_child(cfg, "schema"))) {
+			/* Count fields in schema so we can calculate required buffer size */
+			for (field = switch_xml_child(schema, "field"); field; field = field->next) {
+				if (switch_xml_attr(field, "var")) {
+					num_fields++;
 				}
 			}
+
+			globals.db_schema = switch_core_alloc(pool, (num_fields + 1) * sizeof(cdr_field_t));
+			cdr_field = globals.db_schema->fields;
+
+			for (field = switch_xml_child(schema, "field"); field; field = field->next) {
+				if ((attr = switch_xml_attr(field, "var"))) {
+					cdr_field->var_name = switch_core_strdup(pool, attr);
+
+					/* Assume SQL column name is the same as FreeSWITCH channel var name, unless specified otherwise */
+					if ((attr = switch_xml_attr(field, "column"))) {
+						cdr_field->col_name = switch_core_strdup(pool, attr);
+					} else {
+						cdr_field->col_name = switch_core_strdup(pool, cdr_field->var_name);
+					}
+
+					/* Assume all fields should be quoted (treated as strings), unless specified otherwise */
+					if ((attr = switch_xml_attr(field, "quote")) && !strncmp(attr, "false", 5)) {
+						cdr_field->quote = SWITCH_FALSE;
+					} else {
+						cdr_field->quote = SWITCH_TRUE;
+					}
+
+					/* Assume all fields allow SQL nulls, unless specified otherwise */
+					if ((attr = switch_xml_attr(field, "not-null")) && !strncmp(attr, "true", 4)) {
+						cdr_field->not_null = SWITCH_TRUE;
+					} else {
+						cdr_field->not_null = SWITCH_FALSE;
+					}
+
+					len += strlen(cdr_field->col_name) + 1;
+					cdr_field++;
+				}
+			}
+			cdr_field->var_name = 0;
+
+			globals.db_schema->columns = switch_core_alloc(pool, len);
+			ptr = globals.db_schema->columns;
+			for (cdr_field = globals.db_schema->fields; cdr_field->col_name; cdr_field++) {
+				len = strlen(cdr_field->col_name);
+				memcpy(ptr, cdr_field->col_name, len);
+				ptr += len;
+				*ptr = ',';
+				ptr++;
+			}
+			*--ptr = '\0';
 		}
+
 		switch_xml_free(xml);
 	}
 
@@ -596,7 +538,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_pg_csv_load)
 	switch_core_add_state_handler(&state_handlers);
 	*module_interface = switch_loadable_module_create_module_interface(pool, modname);
 
-
 	return status;
 }
 
committer: Anthony Minessale
comments: 
default to 10

diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c
index c78aac7..c683203 100644
--- a/src/mod/endpoints/mod_sofia/mod_sofia.c
+++ b/src/mod/endpoints/mod_sofia/mod_sofia.c
@@ -3708,7 +3708,7 @@ SWITCH_STANDARD_API(sofia_function)
 
 				if (argc > 2) {
 					if (strstr(argv[2], "presence")) {
-						mod_sofia_globals.debug_presence = 1;
+						mod_sofia_globals.debug_presence = 10;
 						stream->write_function(stream, "+OK Debugging presence\n");
 					}
 					
committer: Anthony Minessale
comments: 
FS-3038

diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c
index 807770a..f34042a 100644
--- a/src/mod/applications/mod_commands/mod_commands.c
+++ b/src/mod/applications/mod_commands/mod_commands.c
@@ -4439,19 +4439,23 @@ SWITCH_STANDARD_API(strftime_tz_api_function)
 
 		if ((format = strchr(mycmd, ' '))) {
 			*format++ = '\0';
-		}
 		
-		if ((p = strchr(format, '|'))) {
-			*p++ = '\0';
-			when = atol(format);
-			format = p;
+			if (format && (p = strchr(format, '|'))) {
+				*p++ = '\0';
+				when = atol(format);
+				format = p;
+			}
 		}
 	}
 
-	if (switch_strftime_tz(tz_name, format, date, sizeof(date), when * 1000000) == SWITCH_STATUS_SUCCESS) {	/* The lookup of the zone may fail. */
+	if (zstr(format)) {
+		format = "%Y-%m-%d";
+	}
+	
+	if (format && switch_strftime_tz(tz_name, format, date, sizeof(date), when * 1000000) == SWITCH_STATUS_SUCCESS) {	/* The lookup of the zone may fail. */
 		stream->write_function(stream, "%s", date);
 	} else {
-		stream->write_function(stream, "-ERR Invalid Timezone\n");
+		stream->write_function(stream, "-ERR Invalid Timezone/Format\n");
 	}
 
 	switch_safe_free(mycmd);
committer: Anthony Minessale
comments: 
FS-3040

diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c
index f829e57..bea8214 100644
--- a/src/mod/applications/mod_voicemail/mod_voicemail.c
+++ b/src/mod/applications/mod_voicemail/mod_voicemail.c
@@ -1277,9 +1277,14 @@ static void message_count(vm_profile_t *profile, const char *id_in, const char *
 
 	myid = resolve_id(id_in, domain_name, "message-count");
 
-	switch_snprintf(sql, sizeof(sql), "select 1, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' "
-									  "and read_epoch=0 group by read_flags union select 0, read_flags, count(read_epoch) from voicemail_msgs where username='%s' "
-									  "and domain='%s' and in_folder='%s' and read_epoch<>0 group by read_flags;", myid, domain_name, myfolder);
+	switch_snprintf(sql, sizeof(sql), "select 1, read_flags, count(read_epoch) from voicemail_msgs where "
+					"username='%s' and domain='%s' and in_folder='%s' "
+					"and read_epoch=0 group by read_flags union select 0, read_flags, count(read_epoch) from voicemail_msgs where username='%s' "
+					"and domain='%s' and in_folder='%s' and read_epoch<>0 group by read_flags;", 
+					myid, domain_name, myfolder, myid, domain_name, myfolder);
+					
+				   
+
 	vm_execute_sql_callback(profile, profile->mutex, sql, message_count_callback, &cbt);
 
 	*total_new_messages = cbt.total_new_messages + cbt.total_new_urgent_messages;
committer: Daniel Swarbrick
comments: 
refactor config parsing

diff --git a/conf/autoload_configs/cdr_pg_csv.conf.xml b/conf/autoload_configs/cdr_pg_csv.conf.xml
index 2f2efa9..427bf2d 100644
--- a/conf/autoload_configs/cdr_pg_csv.conf.xml
+++ b/conf/autoload_configs/cdr_pg_csv.conf.xml
@@ -1,19 +1,23 @@
 <configuration name="cdr_pg_csv.conf" description="CDR PG CSV Format">
   <settings>
-    <!-- Log a-leg (a), b-leg (b) or both (ab) -->
-    <param name="legs" value="a"/>
     <!-- See parameters for PQconnectdb() at http://www.postgresql.org/docs/8.4/static/libpq-connect.html -->
     <param name="db-info" value="host=localhost dbname=cdr connect_timeout=10" />
     <!-- CDR table name -->
     <!--<param name="db-table" value="cdr"/>-->
-    <param name="default-template" value="example"/>
-    <!-- 'cdr-pg-csv' will always be appended to log-base -->
-    <!--<param name="log-base" value="/var/log"/>-->
+
+    <!-- Log a-leg (a), b-leg (b) or both (ab) -->
+    <param name="legs" value="a"/>
+
+    <!-- Directory in which to spool failed SQL inserts -->
+    <!-- <param name="spool-dir" value="$${base_dir}/log/cdr-pg-csv"/> -->
     <!-- Disk spool format if DB connection/insert fails - csv (default) or sql -->
     <param name="spool-format" value="csv"/>
     <param name="rotate-on-hup" value="true"/>
+
     <!-- This is like the info app but after the call is hung up -->
     <!--<param name="debug" value="true"/>-->
+
+    <param name="default-template" value="example"/>
   </settings>
   <templates>
     <template name="example">"${local_ip_v4}","${caller_id_name}","${caller_id_number}","${destination_number}","${context}","${start_stamp}","${answer_stamp}","${end_stamp}","${duration}","${billsec}","${hangup_cause}","${uuid}","${bleg_uuid}","${accountcode}","${read_codec}","${write_codec}","${sip_hangup_disposition}","${ani}"</template>
diff --git a/src/mod/event_handlers/mod_cdr_pg_csv/mod_cdr_pg_csv.c b/src/mod/event_handlers/mod_cdr_pg_csv/mod_cdr_pg_csv.c
index 5227161..1ec56bd 100644
--- a/src/mod/event_handlers/mod_cdr_pg_csv/mod_cdr_pg_csv.c
+++ b/src/mod/event_handlers/mod_cdr_pg_csv/mod_cdr_pg_csv.c
@@ -37,18 +37,27 @@
 #include <switch.h>
 #include <libpq-fe.h>
 
+SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_pg_csv_load);
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_cdr_pg_csv_shutdown);
+SWITCH_MODULE_DEFINITION(mod_cdr_pg_csv, mod_cdr_pg_csv_load, mod_cdr_pg_csv_shutdown, NULL);
+
+
 typedef enum {
 	CDR_LEG_A = (1 << 0),
 	CDR_LEG_B = (1 << 1)
 } cdr_leg_t;
 
-struct cdr_fd {
+typedef enum {
+	SPOOL_FORMAT_CSV,
+	SPOOL_FORMAT_SQL
+} spool_format_t;
+
+typedef struct {
 	int fd;
 	char *path;
 	int64_t bytes;
 	switch_mutex_t *mutex;
-};
-typedef struct cdr_fd cdr_fd_t;
+} cdr_fd_t;
 
 const char *default_template =
 	"\"${local_ip_v4}\",\"${caller_id_name}\",\"${caller_id_number}\",\"${destination_number}\",\"${context}\",\"${start_stamp}\","
@@ -59,23 +68,59 @@ static struct {
 	switch_memory_pool_t *pool;
 	switch_hash_t *fd_hash;
 	switch_hash_t *template_hash;
-	char *log_dir;
-	char *default_template;
 	int shutdown;
-	int rotate;
-	int debug;
-	cdr_leg_t legs;
 	char *db_info;
 	char *db_table;
-	char *spool_format;
 	PGconn *db_connection;
 	int db_online;
+	cdr_leg_t legs;
+	char *spool_dir;
+	spool_format_t spool_format;
+	int rotate;
+	int debug;
+	char *default_template;
 	switch_mutex_t *db_mutex;
 } globals = { 0 };
 
-SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_pg_csv_load);
-SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_cdr_pg_csv_shutdown);
-SWITCH_MODULE_DEFINITION(mod_cdr_pg_csv, mod_cdr_pg_csv_load, mod_cdr_pg_csv_shutdown, NULL);
+static switch_xml_config_enum_item_t config_opt_cdr_leg_enum[] = {
+        {"a", CDR_LEG_A},
+        {"b", CDR_LEG_B},
+        {"ab", CDR_LEG_A | CDR_LEG_B},
+        {NULL, 0}
+};
+
+static switch_xml_config_enum_item_t config_opt_spool_format_enum[] = {
+        {"csv", SPOOL_FORMAT_CSV},
+        {"sql", SPOOL_FORMAT_SQL},
+        {NULL, 0}
+};
+
+static switch_status_t config_validate_spool_dir(switch_xml_config_item_t *item, const char *newvalue, switch_config_callback_type_t callback_type, switch_bool_t changed)
+{
+	if ((callback_type == CONFIG_LOAD || callback_type == CONFIG_RELOAD)) {
+		if (zstr(newvalue)) {
+			globals.spool_dir = switch_core_sprintf(globals.pool, "%s%scdr-pg-csv", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR);
+		}
+	}
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_xml_config_item_t config_settings[] = {
+	/* key, type, flags, ptr, default_value, data, syntax, helptext */
+	SWITCH_CONFIG_ITEM_STRING_STRDUP("db-info", CONFIG_RELOADABLE, &globals.db_info, "dbname=cdr", NULL, NULL),
+	SWITCH_CONFIG_ITEM_STRING_STRDUP("db-table", CONFIG_RELOADABLE, &globals.db_table, "cdr", NULL, NULL),
+	SWITCH_CONFIG_ITEM_STRING_STRDUP("default-template", CONFIG_RELOADABLE, &globals.default_template, "default", NULL, NULL),
+	SWITCH_CONFIG_ITEM("legs", SWITCH_CONFIG_ENUM, CONFIG_RELOADABLE, &globals.legs, (void *) CDR_LEG_A, &config_opt_cdr_leg_enum, "a|b|ab", NULL),
+	SWITCH_CONFIG_ITEM("spool-format", SWITCH_CONFIG_ENUM, CONFIG_RELOADABLE, &globals.spool_format, (void *) SPOOL_FORMAT_CSV, &config_opt_spool_format_enum, "csv|sql", "Disk spool format to use if SQL insert fails."),
+	SWITCH_CONFIG_ITEM("rotate-on-hup", SWITCH_CONFIG_BOOL, CONFIG_RELOADABLE, &globals.rotate, SWITCH_FALSE, NULL, NULL, NULL),
+	SWITCH_CONFIG_ITEM("debug", SWITCH_CONFIG_BOOL, CONFIG_RELOADABLE, &globals.debug, SWITCH_FALSE, NULL, NULL, NULL),
+
+	/* key, type, flags, ptr, defaultvalue, function, functiondata, syntax, helptext */
+	SWITCH_CONFIG_ITEM_CALLBACK("spool-dir", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, &globals.spool_dir, NULL, config_validate_spool_dir, NULL, NULL, NULL),
+	SWITCH_CONFIG_ITEM_END()
+};
+
 
 static off_t fd_size(int fd)
 {
@@ -363,12 +408,12 @@ static switch_status_t insert_cdr(const char * const template, const char * cons
 	switch_mutex_unlock(globals.db_mutex);
 
 	/* SQL INSERT failed for whatever reason. Spool the attempted query to disk */
-	if (!strcasecmp(globals.spool_format, "sql")) {
-		path = switch_mprintf("%s%scdr-spool.sql", globals.log_dir, SWITCH_PATH_SEPARATOR);
+	if (globals.spool_format == SPOOL_FORMAT_SQL) {
+		path = switch_mprintf("%s%scdr-spool.sql", globals.spool_dir, SWITCH_PATH_SEPARATOR);
 		assert(path);
 		spool_cdr(path, sql);
 	} else {
-		path = switch_mprintf("%s%scdr-spool.csv", globals.log_dir, SWITCH_PATH_SEPARATOR);
+		path = switch_mprintf("%s%scdr-spool.csv", globals.spool_dir, SWITCH_PATH_SEPARATOR);
 		assert(path);
 		spool_cdr(path, cdr);
 	}
@@ -402,8 +447,8 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
 		}
 	}
 
-	if (switch_dir_make_recursive(globals.log_dir, SWITCH_DEFAULT_DIR_PERMS, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", globals.log_dir);
+	if (switch_dir_make_recursive(globals.spool_dir, SWITCH_DEFAULT_DIR_PERMS, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", globals.spool_dir);
 		return SWITCH_STATUS_FALSE;
 	}
 
@@ -485,7 +530,6 @@ static switch_state_handler_table_t state_handlers = {
 };
 
 
-
 static switch_status_t load_config(switch_memory_pool_t *pool)
 {
 	char *cf = "cdr_pg_csv.conf";
@@ -509,40 +553,11 @@ static switch_status_t load_config(switch_memory_pool_t *pool)
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding default template.\n");
 	globals.legs = CDR_LEG_A;
 
-	if ((xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
-
-		if ((settings = switch_xml_child(cfg, "settings"))) {
-			for (param = switch_xml_child(settings, "param"); param; param = param->next) {
-				char *var = (char *) switch_xml_attr_soft(param, "name");
-				char *val = (char *) switch_xml_attr_soft(param, "value");
-				if (!strcasecmp(var, "debug")) {
-					globals.debug = switch_true(val);
-				} else if (!strcasecmp(var, "legs")) {
-					globals.legs = 0;
-
-					if (strchr(val, 'a')) {
-						globals.legs |= CDR_LEG_A;
-					}
-
-					if (strchr(val, 'b')) {
-						globals.legs |= CDR_LEG_B;
-					}
-				} else if (!strcasecmp(var, "log-base")) {
-					globals.log_dir = switch_core_sprintf(pool, "%s%scdr-pg-csv", val, SWITCH_PATH_SEPARATOR);
-				} else if (!strcasecmp(var, "rotate-on-hup")) {
-					globals.rotate = switch_true(val);
-				} else if (!strcasecmp(var, "db-info")) {
-					globals.db_info = switch_core_strdup(pool, val);
-				} else if (!strcasecmp(var, "db-table") || !strcasecmp(var, "g-table")) {
-					globals.db_table = switch_core_strdup(pool, val);
-				} else if (!strcasecmp(var, "default-template")) {
-					globals.default_template = switch_core_strdup(pool, val);
-				} else if (!strcasecmp(var, "spool-format")) {
-					globals.spool_format = switch_core_strdup(pool, val);
-				}
-			}
-		}
+	if (switch_xml_config_parse_module_settings("cdr_pg_csv.conf", SWITCH_FALSE, config_settings) != SWITCH_STATUS_SUCCESS) {
+		return SWITCH_STATUS_FALSE;
+	}
 
+	if ((xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
 		if ((settings = switch_xml_child(cfg, "templates"))) {
 			for (param = switch_xml_child(settings, "template"); param; param = param->next) {
 				char *var = (char *) switch_xml_attr(param, "name");
@@ -558,26 +573,6 @@ static switch_status_t load_config(switch_memory_pool_t *pool)
 		switch_xml_free(xml);
 	}
 
-	if (!globals.log_dir) {
-		globals.log_dir = switch_core_sprintf(pool, "%s%scdr-pg-csv", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR);
-	}
-
-	if (zstr(globals.db_info)) {
-		globals.db_info = switch_core_strdup(pool, "dbname=cdr");
-	}
-
-	if (zstr(globals.db_table)) {
-		globals.db_table = switch_core_strdup(pool, "cdr");
-	}
-
-	if (zstr(globals.default_template)) {
-		globals.default_template = switch_core_strdup(pool, "default");
-	}
-
-	if (zstr(globals.spool_format)) {
-		globals.spool_format = switch_core_strdup(pool, "csv");
-	}
-
 	return status;
 }
 
@@ -588,8 +583,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_pg_csv_load)
 
 	load_config(pool);
 
-	if ((status = switch_dir_make_recursive(globals.log_dir, SWITCH_DEFAULT_DIR_PERMS, pool)) != SWITCH_STATUS_SUCCESS) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", globals.log_dir);
+	if ((status = switch_dir_make_recursive(globals.spool_dir, SWITCH_DEFAULT_DIR_PERMS, pool)) != SWITCH_STATUS_SUCCESS) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", globals.spool_dir);
 		return status;
 	}
 
committer: Konrad Hammel
comments: 
freemtdm: ss7 - SPC no long in sng_gen...new configuration file

diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c
index 01d1013..20bcc3a 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c
@@ -99,6 +99,7 @@ int  ft_to_sngss7_cfg_all(void)
 			return 1;
 		} else {
 			SS7_INFO("Started Stack Manager!\n");
+			sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_SM);
 		}
 
 		/* check if the configuration had a Relay Channel */
@@ -575,12 +576,10 @@ int ftmod_ss7_mtp3_gen_config(void)
 
 
 	cfg.t.cfg.s.snGen.typeSP		= LSN_TYPE_SP;		/* type of signalling postatic int */
-	cfg.t.cfg.s.snGen.spCode1		= g_ftdm_sngss7_data.cfg.spc;	/* our DPC for CCITT version */
-
+	cfg.t.cfg.s.snGen.spCode1		= 0;				/* our DPC for CCITT version */
 #if (SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || SS7_CHINA || defined(TDS_ROLL_UPGRADE_SUPPORT))
-	cfg.t.cfg.s.snGen.spCode2		= g_ftdm_sngss7_data.cfg.spc;	/* our DPC for ANSI or CHINA version */
+	cfg.t.cfg.s.snGen.spCode2		= 0;				/* our DPC for ANSI or CHINA version */
 #endif
-
 	cfg.t.cfg.s.snGen.ssfValid		= TRUE;				/* ssf validation required */
 	cfg.t.cfg.s.snGen.nmbDLSap		= MAX_SN_LINKS;		/* number of MTP Data Link SAPs */
 	cfg.t.cfg.s.snGen.nmbNSap		= MAX_SN_ROUTES;	/* number of Upper Layer Saps */
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
index ad52827..2f2e502 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
@@ -1598,7 +1598,9 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_ss7_unload)
 		sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY);
 	}
 
-	sng_isup_free_sm();
+	if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_SM)) {
+		sng_isup_free_sm();
+	}
 
 	sng_isup_free_gen();
 
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
index dc6428d..46df990 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
@@ -464,11 +464,6 @@ static int ftmod_ss7_parse_sng_gen(ftdm_conf_node_t *sng_gen)
 			SS7_DEBUG("Found license file = %s\n", g_ftdm_sngss7_data.cfg.license);
 			SS7_DEBUG("Found signature file = %s\n", g_ftdm_sngss7_data.cfg.signature);	
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "spc")) {
-		/**********************************************************************/
-			g_ftdm_sngss7_data.cfg.spc = atoi(parm->val);
-			SS7_DEBUG("Found SPC = %d\n", g_ftdm_sngss7_data.cfg.spc);
-		/**********************************************************************/
 		} else {
 		/**********************************************************************/
 			SS7_ERROR("Found an invalid parameter \"%s\"!\n", parm->val);
committer: Konrad Hammel
comments: 
freetdm: ss7 - only unload layers when they are loaded freetdm: ss7 - configuration updated to allow a route to use multiple linksets...new configuration file

diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c
index 15fc1ef..01d1013 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c
@@ -74,6 +74,7 @@ int ftmod_ss7_relay_chan_config(int id);
 int  ft_to_sngss7_cfg_all(void)
 {
 	int x = 0;
+	int ret = 0;
 
 	/* check if we have done gen_config already */
 	if (!(g_ftdm_sngss7_data.gen_config)) {
@@ -289,15 +290,17 @@ int  ft_to_sngss7_cfg_all(void)
 		/* check if this link has been configured already */
 		if (!(g_ftdm_sngss7_data.cfg.nsap[x].flags & SNGSS7_CONFIGURED)) {
 
-			if (ftmod_ss7_mtp3_nsap_config(x)) {
-				SS7_CRITICAL("MTP3 NSAP %d configuration FAILED!\n", x);
+			ret = ftmod_ss7_mtp3_nsap_config(x);
+			if (ret) {
+				SS7_CRITICAL("MTP3 NSAP %d configuration FAILED!(%s)\n", x, DECODE_LCM_REASON(ret));
 				return 1;
 			} else {
 				SS7_INFO("MTP3 NSAP %d configuration DONE!\n", x);
 			}
 
-			if (ftmod_ss7_isup_nsap_config(x)) {
-				SS7_CRITICAL("ISUP NSAP %d configuration FAILED!\n", x);
+			ret = ftmod_ss7_isup_nsap_config(x);
+			if (ret) {
+				SS7_CRITICAL("ISUP NSAP %d configuration FAILED!(%s)\n", x, DECODE_LCM_REASON(ret));
 				return 1;
 			} else {
 				SS7_INFO("ISUP NSAP %d configuration DONE!\n", x);
@@ -580,7 +583,7 @@ int ftmod_ss7_mtp3_gen_config(void)
 
 	cfg.t.cfg.s.snGen.ssfValid		= TRUE;				/* ssf validation required */
 	cfg.t.cfg.s.snGen.nmbDLSap		= MAX_SN_LINKS;		/* number of MTP Data Link SAPs */
-	cfg.t.cfg.s.snGen.nmbNSap		= MAX_SN_VARIANTS;	/* number of Upper Layer Saps */
+	cfg.t.cfg.s.snGen.nmbNSap		= MAX_SN_ROUTES;	/* number of Upper Layer Saps */
 	cfg.t.cfg.s.snGen.nmbRouts		= MAX_SN_ROUTES;	/* maximum number of routing entries */
 	cfg.t.cfg.s.snGen.nmbLnkSets	= MAX_SN_LINKSETS;	/* number of link sets */
 	cfg.t.cfg.s.snGen.nmbRteInst	= MAX_SN_ROUTES*16;	/* number of simultaneous Rte instances */
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c
index 4ab4359..0298429 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c
@@ -1131,45 +1131,56 @@ static ftdm_status_t handle_show_status(ftdm_stream_handle_t *stream, int span,
 					ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
 					ftdmchan = ss7_info->ftdmchan;
 
-					/* grab the signaling_status */
-					ftdm_channel_get_sig_status(ftdmchan, &sigstatus);
-	
-					stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|sig_status=%4s|state=%s|",
-													ckt->span,
-													ckt->chan,
-													ckt->cic,
-													ftdm_signaling_status2str(sigstatus),
-													ftdm_channel_state2str(ftdmchan->state));
-	
-					if((sngss7_test_ckt_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || (sngss7_test_ckt_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX))) {
-						stream->write_function(stream, "l_mn=Y|");
-					}else {
-						stream->write_function(stream, "l_mn=N|");
-					}
-	
-					if((sngss7_test_ckt_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || (sngss7_test_ckt_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) {
-						stream->write_function(stream, "r_mn=Y|");
-					}else {
-						stream->write_function(stream, "r_mn=N|");
-					}
-	
-					if(sngss7_test_ckt_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) {
-						stream->write_function(stream, "l_hw=Y|");
-					}else {
-						stream->write_function(stream, "l_hw=N|");
-					}
+					if (ftdmchan == NULL) {
+						/* this should never happen!!! */
+						stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|FTDMCHAN DOES NOT EXISTS",
+														ckt->span,
+														ckt->chan,
+														ckt->cic);
+						
+					} else {
+						/* grab the signaling_status */
+						ftdm_channel_get_sig_status(ftdmchan, &sigstatus);
+		
+						stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|sig_status=%4s|state=%s|",
+														ckt->span,
+														ckt->chan,
+														ckt->cic,
+														ftdm_signaling_status2str(sigstatus),
+														ftdm_channel_state2str(ftdmchan->state));
+		
+						if ((sngss7_test_ckt_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || 
+							(sngss7_test_ckt_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX))) {
+							stream->write_function(stream, "l_mn=Y|");
+						}else {
+							stream->write_function(stream, "l_mn=N|");
+						}
+		
+						if ((sngss7_test_ckt_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || 
+							(sngss7_test_ckt_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) {
+							stream->write_function(stream, "r_mn=Y|");
+						}else {
+							stream->write_function(stream, "r_mn=N|");
+						}
+		
+						if (sngss7_test_ckt_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) {
+							stream->write_function(stream, "l_hw=Y|");
+						}else {
+							stream->write_function(stream, "l_hw=N|");
+						}
+		
+						if (sngss7_test_ckt_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) {
+							stream->write_function(stream, "r_hw=Y|");
+						}else {
+							stream->write_function(stream, "r_hw=N|");
+						}
 	
-					if(sngss7_test_ckt_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) {
-						stream->write_function(stream, "r_hw=Y|");
-					}else {
-						stream->write_function(stream, "r_hw=N|");
+						if (sngss7_test_ckt_flag(ss7_info, FLAG_RELAY_DOWN)) {
+							stream->write_function(stream, "relay=Y|");
+						}else {
+							stream->write_function(stream, "relay=N|");
+						}
 					}
-
-					if(sngss7_test_ckt_flag(ss7_info, FLAG_RELAY_DOWN)) {
-						stream->write_function(stream, "relay=Y|");
-					}else {
-						stream->write_function(stream, "relay=N|");
-					}		
 	
 					stream->write_function(stream, "flags=0x%X",ss7_info->ckt_flags);
 	
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
index adee000..ad52827 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
@@ -1570,26 +1570,33 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_ss7_unload)
 
 	if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC)) {
 		sng_isup_free_cc();
+		sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC);
 	}
 
 	if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP)) {
 		ftmod_ss7_shutdown_isup();
 		sng_isup_free_isup();
+		sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP);
 	}
 
 	if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3)) {
 		ftmod_ss7_shutdown_mtp3();
 		sng_isup_free_mtp3();
+		sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3);
 	}
 
 	if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2)) {
 		ftmod_ss7_shutdown_mtp2();
 		sng_isup_free_mtp2();
 		sng_isup_free_mtp1();
+		sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2);
 	}
 
-	ftmod_ss7_shutdown_relay();
-	sng_isup_free_relay();
+	if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY)) {
+		ftmod_ss7_shutdown_relay();
+		sng_isup_free_relay();
+		sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY);
+	}
 
 	sng_isup_free_sm();
 
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
index 5272aa8..fe291fb 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
@@ -219,13 +219,18 @@ typedef struct sng_link_set {
 	uint32_t		links[16];
 } sng_link_set_t;
 
+typedef struct sng_link_set_list {
+	uint32_t					lsId;
+	struct sng_link_set_list	*next;
+} sng_link_set_list_t;
+
 typedef struct sng_route {
 	char			name[MAX_NAME_LEN];
 	uint32_t		flags;
 	uint32_t		id;
 	uint32_t		dpc;
 	uint32_t		cmbLinkSetId;
-	uint32_t		linkSetId;
+	struct sng_link_set_list	lnkSets;
 	uint32_t		linkType;
 	uint32_t		switchType;
 	uint32_t		ssf;
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
index d2fa973..dc6428d 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
@@ -1268,9 +1268,9 @@ static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route)
 	ftdm_conf_parameter_t	*parm = mtp_route->parameters;
 	int					 	num_parms = mtp_route->n_parameters;
 	int					 	i;
+	sng_link_set_list_t		*lnkSet;
 
 	ftdm_conf_node_t		*linkset;
-	int						ls_id;
 	int						numLinks;
 
 	/* initalize the mtpRoute structure */
@@ -1383,42 +1383,50 @@ static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route)
 	}
 
 	/* fill in the rest of the values in the mtpRoute struct  */
-	mtpRoute.nwId = mtpRoute.id;
+	mtpRoute.nwId = 0;
 	mtpRoute.cmbLinkSetId = mtpRoute.id;
 
 	/* parse in the list of linksets this route is reachable by */
 	linkset = mtp_route->child->child;
 
+	/* initalize the link-list of linkSet Ids */
+	lnkSet = &mtpRoute.lnkSets;
+
 	while (linkset != NULL) {
 	/**************************************************************************/
 		/* extract the linkset Id */
-		ls_id = atoi(linkset->parameters->val);
+		lnkSet->lsId = atoi(linkset->parameters->val);
 
-		if (g_ftdm_sngss7_data.cfg.mtpLinkSet[ls_id].id != 0) {
-			SS7_DEBUG("Found mtpRoute linkset id = %d that is valid\n",ls_id);
+		if (g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].id != 0) {
+			SS7_DEBUG("Found mtpRoute linkset id = %d that is valid\n",lnkSet->lsId);
 		} else {
-			SS7_ERROR("Found mtpRoute linkset id = %d that is invalid\n",ls_id);
+			SS7_ERROR("Found mtpRoute linkset id = %d that is invalid\n",lnkSet->lsId);
 			goto move_along;
 		}
 
 		/* pull up the linktype, switchtype, and SSF from the linkset */
-		mtpRoute.linkType = g_ftdm_sngss7_data.cfg.mtpLinkSet[ls_id].linkType;
-		mtpRoute.switchType = g_ftdm_sngss7_data.cfg.mtpLinkSet[ls_id].switchType;
-		mtpRoute.ssf = g_ftdm_sngss7_data.cfg.mtpLinkSet[ls_id].ssf;
+		mtpRoute.linkType = g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].linkType;
+		mtpRoute.switchType = g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].switchType;
+		mtpRoute.ssf = g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].ssf;
 		
 		/* extract the number of cmbLinkSetId aleady on this linkset */
-		numLinks = g_ftdm_sngss7_data.cfg.mtpLinkSet[ls_id].numLinks;
+		numLinks = g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].numLinks;
 		
 		/* add this routes cmbLinkSetId to the list */
-		g_ftdm_sngss7_data.cfg.mtpLinkSet[ls_id].links[numLinks] = mtpRoute.cmbLinkSetId;
+		g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].links[numLinks] = mtpRoute.cmbLinkSetId;
 
 		/* increment the number of cmbLinkSets on this linkset */
-		g_ftdm_sngss7_data.cfg.mtpLinkSet[ls_id].numLinks++;
+		g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].numLinks++;
+
+		/* update the linked list */
+		lnkSet->next = ftdm_malloc(sizeof(sng_link_set_list_t));
+		lnkSet = lnkSet->next;
+		lnkSet->lsId = 0;
+		lnkSet->next = NULL;
 
 move_along:
 		/* move to the next linkset element */
 		linkset = linkset->next;
-
 	/**************************************************************************/
 	} /* while (linkset != null) */
 
@@ -1465,6 +1473,7 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
 {
 	sng_isup_inf_t			sng_isup;
 	sng_isap_t				sng_isap;
+	sng_link_set_list_t		*lnkSet;
 	ftdm_conf_parameter_t	*parm = isup_interface->parameters;
 	int						num_parms = isup_interface->n_parameters;
 	int						i;
@@ -1500,7 +1509,6 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
 		} else if (!strcasecmp(parm->var, "spc")) {
 		/**********************************************************************/
 			sng_isup.spc = atoi(parm->val);
-			g_ftdm_sngss7_data.cfg.spc = sng_isup.spc;
 			SS7_DEBUG("Found an isup SPC = %d\n", sng_isup.spc);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "mtprouteId")) {
@@ -1747,17 +1755,14 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
 	sngss7_set_flag(&sng_isup, SNGSS7_PAUSED);
 
 	/* trickle down the SPC to all sub entities */
-	int	linkSetId;
+	lnkSet = &g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].lnkSets;
 
-	linkSetId = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].linkSetId;
+	g_ftdm_sngss7_data.cfg.mtp3Link[lnkSet->lsId].spc = sng_isup.spc;
+	lnkSet = lnkSet->next;
 
-	i = 1;
-	while (g_ftdm_sngss7_data.cfg.mtp3Link[i].id != 0) {
-		if (g_ftdm_sngss7_data.cfg.mtp3Link[i].linkSetId == linkSetId) {
-			g_ftdm_sngss7_data.cfg.mtp3Link[i].spc = g_ftdm_sngss7_data.cfg.spc;
-		}
-
-		i++;
+	while (lnkSet->next != NULL) {
+		g_ftdm_sngss7_data.cfg.mtp3Link[lnkSet->lsId].spc = sng_isup.spc;
+		lnkSet = lnkSet->next;
 	}
 
 	/* pull values from the lower levels */
@@ -2342,7 +2347,10 @@ static int ftmod_ss7_fill_in_mtpLinkSet(sng_link_set_t *mtpLinkSet)
 /******************************************************************************/
 static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route)
 {
-	int i = mtp3_route->id;
+	sng_link_set_list_t	*lnkSet = NULL;
+	int 				i = mtp3_route->id;
+	int					tmp = 0;
+
 
 	/* check if this id value has been used already */
 	if (g_ftdm_sngss7_data.cfg.mtpRoute[i].id == 0) {
@@ -2355,10 +2363,19 @@ static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route)
 	}
 
 	/* fill in the cmbLinkSet in the linkset structure */
-	int tmp = g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3_route->linkSetId].numLinks;
+	lnkSet = &mtp3_route->lnkSets;
+
+	tmp = g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].numLinks;
+	g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].links[tmp] = mtp3_route->cmbLinkSetId;
+	g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].numLinks++;
+
+	while (lnkSet->next != NULL) {
+		tmp = g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].numLinks;
+		g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].links[tmp] = mtp3_route->cmbLinkSetId;
+		g_ftdm_sngss7_data.cfg.mtpLinkSet[lnkSet->lsId].numLinks++;
 
-	g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3_route->linkSetId].links[tmp] = mtp3_route->cmbLinkSetId;
-	g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3_route->linkSetId].numLinks++;
+		lnkSet = lnkSet->next;
+	}
 
 	strcpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[i].name, (char *)mtp3_route->name);
 
@@ -2369,7 +2386,7 @@ static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route)
 	g_ftdm_sngss7_data.cfg.mtpRoute[i].cmbLinkSetId	= mtp3_route->cmbLinkSetId;
 	g_ftdm_sngss7_data.cfg.mtpRoute[i].isSTP		= mtp3_route->isSTP;
 	g_ftdm_sngss7_data.cfg.mtpRoute[i].nwId			= mtp3_route->nwId;
-	g_ftdm_sngss7_data.cfg.mtpRoute[i].linkSetId	= mtp3_route->linkSetId;
+	g_ftdm_sngss7_data.cfg.mtpRoute[i].lnkSets		= mtp3_route->lnkSets;
 	g_ftdm_sngss7_data.cfg.mtpRoute[i].ssf			= mtp3_route->ssf;
 	if (mtp3_route->t6 != 0) {
 		g_ftdm_sngss7_data.cfg.mtpRoute[i].t6		= mtp3_route->t6;
@@ -2439,8 +2456,7 @@ static int ftmod_ss7_fill_in_nsap(sng_route_t *mtp3_route)
 	i = 1;
 	while (g_ftdm_sngss7_data.cfg.nsap[i].id != 0) {
 		if ((g_ftdm_sngss7_data.cfg.nsap[i].linkType == mtp3_route->linkType) &&
-			(g_ftdm_sngss7_data.cfg.nsap[i].switchType == mtp3_route->switchType) &&
-			(g_ftdm_sngss7_data.cfg.nsap[i].ssf == mtp3_route->ssf)) {
+			(g_ftdm_sngss7_data.cfg.nsap[i].switchType == mtp3_route->switchType)) {
 
 			/* we have a match so break out of this loop */
 			break;
@@ -2789,6 +2805,7 @@ static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan)
 	sngss7_chan_data_t	*ss7_info = NULL;
 	int					x;
 	int					count = 1;
+	int					flag;
 
 	while (ccSpan->ch_map[0] != '\0') {
 	/**************************************************************************/
@@ -2799,13 +2816,45 @@ static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan)
 			return FTDM_FAIL;
 		}
 
-		/* find the spot in master array for this circuit */
-		x = (ccSpan->procId * 1000) + count;
+		/* find a spot for this circuit in the global structure */
+		x = (ccSpan->procId * 1000);
+		flag = 0;
+		while (flag == 0) {
+		/**********************************************************************/
+			/* check the id value ( 0 = new, 0 > circuit can be existing) */
+			if (g_ftdm_sngss7_data.cfg.isupCkt[x].id == 0) {
+				/* we're at the end of the list of circuitsl aka this is new */
+				SS7_DEBUG("Found a new circuit %d, ccSpanId=%d, chan=%d\n",
+							x, 
+							ccSpan->id, 
+							count);
 
-		/* check if this circuit has already been filled in */
-		if (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
-			SS7_DEVEL_DEBUG("Filling in circuit that already exists...%d\n", x);
-		}
+				/* throw the flag to end the loop */
+				flag = 1;
+			} else {
+				/* check the ccspan.id and chan to see if the circuit already exists */
+				if ((g_ftdm_sngss7_data.cfg.isupCkt[x].ccSpanId == ccSpan->id) &&
+					(g_ftdm_sngss7_data.cfg.isupCkt[x].chan == count)) {
+
+					/* we are processing a circuit that already exists */
+					SS7_DEBUG("Found an existing circuit %d, ccSpanId=%d, chan%d\n",
+								x, 
+								ccSpan->id, 
+								count);
+	
+					/* throw the flag to end the loop */
+					flag = 1;
+
+					/* not supporting reconfig at this time */
+					SS7_DEBUG("Not supporting ckt reconfig at this time!\n");
+					goto move_along;
+				} else {
+					/* this is not the droid you are looking for */
+					x++;
+				}
+			}
+		/**********************************************************************/
+		} /* while (flag == 0) */
 
 		/* prepare the global info sturcture */
 		ss7_info = ftdm_calloc(1, sizeof(sngss7_chan_data_t));
@@ -2901,6 +2950,7 @@ static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan)
 					g_ftdm_sngss7_data.cfg.isupCkt[x].cic,
 					g_ftdm_sngss7_data.cfg.isupCkt[x].id);
 
+move_along:
 		/* increment the span channel count */
 		count++;
 
committer: cypromis
comments: 
more formatting mistakes *sigh*

diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c
index 1684127..f829e57 100644
--- a/src/mod/applications/mod_voicemail/mod_voicemail.c
+++ b/src/mod/applications/mod_voicemail/mod_voicemail.c
@@ -1277,9 +1277,9 @@ static void message_count(vm_profile_t *profile, const char *id_in, const char *
 
 	myid = resolve_id(id_in, domain_name, "message-count");
 
-	switch_snprintf(sql, sizeof(sql), "select 1, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' and read_epoch=0 group by read_flags union 
-	select 0, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' and read_epoch<>0 group by read_flags;",	myid, domain_name, myfolder);
-
+	switch_snprintf(sql, sizeof(sql), "select 1, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' "
+									  "and read_epoch=0 group by read_flags union select 0, read_flags, count(read_epoch) from voicemail_msgs where username='%s' "
+									  "and domain='%s' and in_folder='%s' and read_epoch<>0 group by read_flags;", myid, domain_name, myfolder);
 	vm_execute_sql_callback(profile, profile->mutex, sql, message_count_callback, &cbt);
 
 	*total_new_messages = cbt.total_new_messages + cbt.total_new_urgent_messages;
committer: cypromis
comments: 
seems whitespaces are unpopular on some linux/gcc combinations

diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c
index f868c3a..1684127 100644
--- a/src/mod/applications/mod_voicemail/mod_voicemail.c
+++ b/src/mod/applications/mod_voicemail/mod_voicemail.c
@@ -1277,11 +1277,8 @@ static void message_count(vm_profile_t *profile, const char *id_in, const char *
 
 	myid = resolve_id(id_in, domain_name, "message-count");
 
-	switch_snprintf(sql, sizeof(sql),
-					"select 1, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' and read_epoch=0 group by read_flags 
-					union 
-					select 0, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' and read_epoch<>0 group by read_flags;",	
-					myid, domain_name, myfolder);
+	switch_snprintf(sql, sizeof(sql), "select 1, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' and read_epoch=0 group by read_flags union 
+	select 0, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' and read_epoch<>0 group by read_flags;",	myid, domain_name, myfolder);
 
 	vm_execute_sql_callback(profile, profile->mutex, sql, message_count_callback, &cbt);
 
committer: cypromis
comments: 
FS-1742 - Make Voicemail use 1 SQL query instead of 4 to get the message count use in MWI - Now also working on your more favourite and less favourite databases

diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c
index 80b011e..f868c3a 100644
--- a/src/mod/applications/mod_voicemail/mod_voicemail.c
+++ b/src/mod/applications/mod_voicemail/mod_voicemail.c
@@ -1278,7 +1278,9 @@ static void message_count(vm_profile_t *profile, const char *id_in, const char *
 	myid = resolve_id(id_in, domain_name, "message-count");
 
 	switch_snprintf(sql, sizeof(sql),
-					"select read_epoch=0, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' group by read_epoch=0,read_flags;",
+					"select 1, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' and read_epoch=0 group by read_flags 
+					union 
+					select 0, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' and read_epoch<>0 group by read_flags;",	
 					myid, domain_name, myfolder);
 
 	vm_execute_sql_callback(profile, profile->mutex, sql, message_count_callback, &cbt);
committer: Leon de Rooij
comments: 
Merge branch 'master' of ssh://git.freeswitch.org/freeswitch
committer: Leon de Rooij
comments: 
reswig mod_lua for freeswitch.email

diff --git a/src/mod/languages/mod_lua/mod_lua_wrap.cpp b/src/mod/languages/mod_lua/mod_lua_wrap.cpp
index 1d84a39..559d403 100644
--- a/src/mod/languages/mod_lua/mod_lua_wrap.cpp
+++ b/src/mod/languages/mod_lua/mod_lua_wrap.cpp
@@ -1582,6 +1582,55 @@ fail:
 }
 
 
+static int _wrap_email(lua_State* L) {
+  int SWIG_arg = -1;
+  char *arg1 = (char *) 0 ;
+  char *arg2 = (char *) 0 ;
+  char *arg3 = (char *) NULL ;
+  char *arg4 = (char *) NULL ;
+  char *arg5 = (char *) NULL ;
+  char *arg6 = (char *) NULL ;
+  char *arg7 = (char *) NULL ;
+  bool result;
+  
+  SWIG_check_num_args("email",2,7)
+  if(!lua_isstring(L,1)) SWIG_fail_arg("email",1,"char *");
+  if(!lua_isstring(L,2)) SWIG_fail_arg("email",2,"char *");
+  if(lua_gettop(L)>=3 && !lua_isstring(L,3)) SWIG_fail_arg("email",3,"char *");
+  if(lua_gettop(L)>=4 && !lua_isstring(L,4)) SWIG_fail_arg("email",4,"char *");
+  if(lua_gettop(L)>=5 && !lua_isstring(L,5)) SWIG_fail_arg("email",5,"char *");
+  if(lua_gettop(L)>=6 && !lua_isstring(L,6)) SWIG_fail_arg("email",6,"char *");
+  if(lua_gettop(L)>=7 && !lua_isstring(L,7)) SWIG_fail_arg("email",7,"char *");
+  arg1 = (char *)lua_tostring(L, 1);
+  arg2 = (char *)lua_tostring(L, 2);
+  if(lua_gettop(L)>=3){
+    arg3 = (char *)lua_tostring(L, 3);
+  }
+  if(lua_gettop(L)>=4){
+    arg4 = (char *)lua_tostring(L, 4);
+  }
+  if(lua_gettop(L)>=5){
+    arg5 = (char *)lua_tostring(L, 5);
+  }
+  if(lua_gettop(L)>=6){
+    arg6 = (char *)lua_tostring(L, 6);
+  }
+  if(lua_gettop(L)>=7){
+    arg7 = (char *)lua_tostring(L, 7);
+  }
+  result = (bool)email(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+  SWIG_arg=0;
+  lua_pushboolean(L,(int)(result==true)); SWIG_arg++;
+  return SWIG_arg;
+  
+  if(0) SWIG_fail;
+  
+fail:
+  lua_error(L);
+  return SWIG_arg;
+}
+
+
 static int _wrap_new_IVRMenu(lua_State* L) {
   int SWIG_arg = -1;
   IVRMenu *arg1 = (IVRMenu *) 0 ;
@@ -7525,6 +7574,7 @@ static swig_lua_class _wrap_class_LUA_Dbh = { "Dbh", &SWIGTYPE_p_LUA__Dbh,_wrap_
 static const struct luaL_reg swig_commands[] = {
     { "consoleLog", _wrap_consoleLog},
     { "consoleCleanLog", _wrap_consoleCleanLog},
+    { "email", _wrap_email},
     { "console_log", _wrap_console_log},
     { "console_clean_log", _wrap_console_clean_log},
     { "msleep", _wrap_msleep},
committer: Mathieu Rene
comments: 
Add libjpeg-dev to apt prereqs

diff --git a/support-d/prereq.sh b/support-d/prereq.sh
index 4e214cf..8bc454d 100755
--- a/support-d/prereq.sh
+++ b/support-d/prereq.sh
@@ -2,7 +2,7 @@ UNAME=`uname`
 
 
 NEEDED_PACKAGES_YUM='automake autoconf libtool screen gdb gcc-c++ compat-gcc-32 compat-gcc-32-c++ subversion ncurses-devel unixODBC-devel make wget'
-NEEDED_PACAKGES_APT='automake autoconf libtool screen gdb libncurses5-dev unixodbc-dev subversion emacs22-nox gcc g++ make'
+NEEDED_PACAKGES_APT='automake autoconf libtool screen gdb libncurses5-dev unixodbc-dev subversion emacs22-nox gcc g++ make libjpeg-dev'
 NEEDED_PACKAGES_PKG_ADD=''
 
 
committer: Mathieu Rene
comments: 
Add session.ringReady() to check for CF_RING_READY

diff --git a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
index 1d6ee8d..a818c1d 100644
--- a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
+++ b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
@@ -2126,6 +2126,15 @@ static JSBool session_media_ready(JSContext * cx, JSObject * obj, uintN argc, js
 }
 
 
+static JSBool session_ring_ready(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
+{
+	struct js_session *jss = JS_GetPrivate(cx, obj);
+
+	*rval = BOOLEAN_TO_JSVAL((jss && jss->session && switch_channel_test_flag(switch_core_session_get_channel(jss->session), CF_RING_READY)) ? JS_TRUE : JS_FALSE);
+
+	return JS_TRUE;
+}
+
 static JSBool session_answered(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
 {
 	struct js_session *jss = JS_GetPrivate(cx, obj);
@@ -2673,6 +2682,7 @@ static JSFunctionSpec session_methods[] = {
 	{"ready", session_ready, 0},
 	{"answered", session_answered, 0},
 	{"mediaReady", session_media_ready, 0},
+	{"ringReady", session_ring_ready, 0},
 	{"waitForAnswer", session_wait_for_answer, 0},
 	{"waitForMedia", session_wait_for_media, 0},
 	{"getEvent", session_get_event, 0},
committer: Mathieu Rene
comments: 
xml_config: change min/max enforcements to >= instead of >

diff --git a/src/switch_xml_config.c b/src/switch_xml_config.c
index b6b37bd..5ade057 100644
--- a/src/switch_xml_config.c
+++ b/src/switch_xml_config.c
@@ -177,7 +177,7 @@ SWITCH_DECLARE(switch_status_t) switch_xml_config_parse_event(switch_event_t *ev
 
 					if (int_options) {
 						/* Enforce validation options */
-						if ((int_options->enforce_min && !(intval > int_options->min)) || (int_options->enforce_max && !(intval < int_options->max))) {
+						if ((int_options->enforce_min && !(intval >= int_options->min)) || (int_options->enforce_max && !(intval <= int_options->max))) {
 							/* Validation failed, set default */
 							intval = (int) (intptr_t) item->defaultvalue;
 							/* Then complain */
committer: Leon de Rooij
comments: 
Merge branch 'master' of ssh://git.freeswitch.org/freeswitch
committer: cypromis
comments: 
Merge branch 'master' of ssh://git.freeswitch.org/freeswitch
committer: David Yat Sin
comments: 
chlog: freetdm: isdn: fix for 4ESS call clearing procedures

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 97984fb..5702b72 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
@@ -801,12 +801,14 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm
 						sngisdn_snd_release(ftdmchan, 0);
 						break;
 					case FTDM_CHANNEL_STATE_PROCEED:
-						if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) &&
-							((sngisdn_span_data_t*)(ftdmchan->span->signal_data))->switchtype == SNGISDN_SWITCH_5ESS) {
+						if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
+							if (((sngisdn_span_data_t*)(ftdmchan->span->signal_data))->switchtype == SNGISDN_SWITCH_4ESS ||
+							    ((sngisdn_span_data_t*)(ftdmchan->span->signal_data))->switchtype == SNGISDN_SWITCH_5ESS) {
 							
-							/* When using 5ESS, if the user wants to clear an inbound call, the correct procedure is to send a PROGRESS with in-band info available, and play tones. Then send a DISCONNECT. If we reached this point, it means user did not try to play-tones, so send a RELEASE because remote side does not expect DISCONNECT in state 3 */
-							sngisdn_snd_release(ftdmchan, 0);
-							break;
+								/* When using 5ESS, if the user wants to clear an inbound call, the correct procedure is to send a PROGRESS with in-band info available, and play tones. Then send a DISCONNECT. If we reached this point, it means user did not try to play-tones, so send a RELEASE because remote side does not expect DISCONNECT in state 3 */
+								sngisdn_snd_release(ftdmchan, 0);
+								break;
+							}
 						}
 						/* fall-through */
 					default:
committer: Anthony Minessale
comments: 
nm 40 doesn't work yet

diff --git a/src/mod/codecs/mod_opus/mod_opus.c b/src/mod/codecs/mod_opus/mod_opus.c
index 0234ed8..b9a3120 100644
--- a/src/mod/codecs/mod_opus/mod_opus.c
+++ b/src/mod/codecs/mod_opus/mod_opus.c
@@ -159,7 +159,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load)
 
 	SWITCH_ADD_CODEC(codec_interface, "OPUS (BETA 0.9.0)");
 
-	for (x = 0; x < 3; x++) {
+	for (x = 0; x < 2; x++) {
 		switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,	/* enumeration defining the type of the codec */
 											 115,	/* the IANA code number */
 											 "Opus-0.9.0",/* the IANA code name */
committer: Anthony Minessale
comments: 
add 10 20 and 40ms

diff --git a/src/mod/codecs/mod_opus/mod_opus.c b/src/mod/codecs/mod_opus/mod_opus.c
index ddb5a7a..0234ed8 100644
--- a/src/mod/codecs/mod_opus/mod_opus.c
+++ b/src/mod/codecs/mod_opus/mod_opus.c
@@ -147,52 +147,43 @@ static switch_status_t switch_opus_decode(switch_codec_t *codec,
 SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load)
 {
 	switch_codec_interface_t *codec_interface;
+	int samples = 80;
+	int bytes = 960;
+	int mss = 10000;
+	int x = 0;
+	int rate = 48000;
+	int bits = 32000;
 
 	/* connect my internal structure to the blank pointer passed to me */
 	*module_interface = switch_loadable_module_create_module_interface(pool, modname);
 
 	SWITCH_ADD_CODEC(codec_interface, "OPUS (BETA 0.9.0)");
 
-	switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,	/* enumeration defining the type of the codec */
-										 115,	/* the IANA code number */
-										 "Opus-0.9.0",/* the IANA code name */
-										 NULL,	/* default fmtp to send (can be overridden by the init function) */
-										 48000,	/* samples transferred per second */
-										 48000,	/* actual samples transferred per second */
-										 32000,	/* bits transferred per second */
-										 10000,	/* number of microseconds per frame */
-										 80,	/* number of samples per frame */
-										 960,	/* 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_opus_init,	/* function to initialize a codec handle using this implementation */
-										 switch_opus_encode,	/* function to encode raw data into encoded data */
-										 switch_opus_decode,	/* function to decode encoded data into raw data */
-										 switch_opus_destroy);	/* deinitalize a codec handle using this implementation */
-
-
-	switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,	/* enumeration defining the type of the codec */
-										 115,	/* the IANA code number */
-										 "Opus-0.9.0",	/* the IANA code name */
-										 NULL,	/* default fmtp to send (can be overridden by the init function) */
-										 48000,	/* samples transferred per second */
-										 48000,	/* actual samples transferred per second */
-										 32000,	/* bits transferred per second */
-										 20000,	/* number of microseconds per frame */
-										 160,	/* number of samples per frame */
-										 1920,	/* 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_opus_init,	/* function to initialize a codec handle using this implementation */
-										 switch_opus_encode,	/* function to encode raw data into encoded data */
-										 switch_opus_decode,	/* function to decode encoded data into raw data */
-										 switch_opus_destroy);	/* deinitalize a codec handle using this implementation */
-
-
-
+	for (x = 0; x < 3; x++) {
+		switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,	/* enumeration defining the type of the codec */
+											 115,	/* the IANA code number */
+											 "Opus-0.9.0",/* the IANA code name */
+											 NULL,	/* default fmtp to send (can be overridden by the init function) */
+											 rate,	/* samples transferred per second */
+											 rate,	/* actual samples transferred per second */
+											 bits,	/* bits transferred per second */
+											 mss,	/* number of microseconds per frame */
+											 samples,	/* number of samples per frame */
+											 bytes,	/* 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_opus_init,	/* function to initialize a codec handle using this implementation */
+											 switch_opus_encode,	/* function to encode raw data into encoded data */
+											 switch_opus_decode,	/* function to decode encoded data into raw data */
+											 switch_opus_destroy);	/* deinitalize a codec handle using this implementation */
+		
+		bytes *= 2;
+		samples *= 2;
+		mss *= 2;
 
+	}
+	
 	/* indicate that the module should continue to be loaded */
 	return SWITCH_STATUS_SUCCESS;
 }
committer: Anthony Minessale
comments: 
change signalling name to avoid polluting the namespace before its ready

diff --git a/src/mod/codecs/mod_opus/mod_opus.c b/src/mod/codecs/mod_opus/mod_opus.c
index 341254f..ddb5a7a 100644
--- a/src/mod/codecs/mod_opus/mod_opus.c
+++ b/src/mod/codecs/mod_opus/mod_opus.c
@@ -151,11 +151,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load)
 	/* connect my internal structure to the blank pointer passed to me */
 	*module_interface = switch_loadable_module_create_module_interface(pool, modname);
 
-	SWITCH_ADD_CODEC(codec_interface, "OPUS (BETA)");
+	SWITCH_ADD_CODEC(codec_interface, "OPUS (BETA 0.9.0)");
 
 	switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,	/* enumeration defining the type of the codec */
 										 115,	/* the IANA code number */
-										 "OPUS",	/* the IANA code name */
+										 "Opus-0.9.0",/* the IANA code name */
 										 NULL,	/* default fmtp to send (can be overridden by the init function) */
 										 48000,	/* samples transferred per second */
 										 48000,	/* actual samples transferred per second */
@@ -174,7 +174,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load)
 
 	switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,	/* enumeration defining the type of the codec */
 										 115,	/* the IANA code number */
-										 "OPUS",	/* the IANA code name */
+										 "Opus-0.9.0",	/* the IANA code name */
 										 NULL,	/* default fmtp to send (can be overridden by the init function) */
 										 48000,	/* samples transferred per second */
 										 48000,	/* actual samples transferred per second */
committer: Anthony Minessale
comments: 
add mod_opus

diff --git a/build/modules.conf.in b/build/modules.conf.in
index 84a9e9a..8d3dfaa 100644
--- a/build/modules.conf.in
+++ b/build/modules.conf.in
@@ -48,6 +48,7 @@ codecs/mod_ilbc
 codecs/mod_speex
 codecs/mod_siren
 #codecs/mod_celt
+#codecs/mod_opus
 #codecs/mod_sangoma_codec
 #codecs/mod_dahdi_codec
 #dialplans/mod_dialplan_directory
diff --git a/conf/autoload_configs/modules.conf.xml b/conf/autoload_configs/modules.conf.xml
index 2e7ebfa..8b4a4e7 100644
--- a/conf/autoload_configs/modules.conf.xml
+++ b/conf/autoload_configs/modules.conf.xml
@@ -78,6 +78,7 @@
     <load module="mod_h26x"/>
     <load module="mod_siren"/>
     <!--<load module="mod_celt"/>-->
+    <!--<load module="mod_opus"/>-->
 
     <!-- File Format Interfaces -->
     <load module="mod_sndfile"/>
diff --git a/src/mod/codecs/mod_opus/Makefile b/src/mod/codecs/mod_opus/Makefile
new file mode 100644
index 0000000..a346956
--- /dev/null
+++ b/src/mod/codecs/mod_opus/Makefile
@@ -0,0 +1,28 @@
+BASE=../../../..
+
+OPUS=opus-0.9.0
+
+OPUS_DIR=$(switch_srcdir)/libs/$(OPUS)
+OPUS_BUILDDIR=$(switch_builddir)/libs/$(OPUS)
+LOCAL_CFLAGS=-I$(OPUS_DIR)/src -g -O2
+
+IETF_LA=$(OPUS_BUILDDIR)/src/.libs/libietfcodec.a
+CELT_LA=$(OPUS_BUILDDIR)/celt/libcelt/.libs/libcelt0.a
+SILK_LA=$(OPUS_BUILDDIR)/silk/.libs/libSKP_SILK_SDK.a
+
+LOCAL_LIBADD=$(IETF_LA) $(CELT_LA) $(SILK_LA) -lm -lz
+
+include $(BASE)/build/modmake.rules
+
+$(OPUS_DIR):
+	$(GETLIB) $(OPUS).tar.gz
+
+$(OPUS_BUILDDIR)/Makefile: $(OPUS_DIR)
+	mkdir -p $(OPUS_BUILDDIR)
+	cd $(OPUS_BUILDDIR) && $(DEFAULT_VARS) $(OPUS_DIR)/configure --disable-shared --with-pic --srcdir=$(OPUS_DIR)
+	$(TOUCH_TARGET)
+
+$(IETF_LA): $(OPUS_BUILDDIR)/Makefile
+	cd $(OPUS_BUILDDIR) && $(MAKE)
+	$(TOUCH_TARGET)
+
diff --git a/src/mod/codecs/mod_opus/mod_opus.c b/src/mod/codecs/mod_opus/mod_opus.c
new file mode 100644
index 0000000..341254f
--- /dev/null
+++ b/src/mod/codecs/mod_opus/mod_opus.c
@@ -0,0 +1,209 @@
+/* 
+ * 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):
+ * 
+ * Brian K. West <brian@freeswitch.org>
+ *
+ * mod_opus.c -- The OPUS ultra-low delay audio codec (http://www.opus-codec.org/)
+ *
+ */
+
+#include "switch.h"
+#include "opus.h"
+
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load);
+SWITCH_MODULE_DEFINITION(mod_opus, mod_opus_load, NULL, NULL);
+
+struct opus_context {
+	OpusEncoder *encoder_object;
+	OpusDecoder *decoder_object;
+	int frame_size;
+};
+
+static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
+{
+	struct opus_context *context = NULL;
+	int encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
+	int decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
+
+	if (!(encoding || decoding) || (!(context = switch_core_alloc(codec->memory_pool, sizeof(*context))))) {
+		return SWITCH_STATUS_FALSE;
+	}
+
+	context->frame_size = codec->implementation->samples_per_packet;
+	
+	if (encoding) {
+		/* come up with a way to specify these */
+		int bitrate_bps = codec->implementation->bits_per_second;
+		int mode = MODE_HYBRID;
+		int use_vbr = 1;
+		int complexity = 10;
+		int use_inbandfec = 1;
+		int use_dtx = 1;
+		int bandwidth = BANDWIDTH_FULLBAND;
+
+		context->encoder_object = opus_encoder_create(codec->implementation->actual_samples_per_second, codec->implementation->number_of_channels);
+
+		opus_encoder_ctl(context->encoder_object, OPUS_SET_MODE(mode));
+		opus_encoder_ctl(context->encoder_object, OPUS_SET_BITRATE(bitrate_bps));
+		opus_encoder_ctl(context->encoder_object, OPUS_SET_BANDWIDTH(bandwidth));
+		opus_encoder_ctl(context->encoder_object, OPUS_SET_VBR_FLAG(use_vbr));
+		opus_encoder_ctl(context->encoder_object, OPUS_SET_COMPLEXITY(complexity));
+		opus_encoder_ctl(context->encoder_object, OPUS_SET_INBAND_FEC_FLAG(use_inbandfec));
+		opus_encoder_ctl(context->encoder_object, OPUS_SET_DTX_FLAG(use_dtx));
+
+	}
+	
+	if (decoding) {
+		context->decoder_object = opus_decoder_create(codec->implementation->actual_samples_per_second, codec->implementation->number_of_channels);
+	}
+
+	codec->private_info = context;
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t switch_opus_destroy(switch_codec_t *codec)
+{
+	codec->private_info = NULL;
+	return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t switch_opus_encode(switch_codec_t *codec,
+										  switch_codec_t *other_codec,
+										  void *decoded_data,
+										  uint32_t decoded_data_len,
+										  uint32_t decoded_rate, void *encoded_data, uint32_t *encoded_data_len, uint32_t *encoded_rate,
+										  unsigned int *flag)
+{
+	struct opus_context *context = codec->private_info;
+	int bytes = 0;
+	int len = (int) *encoded_data_len;
+
+	if (!context) {
+		return SWITCH_STATUS_FALSE;
+	}
+
+	if (len > 1275) len = 1275;
+
+	bytes = opus_encode(context->encoder_object, (void *) decoded_data, decoded_data_len / 2, (unsigned char *) encoded_data, len);
+	
+	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_opus_decode(switch_codec_t *codec,
+										  switch_codec_t *other_codec,
+										  void *encoded_data,
+										  uint32_t encoded_data_len,
+										  uint32_t encoded_rate, void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate,
+										  unsigned int *flag)
+{
+	struct opus_context *context = codec->private_info;
+	int samples = 0;
+
+	if (!context) {
+		return SWITCH_STATUS_FALSE;
+	}
+	
+	samples = opus_decode(context->decoder_object, encoded_data, encoded_data_len, decoded_data, *decoded_data_len);
+
+	if (samples < 0) {
+		return SWITCH_STATUS_GENERR;
+	}
+
+	*decoded_data_len = samples * 2;
+	
+	return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load)
+{
+	switch_codec_interface_t *codec_interface;
+
+	/* connect my internal structure to the blank pointer passed to me */
+	*module_interface = switch_loadable_module_create_module_interface(pool, modname);
+
+	SWITCH_ADD_CODEC(codec_interface, "OPUS (BETA)");
+
+	switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,	/* enumeration defining the type of the codec */
+										 115,	/* the IANA code number */
+										 "OPUS",	/* the IANA code name */
+										 NULL,	/* default fmtp to send (can be overridden by the init function) */
+										 48000,	/* samples transferred per second */
+										 48000,	/* actual samples transferred per second */
+										 32000,	/* bits transferred per second */
+										 10000,	/* number of microseconds per frame */
+										 80,	/* number of samples per frame */
+										 960,	/* 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_opus_init,	/* function to initialize a codec handle using this implementation */
+										 switch_opus_encode,	/* function to encode raw data into encoded data */
+										 switch_opus_decode,	/* function to decode encoded data into raw data */
+										 switch_opus_destroy);	/* deinitalize a codec handle using this implementation */
+
+
+	switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,	/* enumeration defining the type of the codec */
+										 115,	/* the IANA code number */
+										 "OPUS",	/* the IANA code name */
+										 NULL,	/* default fmtp to send (can be overridden by the init function) */
+										 48000,	/* samples transferred per second */
+										 48000,	/* actual samples transferred per second */
+										 32000,	/* bits transferred per second */
+										 20000,	/* number of microseconds per frame */
+										 160,	/* number of samples per frame */
+										 1920,	/* 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_opus_init,	/* function to initialize a codec handle using this implementation */
+										 switch_opus_encode,	/* function to encode raw data into encoded data */
+										 switch_opus_decode,	/* function to decode encoded data into raw data */
+										 switch_opus_destroy);	/* deinitalize a codec handle using this implementation */
+
+
+
+
+	/* indicate that the module should continue to be loaded */
+	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:
+ */
committer: Christopher Rienzo
comments: 
forgot this spot when closing speech channel

diff --git a/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c b/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c
index 812744c..734ef21 100644
--- a/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c
+++ b/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c
@@ -1362,6 +1362,8 @@ static switch_status_t speech_channel_stop(speech_channel_t *schannel)
 			goto done;
 		}
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) %s stopped\n", schannel->name, speech_channel_type_to_string(schannel->type));
+	} else if (schannel->state == SPEECH_CHANNEL_DONE) {
+		speech_channel_set_state(schannel, SPEECH_CHANNEL_READY);
 	}
 
   done:
committer: Christopher Rienzo
comments: 
FS-3201 fix truncated TTS

diff --git a/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c b/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c
index 5db1491..812744c 100644
--- a/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c
+++ b/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c
@@ -260,6 +260,7 @@ static switch_status_t audio_queue_create(audio_queue_t ** queue, const char *na
 static switch_status_t audio_queue_write(audio_queue_t *queue, void *data, switch_size_t *data_len);
 static switch_status_t audio_queue_read(audio_queue_t *queue, void *data, switch_size_t *data_len, int block);
 static switch_status_t audio_queue_clear(audio_queue_t *queue);
+static switch_status_t audio_queue_signal(audio_queue_t *queue);
 static switch_status_t audio_queue_destroy(audio_queue_t *queue);
 
 /*********************************************************************************************************************************************
@@ -287,6 +288,8 @@ enum speech_channel_state {
 	SPEECH_CHANNEL_READY,
 	/** processing speech request */
 	SPEECH_CHANNEL_PROCESSING,
+	/** finished processing speech request */
+	SPEECH_CHANNEL_DONE,
 	/** error opening channel */
 	SPEECH_CHANNEL_ERROR
 };
@@ -667,10 +670,12 @@ static switch_status_t audio_queue_create(audio_queue_t ** audio_queue, const ch
 static switch_status_t audio_queue_write(audio_queue_t *queue, void *data, switch_size_t *data_len)
 {
 	switch_status_t status = SWITCH_STATUS_SUCCESS;
+#ifdef MOD_UNIMRCP_DEBUG_AUDIO_QUEUE
+	switch_size_t len = *data_len;
+#endif
 	switch_mutex_lock(queue->mutex);
 
 #ifdef MOD_UNIMRCP_DEBUG_AUDIO_QUEUE
-	switch_size_t len = *data_len;
 	if (queue->file_write) {
 		switch_file_write(queue->file_write, data, &len);
 	}
@@ -708,6 +713,9 @@ static switch_status_t audio_queue_read(audio_queue_t *queue, void *data, switch
 {
 	switch_size_t requested = *data_len;
 	switch_status_t status = SWITCH_STATUS_SUCCESS;
+#ifdef MOD_UNIMRCP_DEBUG_AUDIO_QUEUE
+	switch_size_t len = *data_len;
+#endif
 	switch_mutex_lock(queue->mutex);
 
 	/* wait for data, if allowed */
@@ -736,7 +744,6 @@ static switch_status_t audio_queue_read(audio_queue_t *queue, void *data, switch
 #ifdef MOD_UNIMRCP_DEBUG_AUDIO_QUEUE
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) audio queue read total = %ld\tread = %ld\trequested = %ld\n", queue->name,
 					  queue->read_bytes, *data_len, requested);
-	switch_size_t len = *data_len;
 	if (queue->file_read) {
 		switch_file_write(queue->file_read, data, &len);
 	}
@@ -764,6 +771,20 @@ static switch_status_t audio_queue_clear(audio_queue_t *queue)
 }
 
 /**
+ * Wake any threads waiting on this queue
+ *
+ * @param queue the queue to empty
+ * @return SWITCH_STATUS_SUCCESS
+ */
+static switch_status_t audio_queue_signal(audio_queue_t *queue)
+{
+	switch_mutex_lock(queue->mutex);
+	switch_thread_cond_signal(queue->cond);
+	switch_mutex_unlock(queue->mutex);
+	return SWITCH_STATUS_SUCCESS;
+}
+
+/**
  * Destroy the audio queue
  *
  * @param queue the queue to clean up
@@ -1438,9 +1459,19 @@ static switch_status_t speech_channel_read(speech_channel_t *schannel, void *dat
 	}
 
 	switch_mutex_lock(schannel->mutex);
-	if (schannel->state == SPEECH_CHANNEL_PROCESSING) {
+	switch (schannel->state) {
+	case SPEECH_CHANNEL_DONE:
+		/* pull any remaining audio - never blocking */
+		if (audio_queue_read(schannel->audio_queue, data, len, 0) == SWITCH_STATUS_FALSE) {
+			/* all frames read */
+			status = SWITCH_STATUS_BREAK;
+		}
+		break;
+	case SPEECH_CHANNEL_PROCESSING:
+		/* IN-PROGRESS */
 		audio_queue_read(schannel->audio_queue, data, len, block);
-	} else {
+		break;
+	default:
 		status = SWITCH_STATUS_BREAK;
 	}
 	switch_mutex_unlock(schannel->mutex);
@@ -1463,6 +1494,8 @@ static const char *speech_channel_state_to_string(speech_channel_state_t state)
 		return "READY";
 	case SPEECH_CHANNEL_PROCESSING:
 		return "PROCESSING";
+	case SPEECH_CHANNEL_DONE:
+		return "DONE";
 	case SPEECH_CHANNEL_ERROR:
 		return "ERROR";
 	}
@@ -1498,7 +1531,7 @@ static switch_status_t speech_channel_set_state_unlocked(speech_channel_t *schan
 {
 	if (schannel->state == SPEECH_CHANNEL_PROCESSING && state != SPEECH_CHANNEL_PROCESSING) {
 		/* wake anyone waiting for audio data */
-		audio_queue_clear(schannel->audio_queue);
+		audio_queue_signal(schannel->audio_queue);
 	}
 
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) %s ==> %s\n", schannel->name, speech_channel_state_to_string(schannel->state),
@@ -1651,6 +1684,8 @@ static switch_status_t synth_speech_read_tts(switch_speech_handle_t *sh, void *d
 			memset((uint8_t *) data + bytes_read, schannel->silence, *datalen - bytes_read);
 		}
 	} else {
+		/* ready for next speak request */
+		speech_channel_set_state(schannel, SPEECH_CHANNEL_READY);
 		*datalen = 0;
 		status = SWITCH_STATUS_BREAK;
 	}
@@ -1878,7 +1913,7 @@ static apt_bool_t synth_on_message_receive(mrcp_application_t *application, mrcp
 			if (message->start_line.request_state == MRCP_REQUEST_STATE_COMPLETE) {
 				/* got COMPLETE */
 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) COMPLETE\n", schannel->name);
-				speech_channel_set_state(schannel, SPEECH_CHANNEL_READY);
+				speech_channel_set_state(schannel, SPEECH_CHANNEL_DONE);
 			} else {
 				/* received unexpected request state */
 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) unexpected STOP response, request_state = %d\n", schannel->name,
@@ -1896,7 +1931,7 @@ static apt_bool_t synth_on_message_receive(mrcp_application_t *application, mrcp
 		if (message->start_line.method_id == SYNTHESIZER_SPEAK_COMPLETE) {
 			/* got SPEAK-COMPLETE */
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) SPEAK-COMPLETE\n", schannel->name);
-			speech_channel_set_state(schannel, SPEECH_CHANNEL_READY);
+			speech_channel_set_state(schannel, SPEECH_CHANNEL_DONE);
 		} else {
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) unexpected event, method_id = %d\n", schannel->name,
 							  (int) message->start_line.method_id);
committer: Anthony Minessale
comments: 
add default to conf to demonstrate min-idle-cpu

diff --git a/conf/autoload_configs/switch.conf.xml b/conf/autoload_configs/switch.conf.xml
index 8342f12..32cb76f 100644
--- a/conf/autoload_configs/switch.conf.xml
+++ b/conf/autoload_configs/switch.conf.xml
@@ -23,6 +23,10 @@
   <settings>
     <!--Colorize the Console -->
     <param name="colorize-console" value="true"/>
+
+    <!-- minimum idle CPU before refusing calls -->
+    <param name="min-idle-cpu" value="25"/>
+
     <!--
 	Max number of sessions to allow at any given time.
 	
committer: Anthony Minessale
comments: 
fix sql err

diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c
index a38a61e..2313cb7 100644
--- a/src/mod/endpoints/mod_sofia/sofia_presence.c
+++ b/src/mod/endpoints/mod_sofia/sofia_presence.c
@@ -2576,7 +2576,7 @@ uint32_t sofia_presence_contact_count(sofia_profile_t *profile, const char *cont
 	char buf[32] = "";
 	char *sql;
 	
-	sql = switch_mprintf("select count(*) from sip_subscriptions where profile_name='%q' and contact_str='%q'", profile->name, contact_str);
+	sql = switch_mprintf("select count(*) from sip_subscriptions where profile_name='%q' and contact='%q'", profile->name, contact_str);
 	
 	sofia_glue_execute_sql2str(profile, profile->ireg_mutex, sql, buf, sizeof(buf));
 	switch_safe_free(sql);
committer: Jeff Lenk
comments: 
FS-3033 VS2010 libportaudio project improvements for DirectX builds and switch to build DirectX by default

diff --git a/Freeswitch.2010.sln b/Freeswitch.2010.sln
index edee701..464cb2e 100644
--- a/Freeswitch.2010.sln
+++ b/Freeswitch.2010.sln
@@ -1569,18 +1569,18 @@ Global
 		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.All|x64 Setup.ActiveCfg = Release DirectSound|x64
 		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.All|x64 Setup.Build.0 = Release DirectSound|x64
 		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.All|x86 Setup.ActiveCfg = Release DirectSound|x64
-		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|Win32.ActiveCfg = Debug|Win32
-		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|Win32.Build.0 = Debug|Win32
-		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x64.ActiveCfg = Debug|x64
-		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x64.Build.0 = Debug|x64
-		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x64 Setup.ActiveCfg = Debug|x64
-		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x86 Setup.ActiveCfg = Debug|Win32
-		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|Win32.ActiveCfg = Release|Win32
-		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|Win32.Build.0 = Release|Win32
-		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x64.ActiveCfg = Release|x64
-		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x64.Build.0 = Release|x64
-		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x64 Setup.ActiveCfg = Release|x64
-		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x86 Setup.ActiveCfg = Release|Win32
+		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|Win32.ActiveCfg = Debug DirectSound|Win32
+		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|Win32.Build.0 = Debug DirectSound|Win32
+		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x64.ActiveCfg = Debug DirectSound|x64
+		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x64.Build.0 = Debug DirectSound|x64
+		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x64 Setup.ActiveCfg = Debug DirectSound|x64
+		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x86 Setup.ActiveCfg = Debug DirectSound|Win32
+		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|Win32.ActiveCfg = Release DirectSound|Win32
+		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|Win32.Build.0 = Release DirectSound|Win32
+		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x64.ActiveCfg = Release DirectSound|x64
+		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x64.Build.0 = Release DirectSound|x64
+		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x64 Setup.ActiveCfg = Release DirectSound|x64
+		{0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x86 Setup.ActiveCfg = Release DirectSound|Win32
 		{08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.All|Win32.ActiveCfg = Release|x64
 		{08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.All|x64.ActiveCfg = Release|x64
 		{08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.All|x64.Build.0 = Release|x64
diff --git a/libs/portaudio/build/msvc/portaudio.2010.vcxproj b/libs/portaudio/build/msvc/portaudio.2010.vcxproj
index b4eca56..10b4c25 100644
--- a/libs/portaudio/build/msvc/portaudio.2010.vcxproj
+++ b/libs/portaudio/build/msvc/portaudio.2010.vcxproj
@@ -41,11 +41,11 @@
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'" Label="Configuration">
-    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <ConfigurationType>StaticLibrary</ConfigurationType>
     <UseOfMfc>false</UseOfMfc>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'" Label="Configuration">
-    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <ConfigurationType>StaticLibrary</ConfigurationType>
     <UseOfMfc>false</UseOfMfc>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@@ -57,11 +57,11 @@
     <UseOfMfc>false</UseOfMfc>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'" Label="Configuration">
-    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <ConfigurationType>StaticLibrary</ConfigurationType>
     <UseOfMfc>false</UseOfMfc>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'" Label="Configuration">
-    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <ConfigurationType>StaticLibrary</ConfigurationType>
     <UseOfMfc>false</UseOfMfc>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@@ -77,9 +77,11 @@
   </ImportGroup>
   <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'" Label="PropertySheets">
     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="..\..\..\..\w32\extlib.props" />
   </ImportGroup>
   <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'" Label="PropertySheets">
     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="..\..\..\..\w32\extlib.props" />
   </ImportGroup>
   <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
@@ -92,10 +94,12 @@
   <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'" Label="PropertySheets">
     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
     <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+    <Import Project="..\..\..\..\w32\extlib.props" />
   </ImportGroup>
   <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'" Label="PropertySheets">
     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
     <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+    <Import Project="..\..\..\..\w32\extlib.props" />
   </ImportGroup>
   <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
@@ -110,18 +114,6 @@
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup>
     <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">$(Configuration)\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">$(Configuration)\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">true</LinkIncremental>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">$(Platform)\$(Configuration)\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">$(Platform)\$(Configuration)\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">true</LinkIncremental>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">$(Configuration)\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">$(Configuration)\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">false</LinkIncremental>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">$(Platform)\$(Configuration)\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">$(Platform)\$(Configuration)\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">false</LinkIncremental>
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <Midl>
@@ -231,45 +223,23 @@
       <MkTypLibCompatible>true</MkTypLibCompatible>
       <SuppressStartupBanner>true</SuppressStartupBanner>
       <TargetEnvironment>Win32</TargetEnvironment>
-      <TypeLibraryName>.\Debug_x86/portaudio.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
     </Midl>
     <ClCompile>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>..\..\src\common;..\..\include;.\;..\..\src\os\win;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_USRDLL;PA_ENABLE_DEBUG_OUTPUT;_CRT_SECURE_NO_DEPRECATE;PA_NO_ASIO;PAWIN_USE_WDMKS_DEVICE_INFO;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_USRDLL;PA_ENABLE_DEBUG_OUTPUT;_CRT_SECURE_NO_DEPRECATE;PA_NO_ASIO;PA_NO_WMME;PAWIN_USE_WDMKS_DEVICE_INFO;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <MinimalRebuild>true</MinimalRebuild>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>$(Platform)\$(Configuration)/portaudio.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>$(Platform)\$(Configuration)\</AssemblerListingLocation>
-      <ObjectFileName>$(Platform)\$(Configuration)\</ObjectFileName>
-      <ProgramDataBaseFileName>$(Platform)\$(Configuration)\</ProgramDataBaseFileName>
       <WarningLevel>Level3</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
     </ClCompile>
     <ResourceCompile>
       <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <Culture>0x0409</Culture>
     </ResourceCompile>
-    <Link>
-      <AdditionalDependencies>ksuser.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <OutputFile>$(Platform)\$(Configuration)\portaudio_x86.dll</OutputFile>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <ModuleDefinitionFile>.\portaudio.def</ModuleDefinitionFile>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>$(Platform)\$(Configuration)\portaudio_x86.pdb</ProgramDatabaseFile>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <ImportLibrary>$(Platform)\$(Configuration)\portaudio_x86.lib</ImportLibrary>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
     <Bscmake>
       <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>$(Platform)\$(Configuration)\portaudio.bsc</OutputFile>
     </Bscmake>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">
@@ -278,45 +248,23 @@
       <MkTypLibCompatible>true</MkTypLibCompatible>
       <SuppressStartupBanner>true</SuppressStartupBanner>
       <TargetEnvironment>X64</TargetEnvironment>
-      <TypeLibraryName>.\Debug_x86/portaudio.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
     </Midl>
     <ClCompile>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>..\..\src\common;..\..\include;.\;..\..\src\os\win;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_USRDLL;PA_ENABLE_DEBUG_OUTPUT;_CRT_SECURE_NO_DEPRECATE;PAWIN_USE_WDMKS_DEVICE_INFO;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_USRDLL;PA_ENABLE_DEBUG_OUTPUT;_CRT_SECURE_NO_DEPRECATE;PA_NO_ASIO;PA_NO_WMME;PAWIN_USE_WDMKS_DEVICE_INFO;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <MinimalRebuild>true</MinimalRebuild>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>$(Platform)\$(Configuration)\portaudio.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>$(Platform)\$(Configuration)\</AssemblerListingLocation>
-      <ObjectFileName>$(Platform)\$(Configuration)\</ObjectFileName>
-      <ProgramDataBaseFileName>$(Platform)\$(Configuration)\</ProgramDataBaseFileName>
       <WarningLevel>Level3</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
     </ClCompile>
     <ResourceCompile>
       <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <Culture>0x0409</Culture>
     </ResourceCompile>
-    <Link>
-      <AdditionalDependencies>ksuser.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <OutputFile>$(Platform)\$(Configuration)\portaudio_x64.dll</OutputFile>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <ModuleDefinitionFile>.\portaudio.def</ModuleDefinitionFile>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>$(Platform)\$(Configuration)/portaudio_x64.pdb</ProgramDatabaseFile>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <ImportLibrary>$(Platform)\$(Configuration)\portaudio_x64.lib</ImportLibrary>
-      <TargetMachine>MachineX64</TargetMachine>
-    </Link>
     <Bscmake>
       <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>$(Platform)\$(Configuration)/portaudio_x64.bsc</OutputFile>
     </Bscmake>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">
@@ -325,22 +273,15 @@
       <MkTypLibCompatible>true</MkTypLibCompatible>
       <SuppressStartupBanner>true</SuppressStartupBanner>
       <TargetEnvironment>Win32</TargetEnvironment>
-      <TypeLibraryName>.\Release_x86/portaudio.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
     </Midl>
     <ClCompile>
       <Optimization>MaxSpeed</Optimization>
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+      <InlineFunctionExpansion>Default</InlineFunctionExpansion>
       <AdditionalIncludeDirectories>..\..\src\common;..\..\include;.\;..\..\src\os\win;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_USRDLL;PA_ENABLE_DEBUG_OUTPUT;_CRT_SECURE_NO_DEPRECATE;PA_NO_ASIO;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_USRDLL;PA_ENABLE_DEBUG_OUTPUT;_CRT_SECURE_NO_DEPRECATE;PA_NO_ASIO;PA_NO_WMME;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>$(Platform)\$(Configuration)/portaudio.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>$(Platform)\$(Configuration)\</AssemblerListingLocation>
-      <ObjectFileName>$(Platform)\$(Configuration)\</ObjectFileName>
-      <ProgramDataBaseFileName>$(Platform)\$(Configuration)\</ProgramDataBaseFileName>
       <WarningLevel>Level3</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
     </ClCompile>
@@ -348,20 +289,8 @@
       <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <Culture>0x0409</Culture>
     </ResourceCompile>
-    <Link>
-      <OutputFile>$(Platform)\$(Configuration)\portaudio_x86.dll</OutputFile>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <ModuleDefinitionFile>.\portaudio.def</ModuleDefinitionFile>
-      <ProgramDatabaseFile>$(Platform)\$(Configuration)\portaudio_x86.pdb</ProgramDatabaseFile>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <ImportLibrary>$(Platform)\$(Configuration)\portaudio_x86.lib</ImportLibrary>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
     <Bscmake>
       <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>$(Platform)\$(Configuration)\portaudio.bsc</OutputFile>
     </Bscmake>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">
@@ -370,22 +299,15 @@
       <MkTypLibCompatible>true</MkTypLibCompatible>
       <SuppressStartupBanner>true</SuppressStartupBanner>
       <TargetEnvironment>X64</TargetEnvironment>
-      <TypeLibraryName>.\Release_x86/portaudio.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
     </Midl>
     <ClCompile>
       <Optimization>MaxSpeed</Optimization>
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>..\..\src\common;..\..\include;.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_USRDLL;PA_ENABLE_DEBUG_OUTPUT;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <InlineFunctionExpansion>Default</InlineFunctionExpansion>
+      <AdditionalIncludeDirectories>..\..\src\common;..\..\include;.\;..\..\src\os\win;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_USRDLL;PA_ENABLE_DEBUG_OUTPUT;_CRT_SECURE_NO_DEPRECATE;PA_NO_ASIO;PA_NO_WMME;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>$(Platform)\$(Configuration)\portaudio.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>$(Platform)\$(Configuration)\</AssemblerListingLocation>
-      <ObjectFileName>$(Platform)\$(Configuration)\</ObjectFileName>
-      <ProgramDataBaseFileName>$(Platform)\$(Configuration)\</ProgramDataBaseFileName>
       <WarningLevel>Level3</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
     </ClCompile>
@@ -393,20 +315,8 @@
       <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <Culture>0x0409</Culture>
     </ResourceCompile>
-    <Link>
-      <OutputFile>$(Platform)\$(Configuration)\portaudio_x64.dll</OutputFile>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <ModuleDefinitionFile>.\portaudio.def</ModuleDefinitionFile>
-      <ProgramDatabaseFile>$(Platform)\$(Configuration)/portaudio_x64.pdb</ProgramDatabaseFile>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <ImportLibrary>$(Platform)\$(Configuration)/portaudio_x64.lib</ImportLibrary>
-      <TargetMachine>MachineX64</TargetMachine>
-    </Link>
     <Bscmake>
       <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>$(Platform)\$(Configuration)\portaudio_x64.bsc</OutputFile>
     </Bscmake>
   </ItemDefinitionGroup>
   <ItemGroup>
@@ -594,6 +504,7 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
@@ -605,6 +516,7 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -618,6 +530,7 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
@@ -629,6 +542,7 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -642,6 +556,7 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
@@ -653,6 +568,7 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -666,6 +582,7 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
@@ -677,6 +594,7 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -690,6 +608,7 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
@@ -701,6 +620,7 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -714,6 +634,7 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
@@ -725,6 +646,7 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -738,6 +660,7 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
@@ -749,6 +672,7 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -762,6 +686,7 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug DirectSound|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
@@ -773,6 +698,7 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">true</ExcludedFromBuild>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release DirectSound|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
committer: Anthony Minessale
comments: 
add sanity check on jitterbuffer debug

diff --git a/src/switch_rtp.c b/src/switch_rtp.c
index e8d7558..4df867a 100644
--- a/src/switch_rtp.c
+++ b/src/switch_rtp.c
@@ -1875,6 +1875,10 @@ static void jb_logger(const char *file, const char *func, int line, int level, c
 SWITCH_DECLARE(switch_status_t) switch_rtp_debug_jitter_buffer(switch_rtp_t *rtp_session, const char *name)
 {
 
+	if (!switch_rtp_ready(rtp_session)) {
+		return SWITCH_STATUS_FALSE;
+	}
+	
 	stfu_n_debug(rtp_session->jb, name);
 	stfu_global_set_logger(jb_logger);
 
committer: Anthony Minessale
comments: 
skip blocking writes on fs_cli to avoid backing up event socket

diff --git a/libs/esl/fs_cli.c b/libs/esl/fs_cli.c
index 19e8d7f..a70d63f 100644
--- a/libs/esl/fs_cli.c
+++ b/libs/esl/fs_cli.c
@@ -589,22 +589,36 @@ static void *msg_thread_run(esl_thread_t *me, void *obj)
 
 	while(thread_running && handle->connected) {
 		esl_status_t status = esl_recv_event_timed(handle, 10, 1, NULL);
-
-		if (WARN_STOP) {
-			printf("Type control-D or /exit or /quit or /bye to exit.\n\n");
-			WARN_STOP = 0;
-		}
+		int aok = 1;		
 
 		if (status == ESL_FAIL) {
-			esl_log(ESL_LOG_WARNING, "Disconnected.\n");
+			if (aok) esl_log(ESL_LOG_WARNING, "Disconnected.\n");
 			running = -1; thread_running = 0;
 		} else if (status == ESL_SUCCESS) {
+#ifndef WIN32
+			fd_set can_write;
+			int fd;
+			struct timeval to;
+
+			fd = fileno(stdout);
+			memset(&to, 0, sizeof(to));
+			FD_ZERO(&can_write);
+			FD_SET(fd, &can_write);
+			to.tv_sec = 0;
+			to.tv_usec = 100000;
+			if (select(fd + 1, NULL, &can_write, NULL, &to) > 0) {
+				aok = FD_ISSET(fd, &can_write);
+			} else {
+				aok = 0;
+			}
+#endif
+			
 			if (handle->last_event) {
 				const char *type = esl_event_get_header(handle->last_event, "content-type");
 				int known = 0;
 
 				if (!esl_strlen_zero(type)) {
-					if (!strcasecmp(type, "log/data")) {
+					if (aok && !strcasecmp(type, "log/data")) {
 						const char *userdata = esl_event_get_header(handle->last_event, "user-data");
 						
 						if (esl_strlen_zero(userdata) || esl_strlen_zero(filter_uuid) || !strcasecmp(filter_uuid, userdata)) {
@@ -631,7 +645,7 @@ static void *msg_thread_run(esl_thread_t *me, void *obj)
 					} else if (!strcasecmp(type, "text/disconnect-notice")) {
 						running = -1; thread_running = 0;
 						known++;
-					} else if (!strcasecmp(type, "text/event-plain")) {
+					} else if (aok && !strcasecmp(type, "text/event-plain")) {
 						char *foo;
 						esl_event_serialize(handle->last_ievent, &foo, ESL_FALSE);
 						printf("RECV EVENT\n%s\n", foo);
@@ -641,7 +655,7 @@ static void *msg_thread_run(esl_thread_t *me, void *obj)
 					}
 				}
 				
-				if (!known) {
+				if (aok && !known) {
 					char *foo;
 					printf("INCOMING DATA [%s]\n%s\n", type, handle->last_event->body ? handle->last_event->body : "");
 					esl_event_serialize(handle->last_event, &foo, ESL_FALSE);
@@ -651,6 +665,11 @@ static void *msg_thread_run(esl_thread_t *me, void *obj)
 			}
 		}
 
+		if (WARN_STOP) {
+			if (aok) printf("Type control-D or /exit or /quit or /bye to exit.\n\n");
+			WARN_STOP = 0;
+		}
+
 		usleep(1000);
 	}
 
committer: Anthony Minessale
comments: 
fix regression from f60fdf653dd2d7f8d3eaa6a9086e1f68bd993c59

diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c
index 0b16492..f7bf86b 100755
--- a/src/mod/applications/mod_dptools/mod_dptools.c
+++ b/src/mod/applications/mod_dptools/mod_dptools.c
@@ -2774,7 +2774,7 @@ static switch_call_cause_t group_outgoing_channel(switch_core_session_t *session
 	switch_originate_flag_t myflags = SOF_NONE;
 	char *cid_name_override = NULL;
 	char *cid_num_override = NULL;
-	char *domain = NULL;
+	char *domain = NULL, *dup_domain = NULL;
 	switch_channel_t *new_channel = NULL;
 	unsigned int timelimit = 60;
 	const char *skip, *var;
@@ -2788,6 +2788,7 @@ static switch_call_cause_t group_outgoing_channel(switch_core_session_t *session
 		*domain++ = '\0';
 	} else {
 		domain = switch_core_get_variable_pdup("domain", switch_core_session_get_pool(session));
+		dup_domain = domain;
 	}
 
 	if (!domain) {
@@ -2859,6 +2860,7 @@ static switch_call_cause_t group_outgoing_channel(switch_core_session_t *session
 
 	switch_safe_free(template);
 	switch_safe_free(group);
+	switch_safe_free(dup_domain);
 
 	if (cause == SWITCH_CAUSE_NONE) {
 		cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
diff --git a/src/mod/dialplans/mod_dialplan_asterisk/mod_dialplan_asterisk.c b/src/mod/dialplans/mod_dialplan_asterisk/mod_dialplan_asterisk.c
index 43534da..3bc5cb4 100644
--- a/src/mod/dialplans/mod_dialplan_asterisk/mod_dialplan_asterisk.c
+++ b/src/mod/dialplans/mod_dialplan_asterisk/mod_dialplan_asterisk.c
@@ -309,11 +309,13 @@ static switch_call_cause_t sip_outgoing_channel(switch_core_session_t *session,
 												switch_call_cause_t *cancel_cause)
 {
 	const char *profile;
+	char *dup_profile = NULL;
 
 	if (session) {
 		profile = switch_channel_get_variable(switch_core_session_get_channel(session), "sip_profile");
 	} else {
-		profile = switch_core_get_variable_pdup("sip_profile", switch_core_session_get_pool(session));
+		dup_profile = switch_core_get_variable_dup("sip_profile");
+		profile = dup_profile;
 	}
 	if (zstr(profile)) {
 		profile = "default";
@@ -323,6 +325,8 @@ static switch_call_cause_t sip_outgoing_channel(switch_core_session_t *session,
 
 	UNPROTECT_INTERFACE(sip_endpoint_interface);
 
+	switch_safe_free(dup_profile);
+
 	return switch_core_session_outgoing_channel(session, var_event, "sofia", outbound_profile, new_session, pool, SOF_NONE, cancel_cause);
 }
 
committer: Anthony Minessale
comments: 
fix regression from f60fdf653dd2d7f8d3eaa6a9086e1f68bd993c59

diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c
index 4be2a64..0b16492 100755
--- a/src/mod/applications/mod_dptools/mod_dptools.c
+++ b/src/mod/applications/mod_dptools/mod_dptools.c
@@ -2887,7 +2887,7 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
 												 switch_call_cause_t *cancel_cause)
 {
 	switch_xml_t x_domain = NULL, xml = NULL, x_user = NULL, x_group = NULL, x_param, x_params;
-	char *user = NULL, *domain = NULL;
+	char *user = NULL, *domain = NULL, *dup_domain = NULL;
 	const char *dest = NULL;
 	static switch_call_cause_t cause = SWITCH_CAUSE_NONE;
 	unsigned int timelimit = 60;
@@ -2908,7 +2908,8 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
 	if ((domain = strchr(user, '@'))) {
 		*domain++ = '\0';
 	} else {
-		domain = switch_core_get_variable_pdup("domain", switch_core_session_get_pool(session));
+		domain = switch_core_get_variable_dup("domain");
+		dup_domain = domain;
 	}
 
 	if (!domain) {
@@ -3115,6 +3116,7 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
 	}
 
 	switch_safe_free(user);
+	switch_safe_free(dup_domain);
 
 	return cause;
 }
committer: Jeff Lenk
comments: 
fix iLBC under windows

diff --git a/libs/ilbc/src/iLBC_decode.c b/libs/ilbc/src/iLBC_decode.c
index fc46fe4..9fc7a24 100644
--- a/libs/ilbc/src/iLBC_decode.c
+++ b/libs/ilbc/src/iLBC_decode.c
@@ -47,7 +47,9 @@
     	{
             fld dbl
             frndint
+            fstp dbl
         }
+        return (long int) dbl;
     }
 #elif defined (_WIN64)
 #include <intrin.h>
committer: Anthony Minessale
comments: 
block control-z from fs cli and print a warning how to exit properly

diff --git a/libs/esl/fs_cli.c b/libs/esl/fs_cli.c
index 1e3bf04..19e8d7f 100644
--- a/libs/esl/fs_cli.c
+++ b/libs/esl/fs_cli.c
@@ -8,6 +8,7 @@
 #include <signal.h>
 
 #define CMD_BUFLEN 1024
+static int WARN_STOP = 0;
 
 #ifdef WIN32
 #define strdup(src) _strdup(src)
@@ -535,6 +536,13 @@ static BOOL console_readConsole(HANDLE conIn, char* buf, int len, int* pRed, int
 static void handle_SIGINT(int sig)
 {
 	if (sig);
+
+	WARN_STOP = 1;
+
+	signal(SIGINT, handle_SIGINT);
+#ifdef SIGTSTP
+	signal(SIGTSTP, handle_SIGINT);
+#endif
 	return;
 }
 
@@ -581,6 +589,12 @@ static void *msg_thread_run(esl_thread_t *me, void *obj)
 
 	while(thread_running && handle->connected) {
 		esl_status_t status = esl_recv_event_timed(handle, 10, 1, NULL);
+
+		if (WARN_STOP) {
+			printf("Type control-D or /exit or /quit or /bye to exit.\n\n");
+			WARN_STOP = 0;
+		}
+
 		if (status == ESL_FAIL) {
 			esl_log(ESL_LOG_WARNING, "Disconnected.\n");
 			running = -1; thread_running = 0;
@@ -1023,6 +1037,9 @@ int main(int argc, char *argv[])
 	}
 	
 	signal(SIGINT, handle_SIGINT);
+#ifdef SIGTSTP
+	signal(SIGTSTP, handle_SIGINT);
+#endif
 #ifdef SIGQUIT
 	signal(SIGQUIT, handle_SIGQUIT);
 #endif
committer: Anthony Minessale
comments: 
dont run execute_on_fsk when there was no data collected

diff --git a/src/mod/applications/mod_fsk/mod_fsk.c b/src/mod/applications/mod_fsk/mod_fsk.c
index 9802353..0291707 100644
--- a/src/mod/applications/mod_fsk/mod_fsk.c
+++ b/src/mod/applications/mod_fsk/mod_fsk.c
@@ -220,6 +220,7 @@ static switch_bool_t fsk_detect_callback(switch_media_bug_t *bug, void *user_dat
 				char *sp;
 				switch_event_t *event;
 				const char *app_var;
+				int total = 0;
 
 				switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA);
 				
@@ -255,6 +256,7 @@ static switch_bool_t fsk_detect_callback(switch_media_bug_t *bug, void *user_dat
 					}
 
 					if (varname && val) {
+						total++;
 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s setting FSK var [%s][%s]\n", 
 										  switch_channel_get_name(channel), varname, val);
 						switch_channel_set_variable(channel, varname, val);
@@ -270,7 +272,7 @@ static switch_bool_t fsk_detect_callback(switch_media_bug_t *bug, void *user_dat
 					}
 				}
 				
-				if ((app_var = switch_channel_get_variable(channel, "execute_on_fsk"))) {
+				if (total && (app_var = switch_channel_get_variable(channel, "execute_on_fsk"))) {
 					char *app_arg;
 
 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s processing execute_on_fsk [%s]\n", 
committer: Anthony Minessale
comments: 
fix regression from d72cde9b76a856cf002366300bea02c26db44ffb

diff --git a/src/switch_core_session.c b/src/switch_core_session.c
index 4836aae..d2e28de 100644
--- a/src/switch_core_session.c
+++ b/src/switch_core_session.c
@@ -1865,6 +1865,17 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_get_app_flags(const char *ap
 SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_async(switch_core_session_t *session, const char *app, const char *arg)
 {
 	switch_event_t *execute_event;
+	char *ap, *arp;
+	
+	if (!arg && strstr(app, "::")) {
+		ap = switch_core_session_strdup(session, app);
+		app = ap;
+
+		if ((arp = strstr(ap, "::"))) {
+			*arp = '\0';
+			arg = arp + 2;
+		}
+	}
 	
 	if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) {
 		switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute");
@@ -1894,6 +1905,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flag
 	switch_application_interface_t *application_interface;
 	switch_status_t status = SWITCH_STATUS_SUCCESS;
 
+	if (!arg && strstr(app, "::")) {
+		return switch_core_session_execute_application_async(session, app, arg);
+	}
+
 	if (switch_channel_down(session->channel)) {
 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Channel is hungup, aborting execution of application: %s\n", app);
 		return SWITCH_STATUS_FALSE;
committer: Anthony Minessale
comments: 
FS-3006

diff --git a/src/mod/endpoints/mod_portaudio/mod_portaudio.c b/src/mod/endpoints/mod_portaudio/mod_portaudio.c
index 8978b85..baa33d4 100644
--- a/src/mod/endpoints/mod_portaudio/mod_portaudio.c
+++ b/src/mod/endpoints/mod_portaudio/mod_portaudio.c
@@ -40,6 +40,8 @@
 
 #define MY_EVENT_RINGING "portaudio::ringing"
 #define MY_EVENT_MAKE_CALL "portaudio::makecall"
+#define MY_EVENT_CALL_HELD "portaudio::callheld"
+#define MY_EVENT_CALL_RESUMED "portaudio::callresumed"
 #define MY_EVENT_ERROR_AUDIO_DEV "portaudio::audio_dev_error"
 #define SWITCH_PA_CALL_ID_VARIABLE "pa_call_id"
 
@@ -90,12 +92,20 @@ struct private_object {
 	switch_file_handle_t *hfh;
 	switch_frame_t hold_frame;
 	unsigned char holdbuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
-	switch_codec_t write_codec;
 	struct private_object *next;
 };
 
 typedef struct private_object private_t;
 
+struct audio_stream {
+	int indev;
+	int outdev;
+	PABLIO_Stream *stream;
+	switch_timer_t write_timer;
+	struct audio_stream *next;
+};
+typedef struct audio_stream audio_stream_t;
+
 static struct {
 	int debug;
 	int port;
@@ -113,12 +123,13 @@ static struct {
 	switch_hash_t *call_hash;
 	switch_mutex_t *device_lock;
 	switch_mutex_t *pvt_lock;
+	switch_mutex_t *streams_lock;
 	switch_mutex_t *flag_mutex;
 	switch_mutex_t *pa_mutex;
 	int sample_rate;
 	int codec_ms;
-	PABLIO_Stream *audio_stream;
-	PABLIO_Stream *ring_stream;
+	audio_stream_t *main_stream;
+	audio_stream_t *ring_stream;
 	switch_codec_t read_codec;
 	switch_codec_t write_codec;
 	switch_frame_t read_frame;
@@ -126,13 +137,20 @@ static struct {
 	unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
 	unsigned char cngbuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
 	private_t *call_list;
+	audio_stream_t *stream_list;
 	int ring_interval;
 	GFLAGS flags;
 	switch_timer_t read_timer;
-	switch_timer_t write_timer;
+	switch_timer_t readfile_timer;
 	switch_timer_t hold_timer;
 	int dual_streams;
 	time_t deactivate_timer;
+	int live_stream_switch;
+	int no_auto_resume_call;
+	int no_ring_during_call;
+	int codecs_inited;
+	int stream_in_use; //only really used by playdev
+	int destroying_streams;
 } globals;
 
 
@@ -164,9 +182,22 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
 static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
 static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
 static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
-static switch_status_t engage_device(int restart);
-static switch_status_t engage_ring_device(void);
-static void deactivate_ring_device(void);
+
+static switch_status_t create_codecs(int restart);
+static void create_hold_event(private_t *tech_pvt, int unhold);
+static audio_stream_t * find_audio_stream(int indev, int outdev, int already_locked);
+static audio_stream_t * get_audio_stream(int indev, int outdev);
+static audio_stream_t * create_audio_stream(int indev, int outdev);
+PaError open_audio_stream(PABLIO_Stream **stream, const PaStreamParameters * inputParameters, const PaStreamParameters * outputParameters);
+static switch_status_t switch_audio_stream();
+static void add_stream(audio_stream_t *stream, int already_locked);
+static void remove_stream(audio_stream_t *stream, int already_locked);
+static switch_status_t destroy_audio_stream(int indev, int outdev);
+static switch_status_t destroy_actual_stream(audio_stream_t *stream);
+static void destroy_audio_streams();
+static switch_status_t validate_main_audio_stream();
+static switch_status_t validate_ring_audio_stream();
+
 static int dump_info(int verbose);
 static switch_status_t load_config(void);
 static int get_dev_by_name(char *name, int in);
@@ -212,9 +243,8 @@ static switch_status_t channel_on_routing(switch_core_session_t *session)
 	if (hold_file) {
 		tech_pvt->hold_file = switch_core_session_strdup(session, hold_file);
 	}
-	
-	if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
-		if (engage_device(0) != SWITCH_STATUS_SUCCESS) {
+		if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
+		if (validate_main_audio_stream() != SWITCH_STATUS_SUCCESS) {
 			switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
 			return SWITCH_STATUS_FALSE;
 		}
@@ -238,7 +268,7 @@ static switch_status_t channel_on_routing(switch_core_session_t *session)
 										  globals.read_codec.implementation->actual_samples_per_second,
 										  SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) == SWITCH_STATUS_SUCCESS) {
 
-					if (engage_ring_device() != SWITCH_STATUS_SUCCESS) {
+					if (validate_ring_audio_stream() != SWITCH_STATUS_SUCCESS) {
 						switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Ring Error!\n");
 						switch_core_file_close(&fh);
@@ -263,7 +293,7 @@ static switch_status_t channel_on_routing(switch_core_session_t *session)
 		}
 
 		while (switch_channel_get_state(channel) == CS_ROUTING && !switch_test_flag(tech_pvt, TFLAG_ANSWER)) {
-			switch_size_t olen = globals.read_timer.samples;
+			switch_size_t olen = globals.readfile_timer.samples;
 
 			if (switch_micro_time_now() - last >= waitsec) {
 				char buf[512];
@@ -273,7 +303,8 @@ static switch_status_t channel_on_routing(switch_core_session_t *session)
 
 				if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_RINGING) == SWITCH_STATUS_SUCCESS) {
 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_info", buf);
-					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call_id", tech_pvt->call_id);
+					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call_id", tech_pvt->call_id); /* left behind for backwards compatability */
+					switch_channel_set_variable(channel, SWITCH_PA_CALL_ID_VARIABLE, tech_pvt->call_id);
 					switch_channel_event_set_data(channel, event);
 					switch_event_fire(&event);
 				}
@@ -282,7 +313,7 @@ static switch_status_t channel_on_routing(switch_core_session_t *session)
 			}
 
 			if (ring_file) {
-				if (switch_core_timer_next(&globals.read_timer) != SWITCH_STATUS_SUCCESS) {
+				if (switch_core_timer_next(&globals.readfile_timer) != SWITCH_STATUS_SUCCESS) {
 					switch_core_file_close(&fh);
 					break;
 				}
@@ -292,8 +323,9 @@ static switch_status_t channel_on_routing(switch_core_session_t *session)
 					switch_core_file_seek(&fh, &pos, 0, SEEK_SET);
 				}
 
-				if (globals.ring_stream) {
-					WriteAudioStream(globals.ring_stream, abuf, (long) olen, &globals.write_timer);
+				if (globals.ring_stream && (! switch_test_flag(globals.call_list, TFLAG_MASTER) || 
+							( !globals.no_ring_during_call && globals.main_stream != globals.ring_stream)) ) { //if there is a ring stream and not an active call or if there is an active call and we are allowed to ring during it AND the ring stream is not the main stream						
+						WriteAudioStream(globals.ring_stream->stream, abuf, (long) olen, &globals.ring_stream->write_timer);
 				}
 			} else {
 				switch_yield(10000);
@@ -303,7 +335,6 @@ static switch_status_t channel_on_routing(switch_core_session_t *session)
 	}
 
 	if (ring_file) {
-		deactivate_ring_device();
 		switch_core_file_close(&fh);
 	}
 
@@ -329,27 +360,130 @@ static switch_status_t channel_on_execute(switch_core_session_t *session)
 	return SWITCH_STATUS_SUCCESS;
 }
 
-static void deactivate_audio_device(void)
+static audio_stream_t* find_audio_stream(int indev, int outdev, int already_locked)
 {
-	if (!globals.audio_stream) {
-		return;
+	audio_stream_t *cur_stream;
+	
+	if (! globals.stream_list) {
+		return NULL;
 	}
 
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Stop audio device.\n");
+	if (! already_locked) {
+		switch_mutex_lock(globals.streams_lock);
+	}
+	cur_stream = globals.stream_list;
 
-	switch_mutex_lock(globals.device_lock);
-	/* LOCKED ************************************************************************************************** */
+	while (cur_stream != NULL) {
+		if (cur_stream->outdev == outdev) {
+			if (indev == -1 || cur_stream->indev == indev) {
+				if (! already_locked) {
+					switch_mutex_unlock(globals.streams_lock);
+				}
+				return cur_stream;
+			}
+		}
+		cur_stream = cur_stream->next;
+	}
+	if (! already_locked) {
+		switch_mutex_unlock(globals.streams_lock);
+	}
+	return NULL;
+}
+static void destroy_audio_streams()
+{
+	int close_wait = 4;
+	globals.destroying_streams = 1;
+
+	while (globals.stream_in_use && close_wait--) {
+		switch_yield(250000);
+	}
+	while (globals.stream_list != NULL) {
+		destroy_audio_stream(globals.stream_list->indev, globals.stream_list->outdev);
+	}
+	globals.destroying_streams = 0;
+}
+static switch_status_t validate_main_audio_stream()
+{
+	if (globals.read_timer.timer_interface) {
+		switch_core_timer_sync(&globals.read_timer);
+	}
 
-	if (globals.audio_stream) {
-		if (globals.ring_stream == globals.audio_stream) {
-			globals.ring_stream = NULL;
+	if (globals.main_stream) {
+		if (globals.main_stream->write_timer.timer_interface) {
+			switch_core_timer_sync(&(globals.main_stream->write_timer));
 		}
-		CloseAudioStream(globals.audio_stream);
-		globals.audio_stream = NULL;
+
+		return SWITCH_STATUS_SUCCESS;
 	}
 
-	/* UNLOCKED ************************************************************************************************* */
-	switch_mutex_unlock(globals.device_lock);
+	globals.main_stream = get_audio_stream(globals.indev, globals.outdev);
+	
+	if (globals.main_stream) {
+		return SWITCH_STATUS_SUCCESS;
+	}
+
+	return SWITCH_STATUS_FALSE;
+}
+
+static switch_status_t validate_ring_audio_stream()
+{
+	if (globals.ringdev == -1) {
+		return SWITCH_STATUS_SUCCESS;
+	}
+	if (globals.ring_stream) {
+		if (globals.ring_stream->write_timer.timer_interface) {
+			switch_core_timer_sync(&(globals.ring_stream->write_timer));
+		}
+		return SWITCH_STATUS_SUCCESS;
+	}
+	globals.ring_stream = get_audio_stream(-1, globals.ringdev);
+	if (globals.ring_stream) {
+		return SWITCH_STATUS_SUCCESS;
+	}
+
+	return SWITCH_STATUS_FALSE;
+}
+
+static switch_status_t destroy_actual_stream(audio_stream_t *stream)
+{
+	if (stream == NULL) {
+		return SWITCH_STATUS_FALSE;
+	}
+
+	if (globals.main_stream == stream) {
+		globals.main_stream = NULL;
+	}
+
+	if (globals.ring_stream == stream) {
+		globals.ring_stream = NULL;
+	}
+
+	CloseAudioStream(stream->stream);
+	stream->stream = NULL;
+	
+	if (stream->write_timer.timer_interface) {
+		switch_core_timer_destroy(&stream->write_timer);
+	}
+
+	switch_safe_free(stream);
+	return SWITCH_STATUS_SUCCESS;
+}
+static switch_status_t destroy_audio_stream(int indev, int outdev)
+{
+	audio_stream_t *stream;
+	
+	switch_mutex_lock(globals.streams_lock);
+	stream = find_audio_stream(indev, outdev,1);
+	if (stream == NULL) {
+		switch_mutex_unlock(globals.streams_lock);
+		return SWITCH_STATUS_FALSE;		
+	}
+
+	remove_stream(stream, 1);
+	switch_mutex_unlock(globals.streams_lock);
+
+	destroy_actual_stream(stream);
+	return SWITCH_STATUS_SUCCESS;
 }
 
 
@@ -368,34 +502,69 @@ static void destroy_codecs(void)
 		switch_core_timer_destroy(&globals.read_timer);
 	}
 
-	if (globals.write_timer.timer_interface) {
-		switch_core_timer_destroy(&globals.write_timer);
+	if (globals.readfile_timer.timer_interface) {
+		switch_core_timer_destroy(&globals.readfile_timer);
 	}
 
 	if (globals.hold_timer.timer_interface) {
 		switch_core_timer_destroy(&globals.hold_timer);
 	}
 
-
-
+	globals.codecs_inited = 0;
 }
 
-static void deactivate_ring_device(void)
+static void create_hold_event(private_t *tech_pvt, int unhold)
 {
-	if (!globals.ring_stream) {
-		return;
+	switch_event_t *event;
+	char * event_id;
+
+	if (unhold) {
+		event_id = MY_EVENT_CALL_RESUMED;
+	} else {
+		event_id = MY_EVENT_CALL_HELD;
 	}
 
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Stop ring device.\n");
-	switch_mutex_lock(globals.device_lock);
-	if (globals.ring_stream && globals.ring_stream != globals.audio_stream) {
-		CloseAudioStream(globals.ring_stream);
+	if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, event_id) == SWITCH_STATUS_SUCCESS) {
+		switch_channel_event_set_data(switch_core_session_get_channel(tech_pvt->session), event);
+		switch_event_fire(&event);
 	}
-	globals.ring_stream = NULL;
-	switch_mutex_unlock(globals.device_lock);
 }
 
+static void add_stream(audio_stream_t * stream, int already_locked)
+{
+	audio_stream_t *last;
 
+	if (! already_locked) {
+		switch_mutex_lock(globals.streams_lock);
+	}
+	for (last = globals.stream_list; last && last->next; last = last->next);
+	if (last == NULL) {
+		globals.stream_list = stream;
+	} else {
+		last->next = stream;
+	}
+	if (! already_locked) {
+		switch_mutex_unlock(globals.streams_lock);
+	}
+}
+static void remove_stream(audio_stream_t * stream, int already_locked)
+{
+	audio_stream_t *previous;
+	if (! already_locked) {
+		switch_mutex_lock(globals.streams_lock);
+	}
+	if (globals.stream_list == stream) {
+		globals.stream_list = stream->next;
+	} else {
+		for (previous = globals.stream_list; previous && previous->next && previous->next != stream; previous = previous->next) {
+			;
+		}
+		previous->next = stream->next;
+	}
+	if (! already_locked) {
+		switch_mutex_unlock(globals.streams_lock);
+	}
+}
 
 static void add_pvt(private_t *tech_pvt, int master)
 {
@@ -418,8 +587,9 @@ static void add_pvt(private_t *tech_pvt, int master)
 		if (tp == tech_pvt) {
 			in_list = 1;
 		}
-		if (master) {
+		if (master && switch_test_flag(tp, TFLAG_MASTER) ) {
 			switch_clear_flag_locked(tp, TFLAG_MASTER);
+			create_hold_event(tp,0);
 		}
 	}
 
@@ -446,11 +616,16 @@ static void add_pvt(private_t *tech_pvt, int master)
 static void remove_pvt(private_t *tech_pvt)
 {
 	private_t *tp, *last = NULL;
+	int was_master = 0;
 
 	switch_mutex_lock(globals.pvt_lock);
 	for (tp = globals.call_list; tp; tp = tp->next) {
-		switch_clear_flag_locked(tp, TFLAG_MASTER);
+		
 		if (tp == tech_pvt) {
+			if (switch_test_flag(tp, TFLAG_MASTER)) {
+				switch_clear_flag_locked(tp, TFLAG_MASTER);
+				was_master = 1;
+			}
 			if (last) {
 				last->next = tp->next;
 			} else {
@@ -461,10 +636,13 @@ static void remove_pvt(private_t *tech_pvt)
 	}
 
 	if (globals.call_list) {
-		switch_set_flag_locked(globals.call_list, TFLAG_MASTER);
+		if (was_master && ! globals.no_auto_resume_call) {
+			switch_set_flag_locked(globals.call_list, TFLAG_MASTER);
+			create_hold_event(globals.call_list, 1);
+		}
 	} else {
 		globals.deactivate_timer = switch_epoch_time_now(NULL) + 2;
-		deactivate_audio_device();
+		destroy_audio_streams();
 	}
 
 	switch_mutex_unlock(globals.pvt_lock);
@@ -555,8 +733,8 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
 	int samples = 0;
 	switch_status_t status = SWITCH_STATUS_FALSE;
 	switch_assert(tech_pvt != NULL);
-
-	if (!globals.audio_stream) {
+	
+	if (!globals.main_stream) {
 		goto normal_return;
 	}
 
@@ -618,7 +796,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
 	}
 
 	switch_mutex_lock(globals.device_lock);
-	samples = ReadAudioStream(globals.audio_stream, globals.read_frame.data, globals.read_codec.implementation->samples_per_packet, &globals.read_timer);
+	samples = ReadAudioStream(globals.main_stream->stream, globals.read_frame.data, globals.read_codec.implementation->samples_per_packet, &globals.read_timer);
 	switch_mutex_unlock(globals.device_lock);
 
 	if (samples) {
@@ -635,7 +813,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
 		goto cng_nowait;
 	}
 
-  normal_return:
+normal_return:
 	return status;
 
   cng_nowait:
@@ -655,7 +833,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
 	private_t *tech_pvt = switch_core_session_get_private(session);
 	switch_assert(tech_pvt != NULL);
 
-	if (!globals.audio_stream) {
+	if (!globals.main_stream) {
 		return SWITCH_STATUS_FALSE;
 	}
 
@@ -667,9 +845,9 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
 		return SWITCH_STATUS_SUCCESS;
 	}
 
-	if (globals.audio_stream) {
+	if (globals.main_stream) {
 		if (switch_test_flag((&globals), GFLAG_EAR)) {
-			WriteAudioStream(globals.audio_stream, (short *) frame->data, (int) (frame->datalen / sizeof(SAMPLE)), &globals.write_timer);
+			WriteAudioStream(globals.main_stream->stream, (short *) frame->data, (int) (frame->datalen / sizeof(SAMPLE)), &(globals.main_stream->write_timer));
 		}
 		status = SWITCH_STATUS_SUCCESS;
 	}
@@ -747,7 +925,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
 			channel = switch_core_session_get_channel(*new_session);
 			switch_core_session_set_private(*new_session, tech_pvt);
 			tech_pvt->session = *new_session;
-			globals.flags = GFLAG_EAR | GFLAG_MOUTH;
 		} else {
 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_CRIT, "Hey where is my memory pool?\n");
 			switch_core_session_destroy(new_session);
@@ -796,16 +973,17 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_portaudio_load)
 	switch_core_hash_init(&globals.call_hash, module_pool);
 	switch_mutex_init(&globals.device_lock, SWITCH_MUTEX_NESTED, module_pool);
 	switch_mutex_init(&globals.pvt_lock, SWITCH_MUTEX_NESTED, module_pool);
+	switch_mutex_init(&globals.streams_lock, SWITCH_MUTEX_NESTED, module_pool);
 	switch_mutex_init(&globals.flag_mutex, SWITCH_MUTEX_NESTED, module_pool);
 	switch_mutex_init(&globals.pa_mutex, SWITCH_MUTEX_NESTED, module_pool);
-
+	globals.codecs_inited=0;
 	globals.read_frame.data = globals.databuf;
 	globals.read_frame.buflen = sizeof(globals.databuf);
 	globals.cng_frame.data = globals.cngbuf;
 	globals.cng_frame.buflen = sizeof(globals.cngbuf);
 	globals.cng_frame.datalen = switch_samples_per_packet(globals.sample_rate, globals.codec_ms) * 2;
 	switch_set_flag((&globals.cng_frame), SFF_CNG);
-
+	globals.flags = GFLAG_EAR | GFLAG_MOUTH;
 	/* dual streams makes portaudio on solaris choke */
 #if defined(sun) || defined(__sun)
 	globals.dual_streams = 0;
@@ -834,6 +1012,14 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_portaudio_load)
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass!\n");
 		return SWITCH_STATUS_GENERR;
 	}
+	if (switch_event_reserve_subclass(MY_EVENT_CALL_HELD) != SWITCH_STATUS_SUCCESS) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass!\n");
+		return SWITCH_STATUS_GENERR;
+	}
+	if (switch_event_reserve_subclass(MY_EVENT_CALL_RESUMED) != SWITCH_STATUS_SUCCESS) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass!\n");
+		return SWITCH_STATUS_GENERR;
+	}
 
 	if (switch_event_reserve_subclass(MY_EVENT_ERROR_AUDIO_DEV) != SWITCH_STATUS_SUCCESS) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass!\n");
@@ -861,9 +1047,13 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_portaudio_load)
 	switch_console_set_complete("add pa devlist");
 	switch_console_set_complete("add pa indev");
 	switch_console_set_complete("add pa outdev");
+	switch_console_set_complete("add pa preparestream");
+	switch_console_set_complete("add pa switchstream");
+	switch_console_set_complete("add pa closestreams");
 	switch_console_set_complete("add pa ringdev");
 	switch_console_set_complete("add pa ringfile");
 	switch_console_set_complete("add pa play");
+	switch_console_set_complete("add pa playdev");
 	switch_console_set_complete("add pa looptest");
 
 	/* indicate that the module should continue to be loaded */
@@ -881,9 +1071,12 @@ static switch_status_t load_config(void)
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf);
 		return SWITCH_STATUS_TERM;
 	}
-
+	destroy_audio_streams();
+	destroy_codecs();
 	globals.dual_streams = 0;
-
+	globals.live_stream_switch = 0;
+	globals.no_auto_resume_call = 0;
+	globals.no_ring_during_call = 0;
 	globals.indev = globals.outdev = globals.ringdev = -1;
 	globals.sample_rate = 8000;
 
@@ -896,6 +1089,24 @@ static switch_status_t load_config(void)
 				globals.debug = atoi(val);
 			} else if (!strcmp(var, "ring-interval")) {
 				globals.ring_interval = atoi(val);
+			} else if (!strcmp(var, "no-auto-resume-call")) {
+				if (switch_true(val)) {
+					globals.no_auto_resume_call = 1;
+				} else {
+					globals.no_auto_resume_call = 0;
+				}
+			} else if (!strcmp(var, "no-ring-during-call")) {
+				if (switch_true(val)) {
+					globals.no_ring_during_call = 1;
+				} else {
+					globals.no_ring_during_call = 0;
+				}
+			} else if (!strcmp(var, "live-stream-switch")) {
+				if (switch_true(val)) {
+					globals.live_stream_switch = 1;
+				} else {
+					globals.live_stream_switch = 0;
+				}
 			} else if (!strcmp(var, "ring-file")) {
 				set_global_ring_file(val);
 			} else if (!strcmp(var, "hold-file")) {
@@ -1007,8 +1218,7 @@ static switch_status_t load_config(void)
 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_portaudio_shutdown)
 {
 
-	deactivate_audio_device();
-	deactivate_ring_device();
+	destroy_audio_streams();
 	destroy_codecs();
 
 	Pa_Terminate();
@@ -1017,6 +1227,9 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_portaudio_shutdown)
 	switch_event_free_subclass(MY_EVENT_RINGING);
 	switch_event_free_subclass(MY_EVENT_MAKE_CALL);
 	switch_event_free_subclass(MY_EVENT_ERROR_AUDIO_DEV);
+	switch_event_free_subclass(MY_EVENT_CALL_HELD);
+	switch_event_free_subclass(MY_EVENT_CALL_RESUMED);
+	
 
 	switch_safe_free(globals.dialplan);
 	switch_safe_free(globals.context);
@@ -1118,7 +1331,99 @@ static void PrintSupportedStandardSampleRates(const PaStreamParameters * inputPa
 }
 
 /*******************************************************************/
+static switch_status_t play_dev(switch_stream_handle_t *stream, int outdev, char * file, const char * max_seconds, const char * no_close)
+{
+	switch_file_handle_t fh = { 0 };
+	int samples = 0;
+	int seconds = 5;
+	audio_stream_t * audio_stream;
+	int created_stream = 0;
+	int wrote = 0;
+	switch_size_t olen;
+	int16_t abuf[2048];
+
+
+	if (!strcasecmp(file, "ringtest")) {
+		file = globals.ring_file;
+	}
+	if (outdev == -1) {
+		stream->write_function(stream, "Invalid output audio device\n");
+		return SWITCH_STATUS_FALSE;
+	}
+	audio_stream = get_audio_stream(-1, outdev);
+
+	fh.pre_buffer_datalen = SWITCH_DEFAULT_FILE_BUFFER_LEN;
+
+	if (switch_core_file_open(&fh,	file,
+		globals.read_codec.implementation->number_of_channels,
+		globals.read_codec.implementation->actual_samples_per_second,
+		SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
+			stream->write_function(stream, "Cannot play requested file %s\n", file);
+			return SWITCH_STATUS_FALSE;
+	}
+
+	olen = globals.read_codec.implementation->samples_per_packet;
+
+	if (max_seconds) {
+		int i = atoi(max_seconds);
+		if (i >= 0) {
+			seconds = i;
+		}
+	}
+
+	if (globals.call_list) {
+		switch_mutex_lock(globals.pvt_lock);
+		if (!globals.main_stream) {
+			switch_mutex_unlock(globals.pvt_lock);
+			return SWITCH_STATUS_FALSE;
+		}
+
+		if ( switch_test_flag(globals.call_list, TFLAG_MASTER) && globals.main_stream->outdev == outdev) { /*so we are the active stream so we need to dupe it basically */
+			audio_stream = create_audio_stream(-1,outdev);
+			created_stream=1;
+		}
+		switch_mutex_unlock(globals.pvt_lock);
+	}
+
+	if (! audio_stream) {
+		stream->write_function(stream, "Failed to engage audio device\n");
+		return SWITCH_STATUS_FALSE;
+	}
+
+
 
+	samples = globals.read_codec.implementation->actual_samples_per_second * seconds;
+	globals.stream_in_use=1;
+	while (switch_core_file_read(&fh, abuf, &olen) == SWITCH_STATUS_SUCCESS) {
+		if (globals.destroying_streams ||  ! audio_stream->stream) {
+			break;
+		}
+		
+		WriteAudioStream(audio_stream->stream, abuf, (long) olen, &(audio_stream->write_timer));
+		wrote += (int) olen;
+		if (samples) {
+			samples -= (int) olen;
+			if (samples <= 0) {
+				break;
+			}
+		}
+		olen = globals.read_codec.implementation->samples_per_packet;
+	}
+	globals.stream_in_use = 0;
+
+	switch_core_file_close(&fh);
+	if (! globals.call_list && ( ! no_close || strcasecmp(no_close,  "no_close"))) {
+		destroy_audio_streams();
+	}
+
+	seconds = wrote / globals.read_codec.implementation->actual_samples_per_second;
+	stream->write_function(stream, "playback test [%s] %d second(s) %d samples @%dkhz",
+		file, seconds, wrote, globals.read_codec.implementation->actual_samples_per_second);
+	if (created_stream) { /*still need this as not added to the global pool */
+		destroy_actual_stream(audio_stream);
+	}
+	return SWITCH_STATUS_SUCCESS;
+}
 static switch_status_t devlist(char **argv, int argc, switch_stream_handle_t *stream)
 {
 	int i, numDevices, prev;
@@ -1200,8 +1505,7 @@ static int dump_info(int verbose)
 	}
 
 	if (verbose < 0) {
-		deactivate_audio_device();
-		deactivate_ring_device();
+		destroy_audio_streams();
 		destroy_codecs();
 		Pa_Terminate();
 		Pa_Initialize();
@@ -1309,36 +1613,15 @@ static int dump_info(int verbose)
 	return err;
 }
 
-static switch_status_t engage_device(int restart)
+static switch_status_t create_codecs(int restart)
 {
-	PaStreamParameters inputParameters, outputParameters;
-	PaError err;
 	int sample_rate = globals.sample_rate;
 	int codec_ms = globals.codec_ms;
-	switch_event_t *event;
-
-	switch_mutex_lock(globals.device_lock);
-	while (globals.deactivate_timer > switch_epoch_time_now(NULL)) {
-		switch_yield(1000000);
-	}
-	switch_mutex_unlock(globals.device_lock);
-
 
 	if (restart) {
-		deactivate_audio_device();
-		deactivate_ring_device();
 		destroy_codecs();
 	}
-
-	if (globals.read_timer.timer_interface) {
-		switch_core_timer_sync(&globals.read_timer);
-	}
-
-	if (globals.write_timer.timer_interface) {
-		switch_core_timer_sync(&globals.write_timer);
-	}
-
-	if (globals.audio_stream) {
+	if (globals.codecs_inited) {
 		return SWITCH_STATUS_SUCCESS;
 	}
 
@@ -1375,20 +1658,18 @@ static switch_status_t engage_device(int restart)
 			return SWITCH_STATUS_FALSE;
 		}
 	}
-
-
-	if (!globals.write_timer.timer_interface) {
-		if (switch_core_timer_init(&globals.write_timer,
+	if (!globals.readfile_timer.timer_interface) {
+		if (switch_core_timer_init(&globals.readfile_timer,
 								   globals.timer_name, codec_ms, globals.read_codec.implementation->samples_per_packet,
 								   module_pool) != SWITCH_STATUS_SUCCESS) {
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "setup timer failed!\n");
 			switch_core_codec_destroy(&globals.read_codec);
 			switch_core_codec_destroy(&globals.write_codec);
-			switch_core_timer_destroy(&globals.read_timer);
 			return SWITCH_STATUS_FALSE;
 		}
 	}
 
+
 	if (!globals.hold_timer.timer_interface) {
 		if (switch_core_timer_init(&globals.hold_timer,
 								   globals.timer_name, codec_ms, globals.read_codec.implementation->samples_per_packet,
@@ -1397,106 +1678,119 @@ static switch_status_t engage_device(int restart)
 			switch_core_codec_destroy(&globals.read_codec);
 			switch_core_codec_destroy(&globals.write_codec);
 			switch_core_timer_destroy(&globals.read_timer);
-			switch_core_timer_destroy(&globals.write_timer);
+			switch_core_timer_destroy(&globals.readfile_timer);
+			
 			return SWITCH_STATUS_FALSE;
 		}
 	}
 
-	globals.read_frame.rate = sample_rate;
-	globals.read_frame.codec = &globals.read_codec;
+	globals.cng_frame.rate = globals.read_frame.rate = sample_rate;
+	globals.cng_frame.codec = globals.read_frame.codec = &globals.read_codec;
 
-	switch_mutex_lock(globals.device_lock);
-	/* LOCKED ************************************************************************************************** */
-	inputParameters.device = globals.indev;
-	inputParameters.channelCount = 1;
-	inputParameters.sampleFormat = SAMPLE_TYPE;
-	inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency;
-	inputParameters.hostApiSpecificStreamInfo = NULL;
-	outputParameters.device = globals.outdev;
+	globals.codecs_inited=1;
+	return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t switch_audio_stream()
+{
+	audio_stream_t *stream;
+	if (! globals.call_list) { /* If no active calls then it will automatically switch over on next call */
+		return SWITCH_STATUS_SUCCESS;
+	}
+	stream = get_audio_stream(globals.indev, globals.outdev);
+	if (stream == NULL) {
+		return SWITCH_STATUS_FALSE;
+	}
+
+	globals.main_stream = stream;//TODO: need locks around here??
+
+	return SWITCH_STATUS_SUCCESS;
+}
+PaError open_audio_stream(PABLIO_Stream **stream, const PaStreamParameters * inputParameters, const PaStreamParameters * outputParameters)
+{
+	if (inputParameters->device != -1) {
+		return OpenAudioStream(stream, inputParameters, outputParameters, globals.sample_rate, paClipOff, globals.read_codec.implementation->samples_per_packet, globals.dual_streams);
+	}
+	return OpenAudioStream(stream, NULL, outputParameters, globals.sample_rate, paClipOff, globals.read_codec.implementation->samples_per_packet, 0);
+}
+
+static audio_stream_t *create_audio_stream(int indev, int outdev)
+{
+	PaStreamParameters inputParameters, outputParameters;
+	PaError err;
+	switch_event_t *event;
+	audio_stream_t *stream;
+
+	stream = malloc(sizeof(audio_stream_t));
+	if (stream == NULL) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to alloc memory\n");
+		return NULL;
+	}
+	memset(stream, 0, sizeof(audio_stream_t));
+	stream->next = NULL;
+	stream->stream = NULL;
+	stream->indev = indev;
+	stream->outdev = outdev;
+	if (!stream->write_timer.timer_interface) {
+		if (switch_core_timer_init(&(stream->write_timer),
+								   globals.timer_name, globals.codec_ms, globals.read_codec.implementation->samples_per_packet,
+								   module_pool) != SWITCH_STATUS_SUCCESS) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "setup timer failed!\n");
+			switch_safe_free(stream);
+			return NULL;
+		}
+	}
+	inputParameters.device = indev;
+	if (indev != -1) {
+		inputParameters.channelCount = 1;
+		inputParameters.sampleFormat = SAMPLE_TYPE;
+		inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency;
+		inputParameters.hostApiSpecificStreamInfo = NULL;
+	}
+	outputParameters.device = outdev;
 	outputParameters.channelCount = 1;
 	outputParameters.sampleFormat = SAMPLE_TYPE;
 	outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency;
 	outputParameters.hostApiSpecificStreamInfo = NULL;
-	//err = OpenAudioStream(&globals.audio_stream, NULL/*&inputParameters*/, &outputParameters, sample_rate, paClipOff,
-	//globals.read_codec.implementation->samples_per_packet);
-	err = OpenAudioStream(&globals.audio_stream, &inputParameters, &outputParameters, sample_rate, paClipOff,
-						  globals.read_codec.implementation->samples_per_packet, globals.dual_streams);
-	/* UNLOCKED ************************************************************************************************* */
+	
+	err = open_audio_stream(&(stream->stream), &inputParameters, &outputParameters);
 	if (err != paNoError) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening audio device retrying\n");
 		switch_yield(1000000);
-		err = OpenAudioStream(&globals.audio_stream, &inputParameters, &outputParameters, sample_rate, paClipOff,
-							  globals.read_codec.implementation->samples_per_packet, globals.dual_streams);
+		err = open_audio_stream(&(stream->stream), &inputParameters, &outputParameters);
 	}
 
-	switch_mutex_unlock(globals.device_lock);
-
 	if (err != paNoError) {
+		switch_safe_free(stream);
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open audio device\n");
-		switch_core_codec_destroy(&globals.read_codec);
-		switch_core_codec_destroy(&globals.write_codec);
-		switch_core_timer_destroy(&globals.read_timer);
-		switch_core_timer_destroy(&globals.write_timer);
-		switch_core_timer_destroy(&globals.hold_timer);
 		if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_ERROR_AUDIO_DEV) == SWITCH_STATUS_SUCCESS) {
 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Reason", Pa_GetErrorText(err));
 			switch_event_fire(&event);
 		}
-		return SWITCH_STATUS_FALSE;
+		return NULL;
 	}
-
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Engage audio device rate: %d channels %d\n", sample_rate, outputParameters.channelCount);
-
-	engage_ring_device();
-
-	return SWITCH_STATUS_SUCCESS;
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Created audio stream: %d channels %d\n", globals.sample_rate, outputParameters.channelCount);
+	return stream;
 }
 
-static switch_status_t engage_ring_device(void)
+audio_stream_t *get_audio_stream(int indev, int outdev)
 {
-	PaStreamParameters outputParameters = { 0 };
-	PaError err;
-	int sample_rate = globals.sample_rate;
-	int channels = 1;
-
-	if (globals.ring_stream) {
-		return SWITCH_STATUS_SUCCESS;
+	audio_stream_t *stream;
+	if (outdev == -1) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error invalid output audio device\n");
 	}
-
-	if (globals.ringdev == globals.outdev) {
-		if (engage_device(0) == SWITCH_STATUS_SUCCESS) {
-			globals.ring_stream = globals.audio_stream;
-		} else {
-			goto error;
-		}
-	} else {
-		switch_mutex_lock(globals.device_lock);
-		/* LOCKED ************************************************************************************************** */
-		outputParameters.device = globals.ringdev;
-		outputParameters.channelCount = channels;
-		outputParameters.sampleFormat = SAMPLE_TYPE;
-		outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency;
-		outputParameters.hostApiSpecificStreamInfo = NULL;
-		err = OpenAudioStream(&globals.ring_stream, NULL,
-							  &outputParameters, sample_rate, paClipOff, globals.read_codec.implementation->samples_per_packet, globals.dual_streams);
-		/* UNLOCKED ************************************************************************************************* */
-		switch_mutex_unlock(globals.device_lock);
-
-		if (err != paNoError) {
-			goto error;
-		}
+	if (create_codecs(0) != SWITCH_STATUS_SUCCESS) {
+		return NULL;
 	}
-
-	switch_yield(10000);
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Engage ring device rate: %d channels %d\n", sample_rate, channels);
-	return SWITCH_STATUS_SUCCESS;
-
-
-  error:
-
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open ring device\n");
-	return SWITCH_STATUS_FALSE;
-
+	stream = find_audio_stream(indev, outdev, 0);
+	if (stream != NULL) {
+		return stream;
+	}
+	stream = create_audio_stream(indev, outdev);
+	if (stream) {
+		add_stream(stream, 0);
+	}
+	return stream;
 }
 
 static switch_status_t dtmf_call(char **argv, int argc, switch_stream_handle_t *stream)
@@ -1523,6 +1817,211 @@ static switch_status_t dtmf_call(char **argv, int argc, switch_stream_handle_t *
 	return SWITCH_STATUS_SUCCESS;
 }
 
+static switch_status_t close_streams(char **argv, int argc, switch_stream_handle_t *stream)
+{
+	if (globals.call_list) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n");
+		return SWITCH_STATUS_FALSE;
+	}
+	destroy_audio_streams();
+	stream->write_function(stream, "closestreams all open streams closed\n");
+	return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t set_indev(char **argv, int argc, switch_stream_handle_t *stream)
+{
+	int devval;
+
+	if (globals.call_list && ! globals.live_stream_switch) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n");
+		return SWITCH_STATUS_FALSE;
+	}
+	if (*argv[0] == '#') {
+		devval = get_dev_by_number(argv[0] + 1, 1);
+	} else {
+		devval = get_dev_by_name(argv[0], 1);
+	}
+	if (devval < 0) {
+		stream->write_function(stream, "indev not set (invalid value)\n");
+		return SWITCH_STATUS_FALSE;
+	}
+	globals.indev = devval;
+	switch_audio_stream();
+	stream->write_function(stream, "indev set to %d\n", devval);
+	return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t set_outdev(char **argv, int argc, switch_stream_handle_t *stream)
+{
+	int devval;
+	if (globals.call_list && ! globals.live_stream_switch) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n");
+		return SWITCH_STATUS_FALSE;
+	}
+	if (*argv[0] == '#') {
+		devval = get_dev_by_number(argv[0] + 1, 0);
+	} else {
+		devval = get_dev_by_name(argv[0], 0);
+	}
+	if (devval < 0) {
+		stream->write_function(stream, "outdev not set (invalid value)\n");
+		return SWITCH_STATUS_FALSE;
+	}
+
+	globals.outdev = devval;
+	switch_audio_stream();
+	stream->write_function(stream, "outdev set to %d\n", devval);
+	return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t prepare_stream(char **argv, int argc, switch_stream_handle_t *stream)
+{
+	int devval=-2,devval2=-1;
+	if (! strcmp(argv[0], "#-1")) {
+		devval = -1;
+	} else if (*argv[0] == '#') {
+		devval = get_dev_by_number(argv[0]+1, 1);
+	}
+	if (devval == -2) {
+		stream->write_function(stream, "preparestream not prepared as indev has (invalid value)\n");
+		return SWITCH_STATUS_FALSE;
+	}
+	if (*argv[1] == '#') {
+		devval2 = get_dev_by_number(argv[1]+1, 0);
+	}
+	if (devval2 == -1) {
+		stream->write_function(stream, "preparestream not prepared as outdev has (invalid value)\n");
+		return SWITCH_STATUS_FALSE;
+	}
+
+	if (! get_audio_stream(devval,devval2)) {
+		stream->write_function(stream, "preparestream not prepared received an invalid stream back\n");
+		return SWITCH_STATUS_FALSE;
+	}
+	stream->write_function(stream, "preparestream prepared indev: %d outdev: %d\n", devval, devval2);
+	return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t switch_stream(char **argv, int argc, switch_stream_handle_t *stream)
+{
+	int devval =-1, devval2 = -1;
+	if (globals.call_list && ! globals.live_stream_switch) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n");
+		return SWITCH_STATUS_FALSE;
+	}
+	if (*argv[0] == '#') {
+		devval = get_dev_by_number(argv[0]+1, 1);
+	}
+	if (devval == -1) {
+		stream->write_function(stream, "switchstream not prepared as indev has (invalid value)\n");
+		return SWITCH_STATUS_FALSE;
+	}
+	if (*argv[1] == '#') {
+		devval2 = get_dev_by_number(argv[1]+1, 0);
+	}
+	if (devval2 == -1) {
+		stream->write_function(stream, "switchstream not prepared as outdev has (invalid value)\n");
+		return SWITCH_STATUS_FALSE;
+	}
+	globals.indev = devval;
+	globals.outdev = devval2;
+	if (switch_audio_stream() != SWITCH_STATUS_SUCCESS) {
+		stream->write_function(stream, "switchstream was unable to switch\n");
+		return SWITCH_STATUS_FALSE;
+	}
+	stream->write_function(stream, "switchstream switched to indev: %d outdev: %d\n", devval, devval2);
+	return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t set_ringdev(char **argv, int argc, switch_stream_handle_t *stream)
+{
+	int devval;
+	if (globals.call_list && ! globals.live_stream_switch) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n");
+		return SWITCH_STATUS_FALSE;
+	}
+	if (! strcmp(argv[0], "#-1")) {
+		globals.ring_stream = NULL;
+		globals.ringdev = -1;
+		stream->write_function(stream, "ringdev set to %d\n", globals.ringdev);
+		return SWITCH_STATUS_SUCCESS;
+	} else if (*argv[0] == '#') {
+		devval = get_dev_by_number(argv[0] + 1, 0);
+	} else {
+		devval = get_dev_by_name(argv[0], 0);
+	}
+	if (devval == -1) {
+		stream->write_function(stream, "ringdev not set as dev has (invalid value)\n");
+		return SWITCH_STATUS_FALSE;
+	}
+	globals.ringdev = devval;
+	stream->write_function(stream, "ringdev set to %d\n", globals.ringdev);
+	return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t looptest(char **argv, int argc, switch_stream_handle_t *stream)
+{
+	int samples = 0;
+	int success = 0;
+	int i;
+
+	if (globals.call_list) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n");
+		return SWITCH_STATUS_FALSE;
+	}
+	if (validate_main_audio_stream() != SWITCH_STATUS_SUCCESS) {
+		stream->write_function(stream, "looptest Failed to engage audio device\n");
+		return SWITCH_STATUS_FALSE;
+	}
+	globals.stream_in_use = 1;
+	for (i = 0; i < 400; i++) {
+		if (globals.destroying_streams ||  ! globals.main_stream->stream) {
+			break;
+		}
+		if ((samples = ReadAudioStream(globals.main_stream->stream, globals.read_frame.data, globals.read_codec.implementation->samples_per_packet, &globals.read_timer))) {
+			WriteAudioStream(globals.main_stream->stream, globals.read_frame.data, (long) samples, &(globals.main_stream->write_timer));
+			success = 1;
+		}
+		switch_yield(10000);
+	}
+	globals.stream_in_use = 0;
+
+	if (!success) {
+		stream->write_function(stream, "Failed to read any bytes from indev\n");
+		return SWITCH_STATUS_FALSE;
+	}
+	destroy_audio_streams();
+	stream->write_function(stream, "looptest complete\n");
+	return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t set_ringfile(char **argv, int argc, switch_stream_handle_t *stream)
+{
+	if (! argv[0]) {
+		stream->write_function(stream, "%s", globals.ring_file);
+		return SWITCH_STATUS_SUCCESS;
+	}
+	if (create_codecs(0) == SWITCH_STATUS_SUCCESS) {
+		switch_file_handle_t fh = { 0 };
+		if (switch_core_file_open(&fh,
+								  argv[0],
+								  globals.read_codec.implementation->number_of_channels,
+								  globals.read_codec.implementation->actual_samples_per_second,
+								  SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) == SWITCH_STATUS_SUCCESS) {
+			switch_core_file_close(&fh);
+			set_global_ring_file(argv[0]);
+		} else {
+			stream->write_function(stream, "ringfile Unable to open ring file %s\n", argv[0]);
+			return SWITCH_STATUS_FALSE;
+		}
+	} else {
+		stream->write_function(stream, "ringfile Failed to init codecs device\n");
+		return SWITCH_STATUS_FALSE;
+	}
+	stream->write_function(stream, "ringfile set to %s", globals.ring_file);
+	return SWITCH_STATUS_SUCCESS;
+}
+
 static switch_status_t switch_call(char **argv, int argc, switch_stream_handle_t *stream)
 {
 	private_t *tp, *tech_pvt = NULL;
@@ -1542,7 +2041,10 @@ static switch_status_t switch_call(char **argv, int argc, switch_stream_handle_t
 		}
 	} else if (!strcasecmp(callid, "none")) {
 		for (tp = globals.call_list; tp; tp = tp->next) {
+			if (switch_test_flag(tp, TFLAG_MASTER))	{
 			switch_clear_flag_locked(tp, TFLAG_MASTER);
+				create_hold_event(tp,0);
+			}
 		}
 		stream->write_function(stream, "OK\n");
 		goto done;
@@ -1559,6 +2061,7 @@ static switch_status_t switch_call(char **argv, int argc, switch_stream_handle_t
 			remove_pvt(tech_pvt);
 		}
 		add_pvt(tech_pvt, PA_MASTER);
+		create_hold_event(tech_pvt, 1);
 		stream->write_function(stream, "OK\n");
 	} else {
 		stream->write_function(stream, "NO SUCH CALL\n");
@@ -1609,7 +2112,6 @@ static switch_status_t answer_call(char **argv, int argc, switch_stream_handle_t
 				switch_channel_t *channel = switch_core_session_get_channel(tp->session);
 				switch_set_flag_locked(tp, TFLAG_ANSWER);
 				add_pvt(tp, PA_MASTER);
-				deactivate_ring_device();
 				switch_channel_mark_answered(channel);
 			}
 		} else {
@@ -1624,7 +2126,6 @@ static switch_status_t answer_call(char **argv, int argc, switch_stream_handle_t
 			switch_channel_t *channel = switch_core_session_get_channel(tp->session);
 			switch_set_flag_locked(tp, TFLAG_ANSWER);
 			add_pvt(tp, PA_MASTER);
-			deactivate_ring_device();
 			switch_channel_mark_answered(channel);
 			x++;
 			break;
@@ -1766,7 +2267,6 @@ static switch_status_t place_call(char **argv, int argc, switch_stream_handle_t
 			channel = switch_core_session_get_channel(session);
 			switch_core_session_set_private(session, tech_pvt);
 			tech_pvt->session = session;
-			globals.flags = GFLAG_EAR | GFLAG_MOUTH;
 		} else {
 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Hey where is my memory pool?\n");
 			switch_core_session_destroy(&session);
@@ -1805,9 +2305,8 @@ static switch_status_t place_call(char **argv, int argc, switch_stream_handle_t
 			switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
 		}
 		tech_pvt->session = session;
-		if ((status = engage_device(0)) == SWITCH_STATUS_SUCCESS) {
+		if ((status = validate_main_audio_stream()) == SWITCH_STATUS_SUCCESS) {
 			switch_set_flag_locked(tech_pvt, TFLAG_ANSWER);
-			deactivate_ring_device();
 			switch_channel_mark_answered(channel);
 			switch_channel_set_state(channel, CS_INIT);
 			if (switch_core_session_thread_launch(tech_pvt->session) != SWITCH_STATUS_SUCCESS) {
@@ -1855,10 +2354,11 @@ SWITCH_STANDARD_API(pa_cmd)
 {
 	char *argv[1024] = { 0 };
 	int argc = 0;
-	char *mycmd = NULL, *devname = NULL;
+	char *mycmd = NULL;
 	switch_status_t status = SWITCH_STATUS_SUCCESS;
 	pa_command_t func = NULL;
-	int lead = 1, devval = 0;
+	int devval;
+	int lead = 1;
 	char *wcmd = NULL, *action = NULL;
 	char cmd_buf[1024] = "";
 	char *http = NULL;
@@ -1878,9 +2378,15 @@ SWITCH_STANDARD_API(pa_cmd)
 		"pa devlist [xml]\n"
 		"pa indev #<num>|<partial name>\n"
 		"pa outdev #<num>|<partial name>\n"
+		"pa preparestream #<indev_num> #<outdev_num>\n"
+		"pa switchstream #<indev_num> #<outdev_num>\n"
+		"pa closestreams\n"
 		"pa ringdev #<num>|<partial name>\n"
-		"pa play [ringtest|<filename>]\n"
-		"pa ringfile [filename]\n" "pa looptest\n" "--------------------------------------------------------------------------------\n";
+		"pa play [ringtest|<filename>] [seconds] [no_close]\n"
+		"pa playdev #<num> [ringtest|<filename>] [seconds] [no_close]\n"
+		"pa ringfile [filename]\n"
+		"pa looptest\n"
+		"--------------------------------------------------------------------------------\n";
 
 
 	if (stream->param_event) {
@@ -1973,169 +2479,42 @@ SWITCH_STANDARD_API(pa_cmd)
 		func = switch_call;
 	} else if (!strcasecmp(argv[0], "dtmf")) {
 		func = dtmf_call;
+	} else if (!strcasecmp(argv[0], "closestreams")) {
+		func = close_streams;
 	} else if (argv[1] && !strcmp(argv[0], "indev")) {
-
-		if (globals.call_list) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n");
-			goto done;
-		}
-
-		if (*argv[1] == '#') {
-			devval = get_dev_by_number(argv[1] + 1, 1);
-		} else {
-			devval = get_dev_by_name(argv[1], 1);
-		}
-		devname = "indev";
-		if (devval > -1) {
-			globals.indev = devval;
-			//engage_device(1);
-		}
+		func = set_indev;
 	} else if (argv[1] && !strcmp(argv[0], "outdev")) {
-
-		if (globals.call_list) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n");
-			goto done;
-		}
-
-		if (*argv[1] == '#') {
-			devval = get_dev_by_number(argv[1] + 1, 0);
-		} else {
-			devval = get_dev_by_name(argv[1], 0);
-		}
-		devname = "outdev";
-		if (devval > -1) {
-			globals.outdev = devval;
-			//engage_device(1);
-		}
+		func = set_outdev;
+	} else if (argv[1] && argv[2] && !strcmp(argv[0], "preparestream")) {
+		func = prepare_stream;	
+	} else if (argv[1] && argv[2] && !strcmp(argv[0], "switchstream")) {
+		func = switch_stream;	
 	} else if (argv[1] && !strcmp(argv[0], "ringdev")) {
-
-		if (globals.call_list) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n");
-			goto done;
+		func = set_ringdev;
+	} else if ((argv[1] && !strcmp(argv[0], "play"))) {
+		if (validate_main_audio_stream() == SWITCH_STATUS_SUCCESS) {
+			play_dev(stream, globals.main_stream ? globals.main_stream->outdev : -1,argv[1],argv[2], argv[3]);
+		}else{
+			stream->write_function(stream, "Failed to engage audio device\n");
 		}
-
+		goto done;
+	} else if ((argv[1] && argv[2] && !strcmp(argv[0], "playdev"))) {
 		if (*argv[1] == '#') {
 			devval = get_dev_by_number(argv[1] + 1, 0);
 		} else {
-			devval = get_dev_by_name(argv[1], 0);
-		}
-		devname = "ringdev";
-		if (devval > -1) {
-			globals.ringdev = devval;
-			//engage_device(1);
-		}
-	} else if ((argv[1] && !strcasecmp(argv[0], "play"))) {
-		switch_file_handle_t fh = { 0 };
-		char *playfile = NULL;
-		int samples = 0;
-		int seconds = 5;
-		int wrote = 0;
-
-		if (globals.call_list) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n");
-			goto done;
-		}
-
-		if (!strcasecmp(argv[1], "ringtest")) {
-			playfile = globals.ring_file;
-		} else {
-			playfile = argv[1];
-		}
-
-		fh.pre_buffer_datalen = SWITCH_DEFAULT_FILE_BUFFER_LEN;
-		if (engage_device(0) == SWITCH_STATUS_SUCCESS) {
-			if (switch_core_file_open(&fh,
-									  playfile,
-									  globals.read_codec.implementation->number_of_channels,
-									  globals.read_codec.implementation->actual_samples_per_second,
-									  SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) == SWITCH_STATUS_SUCCESS) {
-				switch_size_t olen = globals.read_codec.implementation->samples_per_packet;
-				int16_t abuf[2048];
-
-				if (argv[2]) {
-					int i = atoi(argv[2]);
-					if (i >= 0) {
-						seconds = i;
-					}
-				}
-
-				samples = globals.read_codec.implementation->actual_samples_per_second * seconds;
-				while (switch_core_file_read(&fh, abuf, &olen) == SWITCH_STATUS_SUCCESS) {
-					WriteAudioStream(globals.audio_stream, abuf, (long) olen, &globals.read_timer);
-					wrote += (int) olen;
-					if (samples) {
-						samples -= (int) olen;
-						if (samples <= 0) {
-							break;
-						}
-					}
-					olen = globals.read_codec.implementation->samples_per_packet;
-				}
-
-				switch_core_file_close(&fh);
-				deactivate_audio_device();
-
-				seconds = wrote / globals.read_codec.implementation->actual_samples_per_second;
-				stream->write_function(stream, "playback test [%s] %d second(s) %d samples @%dkhz",
-									   playfile, seconds, wrote, globals.read_codec.implementation->actual_samples_per_second);
-
-
-			} else {
-				stream->write_function(stream, "Cannot play requested file %s\n", argv[1]);
-			}
-		} else {
-			stream->write_function(stream, "Failed to engage audio device\n");
+			devval = -1;
 		}
+		play_dev(stream, devval,argv[2],argv[3],argv[4]);
 		goto done;
 	} else if (!strcasecmp(argv[0], "looptest")) {
-		if (globals.call_list) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n");
-			goto done;
-		}
-
-		if (engage_device(0) == SWITCH_STATUS_SUCCESS) {
-			int samples = 0;
-			int success = 0;
-			int i;
-			for (i = 0; i < 400; i++) {
-				if ((samples = ReadAudioStream(globals.audio_stream, globals.read_frame.data,
-											   globals.read_codec.implementation->samples_per_packet, &globals.read_timer))) {
-					WriteAudioStream(globals.audio_stream, globals.read_frame.data, (long) samples, &globals.write_timer);
-					success = 1;
-				}
-				switch_yield(10000);
-			}
-			if (!success) {
-				stream->write_function(stream, "Failed to read any bytes from indev\n");
-			}
-			deactivate_audio_device();
-		} else {
-			stream->write_function(stream, "Failed to engage audio device\n");
-		}
-		goto done;
+		func = looptest;
 	} else if (!strcasecmp(argv[0], "ringfile")) {
-		if (argv[1]) {
-			if (engage_device(0) == SWITCH_STATUS_SUCCESS) {
-				switch_file_handle_t fh = { 0 };
-				if (switch_core_file_open(&fh,
-										  argv[1],
-										  globals.read_codec.implementation->number_of_channels,
-										  globals.read_codec.implementation->actual_samples_per_second,
-										  SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) == SWITCH_STATUS_SUCCESS) {
-					switch_core_file_close(&fh);
-					set_global_ring_file(argv[1]);
-				} else {
-					stream->write_function(stream, "Unable to open ring file %s\n", argv[1]);
-				}
-			} else {
-				stream->write_function(stream, "Failed to engage audio device\n");
-			}
-		} else {
-			stream->write_function(stream, "%s", globals.ring_file);
-		}
-		goto done;
+		func = set_ringfile;
+	} else {
+		stream->write_function(stream, "Unknown Command or not enough args [%s]\n", argv[0]);
 	}
 
+
 	if (func) {
 		if (http) {
 			stream->write_function(stream, "<pre>");
@@ -2143,21 +2522,12 @@ SWITCH_STANDARD_API(pa_cmd)
 
 		switch_mutex_lock(globals.pa_mutex);
 		status = func(&argv[lead], argc - lead, stream);
+		status = SWITCH_STATUS_SUCCESS; /*if func was defined we want to always return success as the command was found */
 		switch_mutex_unlock(globals.pa_mutex);
 
 		if (http) {
 			stream->write_function(stream, "\n\n</pre>");
 		}
-	} else {
-		if (devname) {
-			if (devval > -1) {
-				stream->write_function(stream, "%s set to %d\n", devname, devval);
-			} else {
-				stream->write_function(stream, "%s not set (invalid value)\n", devname);
-			}
-		} else {
-			stream->write_function(stream, "Unknown Command [%s]\n", argv[0]);
-		}
 	}
 
   done:
@@ -2171,6 +2541,14 @@ SWITCH_STANDARD_API(pa_cmd)
 							   "<input name=action type=submit value=\"switch\"> "
 							   "<input name=action type=submit value=\"mute\"> "
 							   "<input name=action type=submit value=\"unmute\"> "
+							   "<input name=action type=submit value=\"indev\"> "
+							   "<input name=action type=submit value=\"outdev\"> "
+							   "<input name=action type=submit value=\"preparestream\"> "
+							   "<input name=action type=submit value=\"switchstream\"> "
+							   "<input name=action type=submit value=\"closestreams\"> "
+							   "<input name=action type=submit value=\"ringdev\"> "
+							   "<input name=action type=submit value=\"play\"> "
+							   "<input name=action type=submit value=\"playdev\"> "
 							   "<input name=action type=submit value=\"answer\"> <br><br>"
 							   "<table border=1>\n"
 							   "<tr><td><input name=action type=submit value=\"1\"></td>"
committer: Anthony Minessale
comments: 
try to improve iLBC compat

diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c
index 8b2f470..a0b7fca 100644
--- a/src/mod/endpoints/mod_sofia/sofia_glue.c
+++ b/src/mod/endpoints/mod_sofia/sofia_glue.c
@@ -4480,7 +4480,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
 						match = strcasecmp(rm_encoding, imp->iananame) ? 0 : 1;
 					}
 
-					if (match && bit_rate && map_bit_rate && map_bit_rate != bit_rate) {
+					if (match && bit_rate && map_bit_rate && map_bit_rate != bit_rate && strcasecmp(map->rm_encoding, "ilbc")) {
 						/* nevermind */
 						match = 0;
 					}
diff --git a/src/switch_core.c b/src/switch_core.c
index 8754305..0eb51cc 100644
--- a/src/switch_core.c
+++ b/src/switch_core.c
@@ -1486,7 +1486,7 @@ static void switch_load_core_config(const char *file)
 {
 	switch_xml_t xml = NULL, cfg = NULL;
 
-	//switch_core_hash_insert(runtime.ptimes, "ilbc", &d_30);
+	switch_core_hash_insert(runtime.ptimes, "ilbc", &d_30);
 	switch_core_hash_insert(runtime.ptimes, "G723", &d_30);
 
 	if ((xml = switch_xml_open_cfg(file, &cfg, NULL))) {
committer: Arnaldo Pereira
comments: 
Merge branch 'master' of git://git.freeswitch.org/freeswitch
committer: Anthony Minessale
comments: 
doh regression

diff --git a/src/switch_event.c b/src/switch_event.c
index 3e12ea1..b626d5b 100644
--- a/src/switch_event.c
+++ b/src/switch_event.c
@@ -1561,6 +1561,7 @@ SWITCH_DECLARE(char *) switch_event_expand_headers(switch_event_t *event, const
 	char *cloned_sub_val = NULL;
 	char *func_val = NULL;
 	int nv = 0;
+	char *gvar = NULL;
 
 	nv = switch_string_var_check_const(in) || switch_string_has_escaped_data(in);
 
@@ -1673,7 +1674,6 @@ SWITCH_DECLARE(char *) switch_event_expand_headers(switch_event_t *event, const
 					int offset = 0;
 					int ooffset = 0;
 					char *ptr;
-					char *gvar = NULL;
 
 					if ((expanded = switch_event_expand_headers(event, (char *) vname)) == vname) {
 						expanded = NULL;
@@ -1690,6 +1690,7 @@ SWITCH_DECLARE(char *) switch_event_expand_headers(switch_event_t *event, const
 					}
 
 					if (!(sub_val = switch_event_get_header(event, vname))) {
+						switch_safe_free(gvar);
 						if ((gvar = switch_core_get_variable_dup(vname))) {
 							sub_val = gvar;
 						}
@@ -1713,7 +1714,6 @@ SWITCH_DECLARE(char *) switch_event_expand_headers(switch_event_t *event, const
 						}
 					}
 
-					switch_safe_free(gvar);
 					switch_safe_free(expanded);
 				} else {
 					switch_stream_handle_t stream = { 0 };
@@ -1789,6 +1789,7 @@ SWITCH_DECLARE(char *) switch_event_expand_headers(switch_event_t *event, const
 		}
 	}
 	free(indup);
+	switch_safe_free(gvar);
 
 	return data;
 }
committer: Anthony Minessale
comments: 
FS-3027

diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c
index dfd6a76..8b2f470 100644
--- a/src/mod/endpoints/mod_sofia/sofia_glue.c
+++ b/src/mod/endpoints/mod_sofia/sofia_glue.c
@@ -4071,15 +4071,22 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
 	greedy = !!sofia_test_pflag(tech_pvt->profile, PFLAG_GREEDY);
 	scrooge = !!sofia_test_pflag(tech_pvt->profile, PFLAG_SCROOGE);
 
-	if (!greedy || !scrooge) {
-		if ((val = switch_channel_get_variable(channel, "sip_codec_negotiation"))) {
-			if (!strcasecmp(val, "greedy")) {
-				greedy = 1;
-			} else if (!strcasecmp(val, "scrooge")) {
-				scrooge = 1;
-				greedy = 1;
-			}
-		}
+	if ((val = switch_channel_get_variable(channel, "sip_codec_negotiation"))) {
+		if (!strcasecmp(val, "generous")) {
+			greedy = 0;
+			scrooge = 0;
+			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sip_codec_negotiation overriding sofia inbound-codec-negotiation : generous\n" );
+		} else if (!strcasecmp(val, "greedy")) {
+			greedy = 1;
+			scrooge = 0;
+			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sip_codec_negotiation overriding sofia inbound-codec-negotiation : greedy\n" );
+		} else if (!strcasecmp(val, "scrooge")) {
+			scrooge = 1;
+			greedy = 1;
+			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sip_codec_negotiation overriding sofia inbound-codec-negotiation : scrooge\n" );
+		} else {
+		    switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sip_codec_negotiation ignored invalid value : '%s' \n", val );	
+		}		
 	}
 
 	if ((tech_pvt->origin = switch_core_session_strdup(session, (char *) sdp->sdp_origin->o_username))) {
committer: Jeff Lenk
comments: 
VS2010 fix minor build order problem

diff --git a/libs/win32/sofia/libsofia_sip_ua_static.2010.vcxproj b/libs/win32/sofia/libsofia_sip_ua_static.2010.vcxproj
index d841b89..be91504 100644
--- a/libs/win32/sofia/libsofia_sip_ua_static.2010.vcxproj
+++ b/libs/win32/sofia/libsofia_sip_ua_static.2010.vcxproj
@@ -508,6 +508,12 @@ if not exist "$(ProjectDir)$(IntDir)\auth_client.obj" "autogen.cmd"
       <Project>{8b3b4c4c-13c2-446c-beb0-f412cc2cfb9a}</Project>
       <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
     </ProjectReference>
+    <ProjectReference Include="..\openssl\libeay32.2010.vcxproj">
+      <Project>{d331904d-a00a-4694-a5a3-fcff64ab5dbe}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\openssl\ssleay32.2010.vcxproj">
+      <Project>{b4b62169-5ad4-4559-8707-3d933ac5db39}</Project>
+    </ProjectReference>
     <ProjectReference Include="..\pthread\pthread.2010.vcxproj">
       <Project>{df018947-0fff-4eb3-bdee-441dc81da7a4}</Project>
       <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
committer: Anthony Minessale
comments: 
fix possible bad pointer in global vars (please test)

diff --git a/fscomm/widgets/codecwidget.cpp b/fscomm/widgets/codecwidget.cpp
index 42b10fe..2f82e1a 100644
--- a/fscomm/widgets/codecwidget.cpp
+++ b/fscomm/widgets/codecwidget.cpp
@@ -131,6 +131,8 @@ void CodecWidget::setCodecString(QString codecList)
         QStringList parsed = codecList.split("{");
         QString var = parsed.at(1);
         var = var.split("}").at(0);
+		// warning switch_core_get_Variable may return an unsafe pointer in some cases.
+		// revise to use switch_core_get_variable_dup, and then free it after you are done.
         var = switch_core_get_variable(var.toAscii().data());
         if ( ! var.isEmpty() ) {
             codecList = var;
committer: Anthony Minessale
comments: 
only pass publish on when you have a subscription

diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c
index 19125c6..a38a61e 100644
--- a/src/mod/endpoints/mod_sofia/sofia_presence.c
+++ b/src/mod/endpoints/mod_sofia/sofia_presence.c
@@ -2570,6 +2570,19 @@ static int sofia_counterpath_crutch(void *pArg, int argc, char **argv, char **co
 	return 0;
 }
 
+
+uint32_t sofia_presence_contact_count(sofia_profile_t *profile, const char *contact_str)
+{
+	char buf[32] = "";
+	char *sql;
+	
+	sql = switch_mprintf("select count(*) from sip_subscriptions where profile_name='%q' and contact_str='%q'", profile->name, contact_str);
+	
+	sofia_glue_execute_sql2str(profile, profile->ireg_mutex, sql, buf, sizeof(buf));
+	switch_safe_free(sql);
+	return atoi(buf);				
+}
+
 void sofia_presence_handle_sip_i_publish(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
 										 tagi_t tags[])
 {
@@ -2584,7 +2597,7 @@ void sofia_presence_handle_sip_i_publish(nua_t *nua, sofia_profile_t *profile, n
 	char expstr[30] = "";
 	long exp = 0, exp_delta = 3600;
 	char *pd_dup = NULL;
-	int count = 1;
+	int count = 1, sub_count = 0;
 	char *contact_str;
 	int open = 1;
 
@@ -2667,24 +2680,25 @@ void sofia_presence_handle_sip_i_publish(nua_t *nua, sofia_profile_t *profile, n
 				count = sofia_reg_reg_count(profile, from_user, from_host);
 			}
 				
+			sub_count = sofia_presence_contact_count(profile, contact_str);
 
 			/* if (count > 1) let's not and say we did or all the clients who subscribe to their own presence will think they selves is offline */
 
 			event_type = sip_header_as_string(profile->home, (void *) sip->sip_event);
 
 			if (count < 2) {
-				if ((sql =
-					 switch_mprintf("delete from sip_presence where sip_user='%q' and sip_host='%q' "
-									" and profile_name='%q' and hostname='%q'", from_user, from_host, profile->name, mod_sofia_globals.hostname))) {
+				if ((sql = switch_mprintf("delete from sip_presence where sip_user='%q' and sip_host='%q' "
+										  " and profile_name='%q' and hostname='%q'", 
+										  from_user, from_host, profile->name, mod_sofia_globals.hostname))) {
 					sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
 				}
 					
-				if ((sql =
-					 switch_mprintf("insert into sip_presence (sip_user, sip_host, status, rpid, expires, user_agent,"
-									" profile_name, hostname, open_closed) "
-									"values ('%q','%q','%q','%q',%ld,'%q','%q','%q','%q')",
-									from_user, from_host, note_txt, rpid, exp, full_agent, profile->name, mod_sofia_globals.hostname, open_closed))) {
-						
+				if (sub_count > 0 && (sql = switch_mprintf("insert into sip_presence (sip_user, sip_host, status, rpid, expires, user_agent,"
+														   " profile_name, hostname, open_closed) "
+														   "values ('%q','%q','%q','%q',%ld,'%q','%q','%q','%q')",
+														   from_user, from_host, note_txt, rpid, exp, full_agent, profile->name, 
+														   mod_sofia_globals.hostname, open_closed))) {
+					
 					sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
 				}
 				
@@ -2696,16 +2710,17 @@ void sofia_presence_handle_sip_i_publish(nua_t *nua, sofia_profile_t *profile, n
 				switch_safe_free(sql);
 			}
 
-
-			if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
-				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO);
-				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", rpid);
-				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url);
-				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "user-agent", full_agent);
-				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host);
-				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", note_txt);
-				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", event_type);
-				switch_event_fire(&event);
+			if (sub_count > 0) {
+				if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
+					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO);
+					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", rpid);
+					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url);
+					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "user-agent", full_agent);
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host);
+					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", note_txt);
+					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", event_type);
+					switch_event_fire(&event);
+				}
 			}
 
 			if (event_type) {
@@ -2728,7 +2743,12 @@ void sofia_presence_handle_sip_i_publish(nua_t *nua, sofia_profile_t *profile, n
 
 	switch_snprintf(expstr, sizeof(expstr), "%d", exp_delta);
 	switch_stun_random_string(etag, 8, NULL);
-	nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), SIPTAG_ETAG_STR(etag), SIPTAG_EXPIRES_STR(expstr), TAG_END());
+
+	if (sub_count > 0) {
+		nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), SIPTAG_ETAG_STR(etag), SIPTAG_EXPIRES_STR(expstr), TAG_END());
+	} else {
+		nua_respond(nh, SIP_404_NOT_FOUND, NUTAG_WITH_THIS(nua), TAG_END());
+	}
 
 	switch_safe_free(contact_str);
 }
committer: Anthony Minessale
comments: 
fix possible bad pointer in global vars (please test)

diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c
index 970cb5b..2ef21cc 100755
--- a/libs/freetdm/mod_freetdm/mod_freetdm.c
+++ b/libs/freetdm/mod_freetdm/mod_freetdm.c
@@ -1067,9 +1067,16 @@ static const char* channel_get_variable(switch_core_session_t *session, switch_e
                        return variable;
                }
        }
+
+
+	   // This is unsafe, I don't see anywhere in the whole code where this is called with NULL session anyway.
+	   // There is a new switch_core_get_variable_dup that will strdup it for you and then you must free it.
+	   // That messes up the abstraction completely so I am just commenting it out for you.....
+	   /*
        if ((variable = switch_core_get_variable(variable_name))) {
                return variable;
        }
+	   */
        return NULL;
 }
 
diff --git a/libs/openzap/mod_openzap/mod_openzap.c b/libs/openzap/mod_openzap/mod_openzap.c
index d52149c..ef346b8 100644
--- a/libs/openzap/mod_openzap/mod_openzap.c
+++ b/libs/openzap/mod_openzap/mod_openzap.c
@@ -1234,19 +1234,19 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
 		zap_set_string(caller_data.ani.digits, dest);
 	}
 	
-	if ((var = switch_event_get_header(var_event, "openzap_outbound_ton")) || (var = switch_core_get_variable("openzap_outbound_ton"))) {
+	if ((var = switch_event_get_header(var_event, "openzap_outbound_ton"))) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Setting TON to: %s\n", var);
 		zap_set_ton(var, &caller_data.ani.type);
 	} else {
 		caller_data.ani.type = outbound_profile->destination_number_ton;
 	}
 
-	if ((var = switch_event_get_header(var_event, "openzap_custom_call_data")) || (var = switch_core_get_variable("openzap_custom_call_data"))) {
+	if ((var = switch_event_get_header(var_event, "openzap_custom_call_data"))) {
 		zap_set_string((char *)caller_data.raw_data, var);
 		caller_data.raw_data_len = strlen(var);
 	}
 	
-	if ((var = switch_event_get_header(var_event, "openzap_outbound_npi")) || (var = switch_core_get_variable("openzap_outbound_npi"))) {
+	if ((var = switch_event_get_header(var_event, "openzap_outbound_npi"))) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Setting NPI to: %s\n", var);
 		zap_set_npi(var, &caller_data.ani.plan);
 	} else {
committer: Anthony Minessale
comments: 
fix possible bad pointer in global vars (please test)

diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h
index 30690b1..05cd24d 100644
--- a/src/include/private/switch_core_pvt.h
+++ b/src/include/private/switch_core_pvt.h
@@ -246,6 +246,7 @@ struct switch_runtime {
 	int sql_buffer_len;
 	int max_sql_buffer_len;
 	switch_dbtype_t odbc_dbtype;
+	char hostname[256];
 };
 
 extern struct switch_runtime runtime;
diff --git a/src/include/switch_core.h b/src/include/switch_core.h
index 109a169..69b0642 100644
--- a/src/include/switch_core.h
+++ b/src/include/switch_core.h
@@ -759,6 +759,9 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_force_locate(_In_z_
   \return the value of the desired variable
 */
 SWITCH_DECLARE(char *) switch_core_get_variable(_In_z_ const char *varname);
+SWITCH_DECLARE(char *) switch_core_get_variable_dup(_In_z_ const char *varname);
+SWITCH_DECLARE(char *) switch_core_get_variable_pdup(_In_z_ const char *varname, switch_memory_pool_t *pool);
+SWITCH_DECLARE(const char *) switch_core_get_hostname(void);
 
 /*! 
   \brief Add a global variable to the core
diff --git a/src/include/switch_nat.h b/src/include/switch_nat.h
index bdbd51b..9e40546 100644
--- a/src/include/switch_nat.h
+++ b/src/include/switch_nat.h
@@ -49,7 +49,7 @@ typedef enum {
 	SWITCH_NAT_TCP
 } switch_nat_ip_proto_t;
 
-
+SWITCH_DECLARE(const char *) switch_nat_get_type(void);
 
 /*! 
   \brief Initilize the NAT Traversal System
diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c
index 7771b09..807770a 100644
--- a/src/mod/applications/mod_commands/mod_commands.c
+++ b/src/mod/applications/mod_commands/mod_commands.c
@@ -349,7 +349,7 @@ SWITCH_STANDARD_API(timer_test_function)
 
 SWITCH_STANDARD_API(group_call_function)
 {
-	char *domain;
+	char *domain, *dup_domain = NULL;
 	char *group_name = NULL;
 	char *flags;
 	int ok = 0;
@@ -392,7 +392,9 @@ SWITCH_STANDARD_API(group_call_function)
 	if (domain) {
 		*domain++ = '\0';
 	} else {
-		domain = switch_core_get_variable("domain");
+		if ((dup_domain = switch_core_get_variable_dup("domain"))) {
+			domain = dup_domain;
+		}
 	}
 
 	if (!zstr(domain)) {
@@ -544,13 +546,14 @@ SWITCH_STANDARD_API(group_call_function)
 	}
 
   end:
-
+	
 	switch_safe_free(group_name);
+	switch_safe_free(dup_domain);
 
 	if (!ok) {
 		stream->write_function(stream, "error/NO_ROUTE_DESTINATION");
 	}
-
+	
 	return SWITCH_STATUS_SUCCESS;
 }
 
@@ -559,7 +562,7 @@ SWITCH_STANDARD_API(in_group_function)
 {
 	switch_xml_t x_domain, xml = NULL, x_user = NULL, x_group;
 	int argc;
-	char *mydata = NULL, *argv[2], *user, *domain;
+	char *mydata = NULL, *argv[2], *user, *domain, *dup_domain = NULL;
 	char delim = ',';
 	switch_event_t *params = NULL;
 	const char *rval = "false";
@@ -579,7 +582,9 @@ SWITCH_STANDARD_API(in_group_function)
 	if ((domain = strchr(user, '@'))) {
 		*domain++ = '\0';
 	} else {
-		domain = switch_core_get_variable("domain");
+		if ((dup_domain = switch_core_get_variable_dup("domain"))) {
+			domain = dup_domain;
+		}
 	}
 
 	switch_event_create(&params, SWITCH_EVENT_REQUEST_PARAMS);
@@ -601,6 +606,7 @@ SWITCH_STANDARD_API(in_group_function)
 
 	switch_xml_free(xml);
 	switch_safe_free(mydata);
+	switch_safe_free(dup_domain);
 	switch_event_destroy(&params);
 
 	return SWITCH_STATUS_SUCCESS;
@@ -610,7 +616,7 @@ SWITCH_STANDARD_API(user_data_function)
 {
 	switch_xml_t x_domain, xml = NULL, x_user = NULL, x_group = NULL, x_param, x_params;
 	int argc;
-	char *mydata = NULL, *argv[3], *key = NULL, *type = NULL, *user, *domain;
+	char *mydata = NULL, *argv[3], *key = NULL, *type = NULL, *user, *domain, *dup_domain = NULL;
 	char delim = ' ';
 	const char *container = "params", *elem = "param";
 	const char *result = NULL;
@@ -631,7 +637,9 @@ SWITCH_STANDARD_API(user_data_function)
 	if ((domain = strchr(user, '@'))) {
 		*domain++ = '\0';
 	} else {
-		if (!(domain = switch_core_get_variable("domain"))) {
+		if ((dup_domain = switch_core_get_variable("domain"))) {
+			domain = dup_domain;
+		} else {
 			domain = "cluecon.com";
 		}
 	}
@@ -694,6 +702,7 @@ SWITCH_STANDARD_API(user_data_function)
 	}
 	switch_xml_free(xml);
 	switch_safe_free(mydata);
+	switch_safe_free(dup_domain);
 	switch_event_destroy(&params);
 
 	return SWITCH_STATUS_SUCCESS;
@@ -4375,7 +4384,9 @@ SWITCH_STANDARD_API(global_getvar_function)
 	if (zstr(cmd)) {
 		switch_core_dump_variables(stream);
 	} else {
-		stream->write_function(stream, "%s", switch_str_nil(switch_core_get_variable(cmd)));
+		char *var = switch_core_get_variable_dup(cmd);
+		stream->write_function(stream, "%s", switch_str_nil(var));
+		switch_safe_free(var);
 	}
 	return SWITCH_STATUS_SUCCESS;
 }
diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c
index 928a9b8..4be2a64 100755
--- a/src/mod/applications/mod_dptools/mod_dptools.c
+++ b/src/mod/applications/mod_dptools/mod_dptools.c
@@ -2787,7 +2787,7 @@ static switch_call_cause_t group_outgoing_channel(switch_core_session_t *session
 	if ((domain = strchr(group, '@'))) {
 		*domain++ = '\0';
 	} else {
-		domain = switch_core_get_variable("domain");
+		domain = switch_core_get_variable_pdup("domain", switch_core_session_get_pool(session));
 	}
 
 	if (!domain) {
@@ -2908,7 +2908,7 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
 	if ((domain = strchr(user, '@'))) {
 		*domain++ = '\0';
 	} else {
-		domain = switch_core_get_variable("domain");
+		domain = switch_core_get_variable_pdup("domain", switch_core_session_get_pool(session));
 	}
 
 	if (!domain) {
@@ -3193,10 +3193,11 @@ static switch_status_t event_chat_send(const char *proto, const char *from, cons
 		if (body)
 			switch_event_add_body(event, "%s", body);
 		if (to) {
-			const char *v;
+			char *v;
 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "To", to);
-			if ((v = switch_core_get_variable(to))) {
+			if ((v = switch_core_get_variable_dup(to))) {
 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Command", v);
+				free(v);
 			}
 		}
 
@@ -3214,15 +3215,15 @@ static switch_status_t api_chat_send(const char *proto, const char *from, const
 									 const char *body, const char *type, const char *hint)
 {
 	if (to) {
-		const char *v;
+		char *v = NULL;
 		switch_stream_handle_t stream = { 0 };
 		char *cmd = NULL, *arg;
 
-		if (!(v = switch_core_get_variable(to))) {
-			v = to;
+		if (!(v = switch_core_get_variable_dup(to))) {
+			v = strdup(to);
 		}
 
-		cmd = strdup(v);
+		cmd = v;
 		switch_assert(cmd);
 
 		switch_url_decode(cmd);
diff --git a/src/mod/applications/mod_redis/mod_redis.c b/src/mod/applications/mod_redis/mod_redis.c
index 1e99967..ebf2a9e 100755
--- a/src/mod/applications/mod_redis/mod_redis.c
+++ b/src/mod/applications/mod_redis/mod_redis.c
@@ -89,7 +89,7 @@ SWITCH_LIMIT_INCR(limit_incr_redis)
 	}
 	
 	/* Get the keys for redis server */
-	uuid_rediskey = switch_core_session_sprintf(session,"%s_%s_%s", switch_core_get_variable("hostname"), realm, resource);
+	uuid_rediskey = switch_core_session_sprintf(session,"%s_%s_%s", switch_core_get_hostname(), realm, resource);
 	rediskey = switch_core_session_sprintf(session, "%s_%s", realm, resource);
 
 	if ((pvt = switch_channel_get_private(channel, "limit_redis"))) {
@@ -179,7 +179,7 @@ SWITCH_LIMIT_RELEASE(limit_release_redis)
 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Couldn't decrement value corresponding to %s\n", (char *)p_key);
 				switch_goto_status(SWITCH_STATUS_FALSE, end);
 			}
-	   		p_uuid_key = switch_core_session_sprintf(session, "%s_%s", switch_core_get_variable("hostname"), (char *)p_key);
+	   		p_uuid_key = switch_core_session_sprintf(session, "%s_%s", switch_core_get_hostname(), (char *)p_key);
 			if (credis_decr(redis,p_uuid_key,&uuid_val) != 0) {
 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Couldn't decrement value corresponding to %s\n", p_uuid_key);
 				switch_goto_status(SWITCH_STATUS_FALSE, end);
@@ -193,7 +193,7 @@ SWITCH_LIMIT_RELEASE(limit_release_redis)
 	
 	} else {	
 	   	rediskey = switch_core_session_sprintf(session, "%s_%s", realm, resource);
-		uuid_rediskey = switch_core_session_sprintf(session, "%s_%s_%s", switch_core_get_variable("hostname"), realm, resource);
+		uuid_rediskey = switch_core_session_sprintf(session, "%s_%s_%s", switch_core_get_hostname(), realm, resource);
 		switch_core_hash_delete(pvt->hash, (const char *) rediskey);
 
 		if (credis_decr(redis, rediskey, &val) != 0) {
@@ -249,13 +249,13 @@ SWITCH_LIMIT_RESET(limit_reset_redis)
 {
 	REDIS redis;
 	if (redis_factory(&redis) == SWITCH_STATUS_SUCCESS) {
-		char *rediskey = switch_mprintf("%s_*", switch_core_get_variable("hostname"));
+		char *rediskey = switch_mprintf("%s_*", switch_core_get_hostname());
 		int dec = 0, val = 0, keyc;
 		char *uuids[2000];
 	
 		if ((keyc = credis_keys(redis, rediskey, uuids, switch_arraylen(uuids))) > 0) {
 			int i = 0;
-			int hostnamelen = strlen(switch_core_get_variable("hostname"))+1;
+			int hostnamelen = strlen(switch_core_get_hostname())+1;
 			
 			for (i = 0; i < keyc && uuids[i]; i++){
 				const char *key = uuids[i] + hostnamelen;
diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c
index 76870f7..80b011e 100644
--- a/src/mod/applications/mod_voicemail/mod_voicemail.c
+++ b/src/mod/applications/mod_voicemail/mod_voicemail.c
@@ -2734,6 +2734,7 @@ static switch_status_t voicemail_inject(const char *data, switch_core_session_t
 	switch_memory_pool_t *pool = NULL;
 	char *forwarded_by = NULL;
 	char *read_flags = NORMAL_FLAG_STRING;
+	char *dup_domain = NULL;
 	
 	if (zstr(data)) {
 		status = SWITCH_STATUS_FALSE;
@@ -2781,7 +2782,9 @@ static switch_status_t voicemail_inject(const char *data, switch_core_session_t
 	}
 
 	if (zstr(domain)) {
-		domain = switch_core_get_variable("domain");
+		if ((dup_domain = switch_core_get_variable_dup("domain"))) {
+			domain = dup_domain;
+		}
 		profile_name = domain;
 	}
 
@@ -2915,6 +2918,7 @@ static switch_status_t voicemail_inject(const char *data, switch_core_session_t
   end:
 
 	switch_safe_free(dup);
+	switch_safe_free(dup_domain);
 
 	return status;
 }
diff --git a/src/mod/dialplans/mod_dialplan_asterisk/mod_dialplan_asterisk.c b/src/mod/dialplans/mod_dialplan_asterisk/mod_dialplan_asterisk.c
index 5869d14..43534da 100644
--- a/src/mod/dialplans/mod_dialplan_asterisk/mod_dialplan_asterisk.c
+++ b/src/mod/dialplans/mod_dialplan_asterisk/mod_dialplan_asterisk.c
@@ -313,7 +313,7 @@ static switch_call_cause_t sip_outgoing_channel(switch_core_session_t *session,
 	if (session) {
 		profile = switch_channel_get_variable(switch_core_session_get_channel(session), "sip_profile");
 	} else {
-		profile = switch_core_get_variable("sip_profile");
+		profile = switch_core_get_variable_pdup("sip_profile", switch_core_session_get_pool(session));
 	}
 	if (zstr(profile)) {
 		profile = "default";
diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c
index 66f62b2..9fb1f39 100644
--- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c
+++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c
@@ -2049,7 +2049,7 @@ static void set_profile_val(mdl_profile_t *profile, char *var, char *val)
 	} else if (!strcasecmp(var, "ext-rtp-ip")) {
 		char *ip = globals.guess_ip;
 		if (val && !strcasecmp(val, "auto-nat")) {
-			ip = globals.auto_nat ? switch_core_get_variable("nat_public_addr") : globals.guess_ip;
+			ip = globals.auto_nat ? switch_core_get_variable_pdup("nat_public_addr", module_pool) : globals.guess_ip;
 		} else if (val && !strcasecmp(val, "auto")) {
 			globals.auto_nat = 0;
 			ip = globals.guess_ip;
@@ -2523,7 +2523,7 @@ static switch_status_t load_config(void)
 
 	memset(&globals, 0, sizeof(globals));
 	globals.running = 1;
-	globals.auto_nat = (switch_core_get_variable("nat_type") ? 1 : 0);
+	globals.auto_nat = (switch_nat_get_type() ? 1 : 0);
 
 	switch_find_local_ip(globals.guess_ip, sizeof(globals.guess_ip), NULL, AF_INET);
 
diff --git a/src/mod/endpoints/mod_khomp/src/khomp_pvt.cpp b/src/mod/endpoints/mod_khomp/src/khomp_pvt.cpp
index 1b126eb..15009f2 100644
--- a/src/mod/endpoints/mod_khomp/src/khomp_pvt.cpp
+++ b/src/mod/endpoints/mod_khomp/src/khomp_pvt.cpp
@@ -1625,9 +1625,10 @@ bool Board::KhompPvt::setCollectCall()
     DBG(FUNC, PVT_FMT(_target, "option drop collect call is '%s'") % (Opt::_options._drop_collect_call() ? "yes" : "no"));
 
     // get global filter configuration value
-    tmp_var = switch_core_get_variable("KDropCollectCall");
+    tmp_var = switch_core_get_variable_dup("KDropCollectCall");
     confvalues.push_back(getTriStateValue(tmp_var));
     DBG(FUNC, PVT_FMT(_target, "global KDropCollectCall was '%s'") % (tmp_var ? tmp_var : "(empty)"));
+	switch_safe_free(tmp_var);
 
     try 
     {
diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c
index 8bceb3b..c78aac7 100644
--- a/src/mod/endpoints/mod_sofia/mod_sofia.c
+++ b/src/mod/endpoints/mod_sofia/mod_sofia.c
@@ -3501,7 +3501,7 @@ SWITCH_STANDARD_API(sofia_contact_function)
 	}
 
 	if (zstr(domain)) {
-		domain = switch_core_get_variable("domain");
+		domain = switch_core_get_variable_pdup("domain", switch_core_session_get_pool(session));
 	}
 
 	if (!user) goto end;
@@ -4776,7 +4776,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
 	mod_sofia_globals.running = 1;
 	switch_mutex_unlock(mod_sofia_globals.mutex);
 
-	mod_sofia_globals.auto_nat = (switch_core_get_variable("nat_type") ? 1 : 0);
+	mod_sofia_globals.auto_nat = (switch_nat_get_type() ? 1 : 0);
 
 	switch_queue_create(&mod_sofia_globals.presence_queue, SOFIA_QUEUE_SIZE, mod_sofia_globals.pool);
 	switch_queue_create(&mod_sofia_globals.mwi_queue, SOFIA_QUEUE_SIZE, mod_sofia_globals.pool);
diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c
index 47f94b1..825d1bf 100644
--- a/src/mod/endpoints/mod_sofia/sofia.c
+++ b/src/mod/endpoints/mod_sofia/sofia.c
@@ -1459,7 +1459,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
 
 	supported = switch_core_sprintf(profile->pool, "%s%sprecondition, path, replaces", use_100rel ? "100rel, " : "", use_timer ? "timer, " : "");
 
-	if (sofia_test_pflag(profile, PFLAG_AUTO_NAT) && switch_core_get_variable("nat_type")) {
+	if (sofia_test_pflag(profile, PFLAG_AUTO_NAT) && switch_nat_get_type()) {
 		if (switch_nat_add_mapping(profile->sip_port, SWITCH_NAT_UDP, NULL, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Created UDP nat mapping for %s port %d\n", profile->name, profile->sip_port);
 		}
@@ -1676,7 +1676,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
 		switch_event_fire(&s_event);
 	}
 
-	if (sofia_test_pflag(profile, PFLAG_AUTO_NAT) && switch_core_get_variable("nat_type")) {
+	if (sofia_test_pflag(profile, PFLAG_AUTO_NAT) && switch_nat_get_type()) {
 		if (switch_nat_del_mapping(profile->sip_port, SWITCH_NAT_UDP) == SWITCH_STATUS_SUCCESS) {
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Deleted UDP nat mapping for %s port %d\n", profile->name, profile->sip_port);
 		}
@@ -3741,9 +3741,9 @@ switch_status_t config_sofia(int reload, char *profile_name)
 				if (!profile->rtpip[0]) {
 					profile->rtpip[profile->rtpip_index++] = switch_core_strdup(profile->pool, mod_sofia_globals.guess_ip);
 				}
-
-				if (switch_core_get_variable("nat_type")) {
-					const char *ip = switch_core_get_variable("nat_public_addr");
+				
+				if (switch_nat_get_type()) {
+					char *ip = switch_core_get_variable_dup("nat_public_addr");
 					if (ip && !strchr(profile->sipip, ':')) {
 						if (!profile->extrtpip) {
 							profile->extrtpip = switch_core_strdup(profile->pool, ip);
@@ -3754,6 +3754,7 @@ switch_status_t config_sofia(int reload, char *profile_name)
 						sofia_set_pflag(profile, PFLAG_AUTO_NAT);
 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "NAT detected setting external ip to %s\n", ip);
 					}
+					switch_safe_free(ip);
 				}
 
 				if (profile->nonce_ttl < 60) {
diff --git a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c
index f3a2c92..1462e4e 100644
--- a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c
+++ b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c
@@ -2642,7 +2642,7 @@ static int config(void)
 				} else if (!strcmp(var, "debug")) {
 					globals.debug = atoi(val);
 				} else if (!strcmp(var, "nat-map")) {
-					if (switch_true(val) && switch_core_get_variable("nat_type")) {
+					if (switch_true(val) && switch_nat_get_type()) {
 						prefs.nat_map = 1;
 					}
 				} else if (!strcmp(var, "listen-port")) {
@@ -2795,7 +2795,7 @@ SWITCH_MODULE_RUNTIME_FUNCTION(mod_event_socket_runtime)
 
 	close_socket(&listen_list.sock);
 
-	if (prefs.nat_map && switch_core_get_variable("nat_type")) {
+	if (prefs.nat_map && switch_nat_get_type()) {
 		switch_nat_del_mapping(prefs.port, SWITCH_NAT_TCP);
 	}
 
diff --git a/src/mod/formats/mod_file_string/mod_file_string.c b/src/mod/formats/mod_file_string/mod_file_string.c
index ca86cbd..7e36c72 100644
--- a/src/mod/formats/mod_file_string/mod_file_string.c
+++ b/src/mod/formats/mod_file_string/mod_file_string.c
@@ -77,7 +77,7 @@ static int next_file(switch_file_handle_t *handle)
 
 
 	if (!prefix) {
-		if (!(prefix = switch_core_get_variable("sound_prefix"))) {
+		if (!(prefix = switch_core_get_variable_pdup("sound_prefix", handle->memory_pool))) {
 			prefix = SWITCH_GLOBAL_dirs.sounds_dir;
 		}
 	}
diff --git a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
index 9eb2636..1d6ee8d 100644
--- a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
+++ b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
@@ -3378,8 +3378,9 @@ static JSBool js_global_get(JSContext * cx, JSObject * obj, uintN argc, jsval *
 
 	if (argc > 0) {
 		var_name = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
-		val = switch_core_get_variable(var_name);
+		val = switch_core_get_variable_dup(var_name);
 		*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, val));
+		free(val);
 		return JS_TRUE;
 	}
 
diff --git a/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c b/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c
index 468190d..9e61312 100644
--- a/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c
+++ b/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c
@@ -322,6 +322,7 @@ static abyss_bool http_directory_auth(TSession * r, char *domain_name)
 	int at = 0;
 	char *dp;
 	abyss_bool rval = FALSE;
+	char *dup_domain = NULL;
 
 	p = RequestHeaderValue(r, "authorization");
 
@@ -354,7 +355,9 @@ static abyss_bool http_directory_auth(TSession * r, char *domain_name)
 						if (globals.default_domain) {
 							domain_name = globals.default_domain;
 						} else {
-							domain_name = switch_core_get_variable("domain");
+							if ((dup_domain = switch_core_get_variable_dup("domain"))) {
+								domain_name = dup_domain;
+							}
 						}
 					}
 				}
@@ -465,6 +468,7 @@ static abyss_bool http_directory_auth(TSession * r, char *domain_name)
 	switch_safe_free(mypass1);
 	switch_safe_free(mypass2);
 	switch_safe_free(box);
+	switch_safe_free(dup_domain);
 
 	return rval;
 }
diff --git a/src/switch_channel.c b/src/switch_channel.c
index 70b1879..f750496 100644
--- a/src/switch_channel.c
+++ b/src/switch_channel.c
@@ -672,7 +672,7 @@ SWITCH_DECLARE(const char *) switch_channel_get_hold_music_partner(switch_channe
 
 SWITCH_DECLARE(const char *) switch_channel_get_variable_dup(switch_channel_t *channel, const char *varname, switch_bool_t dup)
 {
-	const char *v = NULL, *r = NULL;
+	const char *v = NULL, *r = NULL, *vdup = NULL;
 	switch_assert(channel != NULL);
 
 	switch_mutex_lock(channel->profile_mutex);
@@ -690,13 +690,16 @@ SWITCH_DECLARE(const char *) switch_channel_get_variable_dup(switch_channel_t *c
 		}
 
 		if (!cp || !(v = switch_caller_get_field_by_name(cp, varname))) {
-			v = switch_core_get_variable(varname);
+			if ((vdup = switch_core_get_variable_pdup(varname, switch_core_session_get_pool(channel->session)))) {
+				v = vdup;
+			}
 		}
 	}
 
-	if (dup) {
-		if (v)
+	if (dup && v != vdup) {
+		if (v) {
 			r = switch_core_session_strdup(channel->session, v);
+		}
 	} else {
 		r = v;
 	}
diff --git a/src/switch_console.c b/src/switch_console.c
index 41bbb91..c5d601b 100644
--- a/src/switch_console.c
+++ b/src/switch_console.c
@@ -643,9 +643,9 @@ SWITCH_DECLARE_NONSTD(switch_status_t) switch_console_list_uuid(const char *line
 
 	if (!zstr(cursor)) {
 		sql = switch_mprintf("select distinct uuid from channels where uuid like '%q%%' and hostname='%q' order by uuid",
-							 cursor, switch_core_get_variable("hostname"));
+							 cursor, switch_core_get_hostname());
 	} else {
-		sql = switch_mprintf("select distinct uuid from channels where hostname='%q' order by uuid", switch_core_get_variable("hostname"));
+		sql = switch_mprintf("select distinct uuid from channels where hostname='%q' order by uuid", switch_core_get_hostname());
 	}
 
 	switch_cache_db_execute_sql_callback(db, sql, uuid_callback, &h, &errmsg);
@@ -764,7 +764,7 @@ SWITCH_DECLARE(unsigned char) switch_console_complete(const char *line, const ch
 
 	if (h.words == 0) {
 		sql = switch_mprintf("select distinct name from interfaces where type='api' and name like '%q%%' and hostname='%q' order by name",
-							 buf, switch_core_get_variable("hostname"));
+							 buf, switch_core_get_hostname());
 	}
 
 	if (sql) {
@@ -792,7 +792,7 @@ SWITCH_DECLARE(unsigned char) switch_console_complete(const char *line, const ch
 
 		if (h.words == 0) {
 			stream.write_function(&stream, "select distinct a1 from complete where " "a1 not in (select name from interfaces where hostname='%s') %s ",
-								  switch_core_get_variable("hostname"), argc ? "and" : "");
+								  switch_core_get_hostname(), argc ? "and" : "");
 		} else {
 			if (db->type == SCDB_TYPE_CORE_DB) {
 				stream.write_function(&stream, "select distinct a%d,'%q','%q' from complete where ", h.words + 1, switch_str_nil(dup), switch_str_nil(lp));
@@ -821,7 +821,7 @@ SWITCH_DECLARE(unsigned char) switch_console_complete(const char *line, const ch
 			}
 		}
 
-		stream.write_function(&stream, " and hostname='%s' order by a%d", switch_core_get_variable("hostname"), h.words + 1);
+		stream.write_function(&stream, " and hostname='%s' order by a%d", switch_core_get_hostname(), h.words + 1);
 		
 		switch_cache_db_execute_sql_callback(db, stream.data, comp_callback, &h, &errmsg);
 
@@ -1794,7 +1794,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_complete(const char *string)
 						}
 					}
 				}
-				mystream.write_function(&mystream, " '%s')", switch_core_get_variable("hostname"));
+				mystream.write_function(&mystream, " '%s')", switch_core_get_hostname());
 				switch_cache_db_persistant_execute(db, mystream.data, 5);
 				status = SWITCH_STATUS_SUCCESS;
 			} else if (!strcasecmp(argv[0], "add")) {
@@ -1810,7 +1810,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_complete(const char *string)
 						}
 					}
 				}
-				mystream.write_function(&mystream, " '%s')", switch_core_get_variable("hostname"));
+				mystream.write_function(&mystream, " '%s')", switch_core_get_hostname());
 
 				switch_cache_db_persistant_execute(db, mystream.data, 5);
 				status = SWITCH_STATUS_SUCCESS;
@@ -1827,7 +1827,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_complete(const char *string)
 							mystream.write_function(&mystream, "a%d = '%w'%w", x + 1, switch_str_nil(argv[x + 1]), x == argc - 2 ? "" : " and ");
 						}
 					}
-					mystream.write_function(&mystream, " and hostname='%s'", switch_core_get_variable("hostname"));
+					mystream.write_function(&mystream, " and hostname='%s'", switch_core_get_hostname());
 					switch_cache_db_persistant_execute(db, mystream.data, 1);
 				}
 				status = SWITCH_STATUS_SUCCESS;
@@ -1863,38 +1863,38 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_alias(const char *string)
 			}
 			
 			if (!strcasecmp(argv[0], "stickyadd") && argc == 3) {
-				sql = switch_mprintf("delete from aliases where alias='%q' and hostname='%q'", argv[1], switch_core_get_variable("hostname"));
+				sql = switch_mprintf("delete from aliases where alias='%q' and hostname='%q'", argv[1], switch_core_get_hostname());
 				switch_cache_db_persistant_execute(db, sql, 5);
 				switch_safe_free(sql);
 				if (db->type == SCDB_TYPE_CORE_DB) {
 					sql = switch_mprintf("insert into aliases (sticky, alias, command, hostname) values (1, '%q','%q','%q')",
-										 argv[1], argv[2], switch_core_get_variable("hostname"));
+										 argv[1], argv[2], switch_core_get_hostname());
 				} else {
 					sql = switch_mprintf("insert into aliases (sticky, alias, command, hostname) values (1, '%w','%w','%w')",
-										 argv[1], argv[2], switch_core_get_variable("hostname"));
+										 argv[1], argv[2], switch_core_get_hostname());
 				}
 				switch_cache_db_persistant_execute(db, sql, 5);
 				status = SWITCH_STATUS_SUCCESS;
 			} else if (!strcasecmp(argv[0], "add") && argc == 3) {
-				sql = switch_mprintf("delete from aliases where alias='%q' and hostname='%q'", argv[1], switch_core_get_variable("hostname"));
+				sql = switch_mprintf("delete from aliases where alias='%q' and hostname='%q'", argv[1], switch_core_get_hostname());
 				switch_cache_db_persistant_execute(db, sql, 5);
 				switch_safe_free(sql);
 				if (db->type == SCDB_TYPE_CORE_DB) {
 					sql = switch_mprintf("insert into aliases (sticky, alias, command, hostname) values (0, '%q','%q','%q')",
-										 argv[1], argv[2], switch_core_get_variable("hostname"));
+										 argv[1], argv[2], switch_core_get_hostname());
 				} else {
 					sql = switch_mprintf("insert into aliases (sticky, alias, command, hostname) values (0, '%w','%w','%w')",
-										 argv[1], argv[2], switch_core_get_variable("hostname"));
+										 argv[1], argv[2], switch_core_get_hostname());
 				}
 				switch_cache_db_persistant_execute(db, sql, 5);
 				status = SWITCH_STATUS_SUCCESS;
 			} else if (!strcasecmp(argv[0], "del") && argc == 2) {
 				char *what = argv[1];
 				if (!strcasecmp(what, "*")) {
-					sql = switch_mprintf("delete from aliases where hostname='%q'", switch_core_get_variable("hostname"));
+					sql = switch_mprintf("delete from aliases where hostname='%q'", switch_core_get_hostname());
 					switch_cache_db_persistant_execute(db, sql, 1);
 				} else {
-					sql = switch_mprintf("delete from aliases where alias='%q' and hostname='%q'", argv[1], switch_core_get_variable("hostname"));
+					sql = switch_mprintf("delete from aliases where alias='%q' and hostname='%q'", argv[1], switch_core_get_hostname());
 					switch_cache_db_persistant_execute(db, sql, 5);
 				}
 				status = SWITCH_STATUS_SUCCESS;
diff --git a/src/switch_core.c b/src/switch_core.c
index 43fb36d..8754305 100644
--- a/src/switch_core.c
+++ b/src/switch_core.c
@@ -261,6 +261,11 @@ SWITCH_DECLARE(void) switch_core_dump_variables(switch_stream_handle_t *stream)
 	switch_mutex_unlock(runtime.global_mutex);
 }
 
+SWITCH_DECLARE(const char *) switch_core_get_hostname(void)
+{
+	return runtime.hostname;
+}
+
 SWITCH_DECLARE(char *) switch_core_get_variable(const char *varname)
 {
 	char *val;
@@ -270,6 +275,32 @@ SWITCH_DECLARE(char *) switch_core_get_variable(const char *varname)
 	return val;
 }
 
+SWITCH_DECLARE(char *) switch_core_get_variable_dup(const char *varname)
+{
+	char *val = NULL, *v;
+
+	switch_mutex_lock(runtime.global_var_mutex);
+	if ((v = (char *) switch_event_get_header(runtime.global_vars, varname))) {
+		val = strdup(v);
+	}
+	switch_mutex_unlock(runtime.global_var_mutex);
+
+	return val;
+}
+
+SWITCH_DECLARE(char *) switch_core_get_variable_pdup(const char *varname, switch_memory_pool_t *pool)
+{
+	char *val = NULL, *v;
+
+	switch_mutex_lock(runtime.global_var_mutex);
+	if ((v = (char *) switch_event_get_header(runtime.global_vars, varname))) {
+		val = switch_core_strdup(pool, v);
+	}
+	switch_mutex_unlock(runtime.global_var_mutex);
+
+	return val;
+}
+
 static void switch_core_unset_variables(void)
 {
 	switch_mutex_lock(runtime.global_var_mutex);
@@ -1202,12 +1233,18 @@ static void switch_core_set_serial(void)
 
 
 	if ((fd = open(path, O_RDONLY, 0)) < 0) {
-		char *ip = switch_core_get_variable("local_ip_v4");
+		char *ip = switch_core_get_variable_dup("local_ip_v4");
 		uint32_t ipi = 0;
 		switch_byte_t *byte;
 		int i = 0;
 
-		switch_inet_pton(AF_INET, ip, &ipi);
+		if (ip) {
+			switch_inet_pton(AF_INET, ip, &ipi);
+			free(ip);
+			ip = NULL;
+		}
+
+
 		byte = (switch_byte_t *) & ipi;
 
 		for (i = 0; i < 8; i += 2) {
@@ -1237,7 +1274,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc
 	char guess_ip[256];
 	int mask = 0;
 	struct in_addr in;
-	char hostname[256] = "";
+
 
 	if (runtime.runlevel > 0) {
 		/* one per customer */
@@ -1310,8 +1347,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc
 		runtime.console = stdout;
 	}
 
-	gethostname(hostname, sizeof(hostname));
-	switch_core_set_variable("hostname", hostname);
+	gethostname(runtime.hostname, sizeof(runtime.hostname));
+	switch_core_set_variable("hostname", runtime.hostname);
 
 	switch_find_local_ip(guess_ip, sizeof(guess_ip), &mask, AF_INET);
 	switch_core_set_variable("local_ip_v4", guess_ip);
diff --git a/src/switch_core_file.c b/src/switch_core_file.c
index 19f2354..fc7d223 100644
--- a/src/switch_core_file.c
+++ b/src/switch_core_file.c
@@ -102,7 +102,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file,
 			}
 
 			if (!spool_path) {
-				spool_path = switch_core_get_variable(SWITCH_AUDIO_SPOOL_PATH_VARIABLE);
+				spool_path = switch_core_get_variable_pdup(SWITCH_AUDIO_SPOOL_PATH_VARIABLE, fh->memory_pool);
 			}
 
 			file_path = fh->file_path;
diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c
index 2db2a0d..73890a1 100644
--- a/src/switch_core_sqldb.c
+++ b/src/switch_core_sqldb.c
@@ -1134,7 +1134,7 @@ static void core_event_handler(switch_event_t *event)
 				new_sql() = switch_mprintf("insert into tasks values(%q,'%q','%q',%q, '%q')",
 										   id,
 										   switch_event_get_header_nil(event, "task-desc"),
-										   switch_event_get_header_nil(event, "task-group"), manager ? manager : "0", switch_core_get_variable("hostname")
+										   switch_event_get_header_nil(event, "task-group"), manager ? manager : "0", switch_core_get_hostname()
 										   );
 			}
 		}
@@ -1142,7 +1142,7 @@ static void core_event_handler(switch_event_t *event)
 	case SWITCH_EVENT_DEL_SCHEDULE:
 	case SWITCH_EVENT_EXE_SCHEDULE:
 		new_sql() = switch_mprintf("delete from tasks where task_id=%q and hostname='%q'",
-								   switch_event_get_header_nil(event, "task-id"), switch_core_get_variable("hostname"));
+								   switch_event_get_header_nil(event, "task-id"), switch_core_get_hostname());
 		break;
 	case SWITCH_EVENT_RE_SCHEDULE:
 		{
@@ -1153,7 +1153,7 @@ static void core_event_handler(switch_event_t *event)
 				new_sql() = switch_mprintf("update tasks set task_desc='%q',task_group='%q', task_sql_manager=%q where task_id=%q and hostname='%q'",
 										   switch_event_get_header_nil(event, "task-desc"),
 										   switch_event_get_header_nil(event, "task-group"), manager ? manager : "0", id,
-										   switch_core_get_variable("hostname"));
+										   switch_core_get_hostname());
 			}
 		}
 		break;
@@ -1163,10 +1163,10 @@ static void core_event_handler(switch_event_t *event)
 			
 			if (uuid) {
 				new_sql() = switch_mprintf("delete from channels where uuid='%q' and hostname='%q'",
-										   uuid, switch_core_get_variable("hostname"));
+										   uuid, switch_core_get_hostname());
 
 				new_sql() = switch_mprintf("delete from calls where (caller_uuid='%q' or callee_uuid='%q') and hostname='%q'",
-										   uuid, uuid, switch_core_get_variable("hostname"));
+										   uuid, uuid, switch_core_get_hostname());
 
 			}
 		}
@@ -1178,12 +1178,12 @@ static void core_event_handler(switch_event_t *event)
 									   "update calls set callee_uuid='%q' where callee_uuid='%q' and hostname='%q'",
 									   switch_event_get_header_nil(event, "unique-id"),
 									   switch_event_get_header_nil(event, "old-unique-id"),
-									   switch_core_get_variable("hostname"),
+									   switch_core_get_hostname(),
 									   switch_event_get_header_nil(event, "unique-id"),
 									   switch_event_get_header_nil(event, "old-unique-id"),
-									   switch_core_get_variable("hostname"),
+									   switch_core_get_hostname(),
 									   switch_event_get_header_nil(event, "unique-id"),
-									   switch_event_get_header_nil(event, "old-unique-id"), switch_core_get_variable("hostname")
+									   switch_event_get_header_nil(event, "old-unique-id"), switch_core_get_hostname()
 									   );
 			break;
 		}
@@ -1198,7 +1198,7 @@ static void core_event_handler(switch_event_t *event)
 								   switch_event_get_header_nil(event, "channel-state"),
 								   switch_event_get_header_nil(event, "channel-call-state"),
 								   switch_event_get_header_nil(event, "caller-dialplan"),
-								   switch_event_get_header_nil(event, "caller-context"), switch_core_get_variable("hostname")
+								   switch_event_get_header_nil(event, "caller-context"), switch_core_get_hostname()
 								   );
 		break;
 	case SWITCH_EVENT_CODEC:
@@ -1211,7 +1211,7 @@ static void core_event_handler(switch_event_t *event)
 			 switch_event_get_header_nil(event, "channel-write-codec-name"),
 			 switch_event_get_header_nil(event, "channel-write-codec-rate"),
 			 switch_event_get_header_nil(event, "channel-write-codec-bit-rate"),
-			 switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname"));
+			 switch_event_get_header_nil(event, "unique-id"), switch_core_get_hostname());
 		break;
 	case SWITCH_EVENT_CHANNEL_HOLD:
 	case SWITCH_EVENT_CHANNEL_UNHOLD:
@@ -1223,7 +1223,7 @@ static void core_event_handler(switch_event_t *event)
 								   switch_event_get_header_nil(event, "application-data"),
 								   switch_event_get_header_nil(event, "channel-presence-id"),
 								   switch_event_get_header_nil(event, "channel-presence-data"),
-								   switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname")
+								   switch_event_get_header_nil(event, "unique-id"), switch_core_get_hostname()
 								   );
 
 	}
@@ -1238,7 +1238,7 @@ static void core_event_handler(switch_event_t *event)
 										   switch_event_get_header_nil(event, "channel-presence-data"),
 										   switch_event_get_header_nil(event, "channel-call-uuid"),
 										   extra_cols,
-										   switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname"));
+										   switch_event_get_header_nil(event, "unique-id"), switch_core_get_hostname());
 				free(extra_cols);
 			} else {
 				new_sql() = switch_mprintf("update channels set "
@@ -1246,7 +1246,7 @@ static void core_event_handler(switch_event_t *event)
 										   switch_event_get_header_nil(event, "channel-presence-id"),
 										   switch_event_get_header_nil(event, "channel-presence-data"),
 										   switch_event_get_header_nil(event, "channel-call-uuid"),
-										   switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname"));
+										   switch_event_get_header_nil(event, "unique-id"), switch_core_get_hostname());
 			}
 
 		}
@@ -1281,7 +1281,7 @@ static void core_event_handler(switch_event_t *event)
 										   switch_str_nil(name),
 										   switch_str_nil(number),
 										   switch_event_get_header_nil(event, "direction"),
-										   switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname"));
+										   switch_event_get_header_nil(event, "unique-id"), switch_core_get_hostname());
 
 				name = switch_event_get_header(event, "callee-name");
 				number = switch_event_get_header(event, "callee-number");
@@ -1298,7 +1298,7 @@ static void core_event_handler(switch_event_t *event)
 		{
 			new_sql() = switch_mprintf("update channels set callstate='%q' where uuid='%q' and hostname='%q'",
 									   switch_event_get_header_nil(event, "channel-call-state"),
-									   switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname"));
+									   switch_event_get_header_nil(event, "unique-id"), switch_core_get_hostname());
 
 		}
 		break;
@@ -1330,7 +1330,7 @@ static void core_event_handler(switch_event_t *event)
 											   switch_event_get_header_nil(event, "channel-presence-id"),
 											   switch_event_get_header_nil(event, "channel-presence-data"),
 											   extra_cols,
-											   switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname"));
+											   switch_event_get_header_nil(event, "unique-id"), switch_core_get_hostname());
 					free(extra_cols);
 				} else {
 					new_sql() = switch_mprintf("update channels set state='%s',cid_name='%q',cid_num='%q',"
@@ -1345,13 +1345,13 @@ static void core_event_handler(switch_event_t *event)
 											   switch_event_get_header_nil(event, "caller-context"),
 											   switch_event_get_header_nil(event, "channel-presence-id"),
 											   switch_event_get_header_nil(event, "channel-presence-data"),
-											   switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname"));
+											   switch_event_get_header_nil(event, "unique-id"), switch_core_get_hostname());
 				}
 				break;
 			default:
 				new_sql() = switch_mprintf("update channels set state='%s' where uuid='%s' and hostname='%q'",
 										   switch_event_get_header_nil(event, "channel-state"),
-										   switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname"));
+										   switch_event_get_header_nil(event, "unique-id"), switch_core_get_hostname());
 				break;
 			}
 
@@ -1377,7 +1377,7 @@ static void core_event_handler(switch_event_t *event)
 
 			new_sql() = switch_mprintf("update channels set call_uuid='%q' where uuid='%s' and hostname='%q'",
 									   switch_event_get_header_nil(event, "channel-call-uuid"),
-									   switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname"));
+									   switch_event_get_header_nil(event, "unique-id"), switch_core_get_hostname());
 
 			if (runtime.odbc_dbtype == DBTYPE_DEFAULT) {
 				func_name = "function";
@@ -1404,7 +1404,7 @@ static void core_event_handler(switch_event_t *event)
 									   callee_cid_num,
 									   switch_event_get_header_nil(event, "Other-Leg-destination-number"),
 									   switch_event_get_header_nil(event, "Other-Leg-channel-name"),
-									   switch_event_get_header_nil(event, "Other-Leg-unique-id"), switch_core_get_variable("hostname")
+									   switch_event_get_header_nil(event, "Other-Leg-unique-id"), switch_core_get_hostname()
 									   );
 		}
 		break;
@@ -1413,14 +1413,14 @@ static void core_event_handler(switch_event_t *event)
 			char *uuid = switch_event_get_header_nil(event, "caller-unique-id");
 
 			new_sql() = switch_mprintf("delete from calls where (caller_uuid='%q' or callee_uuid='%q') and hostname='%q'",
-									   uuid, uuid, switch_core_get_variable("hostname"));
+									   uuid, uuid, switch_core_get_hostname());
 			break;
 		}
 	case SWITCH_EVENT_SHUTDOWN:
 		new_sql() = switch_mprintf("delete from channels where hostname='%q';"
 								   "delete from interfaces where hostname='%q';"
 								   "delete from calls where hostname='%q'",
-								   switch_core_get_variable("hostname"), switch_core_get_variable("hostname"), switch_core_get_variable("hostname")
+								   switch_core_get_hostname(), switch_core_get_hostname(), switch_core_get_hostname()
 								   );
 		break;
 	case SWITCH_EVENT_LOG:
@@ -1438,7 +1438,7 @@ static void core_event_handler(switch_event_t *event)
 					switch_mprintf
 					("insert into interfaces (type,name,description,syntax,ikey,filename,hostname) values('%q','%q','%q','%q','%q','%q','%q')", type, name,
 					 switch_str_nil(description), switch_str_nil(syntax), switch_str_nil(key), switch_str_nil(filename),
-					 switch_core_get_variable("hostname")
+					 switch_core_get_hostname()
 					 );
 			}
 			break;
@@ -1449,7 +1449,7 @@ static void core_event_handler(switch_event_t *event)
 			const char *name = switch_event_get_header_nil(event, "name");
 			if (!zstr(type) && !zstr(name)) {
 				new_sql() = switch_mprintf("delete from interfaces where type='%q' and name='%q' and hostname='%q'", type, name,
-										   switch_core_get_variable("hostname"));
+										   switch_core_get_hostname());
 			}
 			break;
 		}
@@ -1461,7 +1461,7 @@ static void core_event_handler(switch_event_t *event)
 				break;
 			}
 			new_sql() = switch_mprintf("update channels set secure='%s' where uuid='%s' and hostname='%q'",
-									   type, switch_event_get_header_nil(event, "caller-unique-id"), switch_core_get_variable("hostname")
+									   type, switch_event_get_header_nil(event, "caller-unique-id"), switch_core_get_hostname()
 									   );
 			break;
 		}
@@ -1472,12 +1472,12 @@ static void core_event_handler(switch_event_t *event)
 			if (!strcmp("add", op)) {
 				new_sql() = switch_mprintf("insert into nat (port, proto, sticky, hostname) values (%s, %s, %d,'%q')",
 										   switch_event_get_header_nil(event, "port"),
-										   switch_event_get_header_nil(event, "proto"), sticky, switch_core_get_variable("hostname")
+										   switch_event_get_header_nil(event, "proto"), sticky, switch_core_get_hostname()
 										   );
 			} else if (!strcmp("del", op)) {
 				new_sql() = switch_mprintf("delete from nat where port=%s and proto=%s and hostname='%q'",
 										   switch_event_get_header_nil(event, "port"),
-										   switch_event_get_header_nil(event, "proto"), switch_core_get_variable("hostname"));
+										   switch_event_get_header_nil(event, "proto"), switch_core_get_hostname());
 			} else if (!strcmp("status", op)) {
 				/* call show nat api */
 			} else if (!strcmp("status_response", op)) {
@@ -1664,7 +1664,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_
 			char sql[512] = "";
 			char *tables[] = { "channels", "calls", "interfaces", "tasks", NULL };
 			int i;
-			const char *hostname = switch_core_get_variable("hostname");
+			const char *hostname = switch_core_get_hostname();
 
 			for (i = 0; tables[i]; i++) {
 				switch_snprintf(sql, sizeof(sql), "delete from %s where hostname='%s'", tables[i], hostname);
diff --git a/src/switch_event.c b/src/switch_event.c
index 003fc82..3e12ea1 100644
--- a/src/switch_event.c
+++ b/src/switch_event.c
@@ -1673,6 +1673,7 @@ SWITCH_DECLARE(char *) switch_event_expand_headers(switch_event_t *event, const
 					int offset = 0;
 					int ooffset = 0;
 					char *ptr;
+					char *gvar = NULL;
 
 					if ((expanded = switch_event_expand_headers(event, (char *) vname)) == vname) {
 						expanded = NULL;
@@ -1689,7 +1690,9 @@ SWITCH_DECLARE(char *) switch_event_expand_headers(switch_event_t *event, const
 					}
 
 					if (!(sub_val = switch_event_get_header(event, vname))) {
-						sub_val = switch_core_get_variable(vname);
+						if ((gvar = switch_core_get_variable_dup(vname))) {
+							sub_val = gvar;
+						}
 					}
 
 					if (offset || ooffset) {
@@ -1710,6 +1713,7 @@ SWITCH_DECLARE(char *) switch_event_expand_headers(switch_event_t *event, const
 						}
 					}
 
+					switch_safe_free(gvar);
 					switch_safe_free(expanded);
 				} else {
 					switch_stream_handle_t stream = { 0 };
diff --git a/src/switch_nat.c b/src/switch_nat.c
index 536baee..85b0247 100644
--- a/src/switch_nat.c
+++ b/src/switch_nat.c
@@ -45,6 +45,7 @@
 
 typedef struct {
 	switch_nat_type_t nat_type;
+	char nat_type_str[5];
 	struct UPNPUrls urls;
 	struct IGDdatas data;
 	char *descURL;
@@ -420,6 +421,7 @@ SWITCH_DECLARE(void) switch_nat_init(switch_memory_pool_t *pool)
 		switch_core_set_variable("nat_public_addr", nat_globals.pub_addr);
 		switch_core_set_variable("nat_private_addr", nat_globals.pvt_addr);
 		switch_core_set_variable("nat_type", nat_globals.nat_type == SWITCH_NAT_TYPE_PMP ? "pmp" : "upnp");
+		strncpy(nat_globals.nat_type_str, nat_globals.nat_type == SWITCH_NAT_TYPE_PMP ? "pmp" : "upnp", sizeof(nat_globals.nat_type_str) - 1);
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "NAT detected type: %s, ExtIP: '%s'\n",
 						  nat_globals.nat_type == SWITCH_NAT_TYPE_PMP ? "pmp" : "upnp", nat_globals.pub_addr);
 
@@ -564,6 +566,11 @@ static switch_status_t switch_nat_del_mapping_upnp(switch_port_t port, switch_na
 	return status;
 }
 
+SWITCH_DECLARE(const char *) switch_nat_get_type(void)
+{
+	return nat_globals.nat_type_str;
+}
+
 SWITCH_DECLARE(switch_status_t) switch_nat_add_mapping_internal(switch_port_t port, switch_nat_ip_proto_t proto, switch_port_t * external_port,
 																switch_bool_t sticky, switch_bool_t publish)
 {
diff --git a/src/switch_rtp.c b/src/switch_rtp.c
index 4acadfe..e8d7558 100644
--- a/src/switch_rtp.c
+++ b/src/switch_rtp.c
@@ -791,8 +791,8 @@ static void zrtp_logger(int level, const char *data, int len, int offset)
 SWITCH_DECLARE(void) switch_rtp_init(switch_memory_pool_t *pool)
 {
 #ifdef ENABLE_ZRTP
-	const char *zid_string = switch_core_get_variable("switch_serial");
-	const char *zrtp_enabled = switch_core_get_variable("zrtp_enabled");
+	const char *zid_string = switch_core_get_variable_pdup("switch_serial", pool);
+	const char *zrtp_enabled = switch_core_get_variable_pdup("zrtp_enabled", pool);
 	zrtp_config_t zrtp_config;
 	char zrtp_cache_path[256] = "";
 	zrtp_on = zrtp_enabled ? switch_true(zrtp_enabled) : 0;
diff --git a/src/switch_utils.c b/src/switch_utils.c
index 850b07f..eb5ed7f 100644
--- a/src/switch_utils.c
+++ b/src/switch_utils.c
@@ -1154,8 +1154,8 @@ SWITCH_DECLARE(switch_status_t) switch_find_local_ip(char *buf, int len, int *ma
 {
 	switch_status_t status = SWITCH_STATUS_FALSE;
 	char *base;
-	const char *force_local_ip_v4 = switch_core_get_variable("force_local_ip_v4");
-	const char *force_local_ip_v6 = switch_core_get_variable("force_local_ip_v6");
+	char *force_local_ip_v4 = switch_core_get_variable_dup("force_local_ip_v4");
+	char *force_local_ip_v6 = switch_core_get_variable_dup("force_local_ip_v6");
 
 #ifdef WIN32
 	SOCKET tmp_socket;
@@ -1176,14 +1176,20 @@ SWITCH_DECLARE(switch_status_t) switch_find_local_ip(char *buf, int len, int *ma
 	case AF_INET:
 		if (force_local_ip_v4) {
 			switch_copy_string(buf, force_local_ip_v4, len);
+			switch_safe_free(force_local_ip_v4);
+			switch_safe_free(force_local_ip_v6);
 			return SWITCH_STATUS_SUCCESS;
 		}
 	case AF_INET6:
 		if (force_local_ip_v6) {
 			switch_copy_string(buf, force_local_ip_v6, len);
+			switch_safe_free(force_local_ip_v4);
+			switch_safe_free(force_local_ip_v6);
 			return SWITCH_STATUS_SUCCESS;
 		}
 	default:
+		switch_safe_free(force_local_ip_v4);
+		switch_safe_free(force_local_ip_v6);
 		break;
 	}
 
diff --git a/src/switch_xml.c b/src/switch_xml.c
index 964a769..4c30d98 100644
--- a/src/switch_xml.c
+++ b/src/switch_xml.c
@@ -1208,11 +1208,12 @@ static char *expand_vars(char *buf, char *ebuf, switch_size_t elen, switch_size_
 				var = rp;
 				*e++ = '\0';
 				rp = e;
-				if ((val = switch_core_get_variable(var))) {
+				if ((val = switch_core_get_variable_dup(var))) {
 					char *p;
 					for (p = val; p && *p && wp <= ep; p++) {
 						*wp++ = *p;
 					}
+					free(val);
 				}
 				continue;
 			} else if (err) {
committer: Brian West
comments: 
FS-3023

diff --git a/src/include/switch_cpp.h b/src/include/switch_cpp.h
index 0bd2a8b..f4a0922 100644
--- a/src/include/switch_cpp.h
+++ b/src/include/switch_cpp.h
@@ -68,6 +68,10 @@ Note that the first parameter to the new operator is implicitly handled by c++..
 SWITCH_DECLARE(void) consoleLog(char *level_str, char *msg);
 SWITCH_DECLARE(void) consoleCleanLog(char *msg);
 
+SWITCH_DECLARE(bool) email(char *to, char *from, char *headers = NULL, char *body = NULL,
+    char *file = NULL, char *convert_cmd = NULL, char *convert_ext = NULL);
+
+
 	 class CoreSession;
 
 	 class IVRMenu {
diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx
index e91de6d..71e9f99 100644
--- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx
+++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx
@@ -33352,6 +33352,30 @@ SWIGEXPORT void SWIGSTDCALL CSharp_consoleCleanLog(char * jarg1) {
 }
 
 
+SWIGEXPORT unsigned int SWIGSTDCALL CSharp_email(char * jarg1, char * jarg2, char * jarg3, char * jarg4, char * jarg5, char * jarg6, char * jarg7) {
+  unsigned int jresult ;
+  char *arg1 = (char *) 0 ;
+  char *arg2 = (char *) 0 ;
+  char *arg3 = (char *) NULL ;
+  char *arg4 = (char *) NULL ;
+  char *arg5 = (char *) NULL ;
+  char *arg6 = (char *) NULL ;
+  char *arg7 = (char *) NULL ;
+  bool result;
+  
+  arg1 = (char *)jarg1; 
+  arg2 = (char *)jarg2; 
+  arg3 = (char *)jarg3; 
+  arg4 = (char *)jarg4; 
+  arg5 = (char *)jarg5; 
+  arg6 = (char *)jarg6; 
+  arg7 = (char *)jarg7; 
+  result = (bool)email(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+  jresult = result; 
+  return jresult;
+}
+
+
 SWIGEXPORT void * SWIGSTDCALL CSharp_new_IvrMenu(void * jarg1, char * jarg2, char * jarg3, char * jarg4, char * jarg5, char * jarg6, char * jarg7, char * jarg8, char * jarg9, char * jarg10, int jarg11, int jarg12, int jarg13, int jarg14, int jarg15, int jarg16) {
   void * jresult ;
   IVRMenu *arg1 = (IVRMenu *) 0 ;
diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs
index 1f02c3f..c640199 100644
--- a/src/mod/languages/mod_managed/managed/swig.cs
+++ b/src/mod/languages/mod_managed/managed/swig.cs
@@ -5364,6 +5364,11 @@ public class freeswitch {
     freeswitchPINVOKE.consoleCleanLog(msg);
   }
 
+  public static bool email(string to, string from, string headers, string body, string file, string convert_cmd, string convert_ext) {
+    bool ret = freeswitchPINVOKE.email(to, from, headers, body, file, convert_cmd, convert_ext);
+    return ret;
+  }
+
   public static void console_log(string level_str, string msg) {
     freeswitchPINVOKE.console_log(level_str, msg);
   }
@@ -13588,6 +13593,9 @@ class freeswitchPINVOKE {
   [DllImport("mod_managed", EntryPoint="CSharp_consoleCleanLog")]
   public static extern void consoleCleanLog(string jarg1);
 
+  [DllImport("mod_managed", EntryPoint="CSharp_email")]
+  public static extern bool email(string jarg1, string jarg2, string jarg3, string jarg4, string jarg5, string jarg6, string jarg7);
+
   [DllImport("mod_managed", EntryPoint="CSharp_new_IvrMenu")]
   public static extern IntPtr new_IvrMenu(HandleRef jarg1, string jarg2, string jarg3, string jarg4, string jarg5, string jarg6, string jarg7, string jarg8, string jarg9, string jarg10, int jarg11, int jarg12, int jarg13, int jarg14, int jarg15, int jarg16);
 
diff --git a/src/switch_cpp.cpp b/src/switch_cpp.cpp
index bbcd05d..c62946b 100644
--- a/src/switch_cpp.cpp
+++ b/src/switch_cpp.cpp
@@ -1195,6 +1195,13 @@ SWITCH_DECLARE(void) console_clean_log(char *msg)
     switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN,SWITCH_LOG_DEBUG, "%s", switch_str_nil(msg));
 }
 
+SWITCH_DECLARE(bool) email(char *to, char *from, char *headers, char *body, char *file, char *convert_cmd, char *convert_ext)
+{
+    if (switch_simple_email(to, from, headers, body, file, convert_cmd, convert_ext) == SWITCH_TRUE) {
+      return true;
+    }
+    return false;
+}
 
 SWITCH_DECLARE(void) msleep(unsigned ms)
 {
committer: Anthony Minessale
comments: 
FS-3024

diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c
index 35311c9..2db2a0d 100644
--- a/src/switch_core_sqldb.c
+++ b/src/switch_core_sqldb.c
@@ -1409,9 +1409,13 @@ static void core_event_handler(switch_event_t *event)
 		}
 		break;
 	case SWITCH_EVENT_CHANNEL_UNBRIDGE:
-		new_sql() = switch_mprintf("delete from calls where (caller_uuid='%s' or callee_uuid='%q') and hostname='%q'",
-								   switch_event_get_header_nil(event, "caller-unique-id"), switch_core_get_variable("hostname"));
-		break;
+		{
+			char *uuid = switch_event_get_header_nil(event, "caller-unique-id");
+
+			new_sql() = switch_mprintf("delete from calls where (caller_uuid='%q' or callee_uuid='%q') and hostname='%q'",
+									   uuid, uuid, switch_core_get_variable("hostname"));
+			break;
+		}
 	case SWITCH_EVENT_SHUTDOWN:
 		new_sql() = switch_mprintf("delete from channels where hostname='%q';"
 								   "delete from interfaces where hostname='%q';"
committer: David Yat Sin
comments: 
Merge branch 'master' of git.sangoma.com:smg_freeswitch
committer: David Yat Sin
comments: 
freetdm: Fix for typo in print

diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c
index 92cf9e5..563a203 100755
--- a/libs/freetdm/mod_freetdm/mod_freetdm.c
+++ b/libs/freetdm/mod_freetdm/mod_freetdm.c
@@ -1570,8 +1570,8 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session
 		switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-ANI2", "%s", channel_caller_data->aniII);
 		
 		switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-DNIS", "%s", channel_caller_data->dnis.digits);
-		switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-DNIS-TON", "%s", channel_caller_data->dnis.type);
-		switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-DNIS-Plan", "%s", channel_caller_data->dnis.plan);
+		switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-DNIS-TON", "%d", channel_caller_data->dnis.type);
+		switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-DNIS-Plan", "%d", channel_caller_data->dnis.plan);
 
 		switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-RDNIS", "%s", channel_caller_data->rdnis.digits);
 		switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-RDNIS-TON", "%d", channel_caller_data->rdnis.type);
committer: Leon de Rooij
comments: 
Merge branch 'master' of ssh://git.freeswitch.org/freeswitch
committer: Andrew Thompson
comments: 
Added conference UUID to xml_list

diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c
index 12b3193..961a140 100644
--- a/src/mod/applications/mod_conference/mod_conference.c
+++ b/src/mod/applications/mod_conference/mod_conference.c
@@ -3778,6 +3778,7 @@ static void conference_xlist(conference_obj_t *conference, switch_xml_t x_confer
 	switch_xml_set_attr_d(x_conference, "member-count", ival);
 	switch_snprintf(i, sizeof(i), "%u", conference->rate);
 	switch_xml_set_attr_d(x_conference, "rate", ival);
+	switch_xml_set_attr_d(x_conference, "uuid", conference->uuid_str);
 
 	if (switch_test_flag(conference, CFLAG_LOCKED)) {
 		switch_xml_set_attr_d(x_conference, "locked", "true");
committer: Brian West
comments: 
 sigh

diff --git a/libs/openzap/mod_openzap/mod_openzap.c b/libs/openzap/mod_openzap/mod_openzap.c
index 3e5227e..d52149c 100644
--- a/libs/openzap/mod_openzap/mod_openzap.c
+++ b/libs/openzap/mod_openzap/mod_openzap.c
@@ -135,7 +135,9 @@ void dump_chan_xml(zap_span_t *span, uint32_t chan_id, switch_stream_handle_t *s
 
 static void zap_set_npi(const char *npi_string, uint8_t *target)
 {
-	if (!strcasecmp(npi_string, "isdn") || !strcasecmp(npi_string, "e164")) {
+	if (switch_is_number(npi_string)) {
+		*target = (uint8_t)atoi(npi_string);
+	} else if (!strcasecmp(npi_string, "isdn") || !strcasecmp(npi_string, "e164")) {
 		*target = ZAP_NPI_ISDN;
 	} else if (!strcasecmp(npi_string, "data")) {
 		*target = ZAP_NPI_DATA;
@@ -157,7 +159,9 @@ static void zap_set_npi(const char *npi_string, uint8_t *target)
 
 static void zap_set_ton(const char *ton_string, uint8_t *target)
 {
-	if (!strcasecmp(ton_string, "national")) {
+	if (switch_is_number(ton_string)) {
+		*target = (uint8_t)atoi(ton_string);
+	} else if (!strcasecmp(ton_string, "national")) {
 		*target = ZAP_TON_NATIONAL;
 	} else if (!strcasecmp(ton_string, "international")) {
 		*target = ZAP_TON_INTERNATIONAL;
@@ -1231,15 +1235,8 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
 	}
 	
 	if ((var = switch_event_get_header(var_event, "openzap_outbound_ton")) || (var = switch_core_get_variable("openzap_outbound_ton"))) {
-		if (!strcasecmp(var, "national")) {
-			caller_data.ani.type = ZAP_TON_NATIONAL;
-		} else if (!strcasecmp(var, "international")) {
-			caller_data.ani.type = ZAP_TON_INTERNATIONAL;
-		} else if (!strcasecmp(var, "local")) {
-			caller_data.ani.type = ZAP_TON_SUBSCRIBER_NUMBER;
-		} else if (!strcasecmp(var, "unknown")) {
-			caller_data.ani.type = ZAP_TON_UNKNOWN;
-		}
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Setting TON to: %s\n", var);
+		zap_set_ton(var, &caller_data.ani.type);
 	} else {
 		caller_data.ani.type = outbound_profile->destination_number_ton;
 	}
@@ -1248,9 +1245,14 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
 		zap_set_string((char *)caller_data.raw_data, var);
 		caller_data.raw_data_len = strlen(var);
 	}
-
-	caller_data.ani.plan = outbound_profile->destination_number_numplan;
-
+	
+	if ((var = switch_event_get_header(var_event, "openzap_outbound_npi")) || (var = switch_core_get_variable("openzap_outbound_npi"))) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Setting NPI to: %s\n", var);
+		zap_set_npi(var, &caller_data.ani.plan);
+	} else {
+		caller_data.ani.plan = outbound_profile->destination_number_numplan;
+	}
+	
 	/* blindly copy data from outbound_profile. They will be overwritten 
 	 * by calling zap_caller_data if needed after */
 	caller_data.cid_num.type = outbound_profile->caller_ton;
committer: Anthony Minessale
comments: 
more loopback improvements

diff --git a/src/mod/endpoints/mod_loopback/mod_loopback.c b/src/mod/endpoints/mod_loopback/mod_loopback.c
index 727de27..be9b499 100644
--- a/src/mod/endpoints/mod_loopback/mod_loopback.c
+++ b/src/mod/endpoints/mod_loopback/mod_loopback.c
@@ -82,6 +82,7 @@ struct private_object {
 	int32_t bowout_frame_count;
 	char *other_uuid;
 	switch_queue_t *frame_queue;
+	int64_t packet_count;
 };
 
 typedef struct private_object private_t;
@@ -577,40 +578,22 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
 		if (tech_pvt->write_frame) {
 			switch_frame_free(&tech_pvt->write_frame);
 		}
-
+		
 		tech_pvt->write_frame = (switch_frame_t *) pop;
 		tech_pvt->write_frame->codec = &tech_pvt->read_codec;
 		*frame = tech_pvt->write_frame;
+		tech_pvt->packet_count++;
+		switch_clear_flag_locked(tech_pvt, TFLAG_CNG);
+		switch_clear_flag(tech_pvt->write_frame, SFF_CNG);
 	} else {
 		switch_set_flag(tech_pvt, TFLAG_CNG);
 	}
 
 	if (switch_test_flag(tech_pvt, TFLAG_CNG)) {
-		unsigned char data[SWITCH_RECOMMENDED_BUFFER_SIZE];
-		uint32_t flag = 0;
-		switch_status_t encode_status;
-		uint32_t rate = tech_pvt->read_codec.implementation->actual_samples_per_second;
-
 		*frame = &tech_pvt->cng_frame;
 		tech_pvt->cng_frame.codec = &tech_pvt->read_codec;
 		tech_pvt->cng_frame.datalen = tech_pvt->read_codec.implementation->decoded_bytes_per_packet;
-
-		memset(tech_pvt->cng_frame.data, 0, tech_pvt->cng_frame.datalen);
-		memset(&data, 0, tech_pvt->read_codec.implementation->decoded_bytes_per_packet);
-
-		if (strcasecmp(tech_pvt->read_codec.implementation->iananame, "L16")) {
-			encode_status = switch_core_codec_encode(&tech_pvt->read_codec,
-													 NULL,
-													 data,
-													 tech_pvt->read_codec.implementation->decoded_bytes_per_packet,
-													 tech_pvt->read_codec.implementation->actual_samples_per_second,
-													 tech_pvt->cng_frame.data, &tech_pvt->cng_frame.datalen, &rate, &flag);
-			if (encode_status != SWITCH_STATUS_SUCCESS) {
-				switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
-			}
-		} else {
-			switch_set_flag((&tech_pvt->cng_frame), SFF_CNG);
-		}
+		switch_set_flag((&tech_pvt->cng_frame), SFF_CNG);
 		switch_clear_flag_locked(tech_pvt, TFLAG_CNG);
 	}
 
committer: David Yat Sin
comments: 
chlog: freetdm: isdn: fix for 5ESS call clearing procedures

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 df528ae..97984fb 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
@@ -683,8 +683,8 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm
 				if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
 					/* By default, we do not send a progress indicator in the proceed */
 					ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID};
-					
 					sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
+					
 					sngisdn_snd_proceed(ftdmchan, prog_ind);
 				}
 			}
@@ -800,6 +800,15 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm
 						/* If we never received a PROCEED/ALERT/PROGRESS/CONNECT on an outgoing call, we need to send release instead of disconnect */
 						sngisdn_snd_release(ftdmchan, 0);
 						break;
+					case FTDM_CHANNEL_STATE_PROCEED:
+						if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) &&
+							((sngisdn_span_data_t*)(ftdmchan->span->signal_data))->switchtype == SNGISDN_SWITCH_5ESS) {
+							
+							/* When using 5ESS, if the user wants to clear an inbound call, the correct procedure is to send a PROGRESS with in-band info available, and play tones. Then send a DISCONNECT. If we reached this point, it means user did not try to play-tones, so send a RELEASE because remote side does not expect DISCONNECT in state 3 */
+							sngisdn_snd_release(ftdmchan, 0);
+							break;
+						}
+						/* fall-through */
 					default:
 						sngisdn_snd_disconnect(ftdmchan);
 						break;
committer: Leon de Rooij
comments: 
Merge branch 'master' of ssh://git.freeswitch.org/freeswitch
committer: Leon de Rooij
comments: 
Merge branch 'master' of ssh://git.freeswitch.org/freeswitch
committer: Moises Silva
comments: 
test

diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c
index 529a30f..0f92f59 100644
--- a/libs/freetdm/src/ftdm_io.c
+++ b/libs/freetdm/src/ftdm_io.c
@@ -37,6 +37,9 @@
  *
  */
 
+#ifdef MOYTEST
+crap
+#endif
 #define _GNU_SOURCE
 #include "private/ftdm_core.h"
 #include <stdarg.h>
committer: Leon de Rooij
comments: 
Merge branch 'master' of ssh://git.freeswitch.org/freeswitch
committer: Konrad Hammel
comments: 
freetdm: ss7 - bug fix: fix for bug introduced by merge of RELAY work

diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
index c971179..adee000 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
@@ -495,8 +495,6 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 	/**************************************************************************/
 	case FTDM_CHANNEL_STATE_COLLECT:	/* IAM received but wating on digits */
 
-		isup_intf = &g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId];
-
 		if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
 			SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
 			break;
@@ -516,8 +514,8 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 			/*now go to the RING state */
 			ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING);
 			
-		} else if (i >= isup_intf->min_digits) {
-			SS7_DEBUG_CHAN(ftdmchan, "Received %d digits (min digits = %d)\n", i, isup_intf->min_digits);
+		} else if (i >= sngss7_info->circuit->min_digits) {
+			SS7_DEBUG_CHAN(ftdmchan, "Received %d digits (min digits = %d)\n", i, sngss7_info->circuit->min_digits);
 
 			/*now go to the RING state */
 			ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING);
@@ -527,7 +525,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 			if (ftdmchan->last_state != FTDM_CHANNEL_STATE_IDLE) {
 				SS7_INFO_CHAN(ftdmchan,"Received %d out of %d so far: %s...starting T35\n",
 										i,
-										isup_intf->min_digits,
+										sngss7_info->circuit->min_digits,
 										ftdmchan->caller_data.dnis.digits);
 		
 				/* start ISUP t35 */
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
index 93f2678..d2fa973 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
@@ -1509,11 +1509,6 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
 
 			SS7_DEBUG("Found an isup mptRouteId = %d\n", sng_isup.mtpRouteId);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "min_digits")) {
-			sng_isup.min_digits = atoi(parm->val);
-
-			SS7_DEBUG("\tFound min_digits = %d\n", sng_isup.min_digits);
-		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "ssf")) {
 		/**********************************************************************/
 			ret = find_ssf_type_in_map(parm->val);
committer: Konrad Hammel
comments: 
chlog: freetdm: ss7 - update for new licensing, will not work with old licenses 			contact Sangoma (techdesk@sangoma.com) to obtain a new license

diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c
index 42b95a1..15fc1ef 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c
@@ -80,8 +80,7 @@ int  ft_to_sngss7_cfg_all(void)
 
 		/* start of by checking if the license and sig file are valid */
 		if (sng_validate_license(g_ftdm_sngss7_data.cfg.license,
-								 g_ftdm_sngss7_data.cfg.signature,
-								 g_ftdm_sngss7_data.cfg.spc)) {
+								 g_ftdm_sngss7_data.cfg.signature)) {
 
 			SS7_CRITICAL("License verification failed..ending!\n");
 			return 1;
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c
index 1dfcab4..f4143fc 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c
@@ -79,8 +79,8 @@ void handle_sng_log(uint8_t level, char *fmt,...)
 		ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
 		break;
 	/**************************************************************************/
-	case SNG_LOGLEVEL_STATS:
-		ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
+	case SNG_LOGLEVEL_NOTICE:
+		ftdm_log(FTDM_LOG_NOTICE, "sng_ss7->%s", data);
 		break;
 	/**************************************************************************/
 	case SNG_LOGLEVEL_ERROR:
committer: Konrad Hammel
comments: 
chlog: freetdm: ss7 - bug fix: a route now supports multiple linksets

diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c
index d972cd7..92cf9e5 100755
--- a/libs/freetdm/mod_freetdm/mod_freetdm.c
+++ b/libs/freetdm/mod_freetdm/mod_freetdm.c
@@ -2462,7 +2462,7 @@ static ftdm_conf_node_t *get_ss7_config_node(switch_xml_t cfg, const char *confn
 	}
 
 	/* add mtp routes */
-	if (add_config_list_nodes(isup, rootnode, "mtp_routes", "mtp_route", NULL, NULL)) {
+	if (add_config_list_nodes(isup, rootnode, "mtp_routes", "mtp_route", "linksets", "linkset")) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process mtp_routes for sng_isup config %s\n", confname);
 		ftdm_conf_node_destroy(rootnode);
 		return NULL;
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
index 277951c..93f2678 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
@@ -1269,6 +1269,10 @@ static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route)
 	int					 	num_parms = mtp_route->n_parameters;
 	int					 	i;
 
+	ftdm_conf_node_t		*linkset;
+	int						ls_id;
+	int						numLinks;
+
 	/* initalize the mtpRoute structure */
 	memset(&mtpRoute, 0x0, sizeof(mtpRoute));
 
@@ -1299,11 +1303,6 @@ static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route)
 			mtpRoute.dpc = atoi(parm->val);
 			SS7_DEBUG("Found an mtpRoute dpc = %d\n", mtpRoute.dpc);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "linksetId")) {
-		/**********************************************************************/
-			mtpRoute.linkSetId = atoi(parm->val);
-			SS7_DEBUG("Found an mtpRoute linkset = %s\n", parm->val);
-		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isSTP")) {
 		/**********************************************************************/
 			if (!strcasecmp(parm->val, "no")) {
@@ -1383,15 +1382,47 @@ static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route)
 		parm = parm + 1;
 	}
 
-	/* pull up the linktype, switchtype, and SSF from the linkset */
-	mtpRoute.linkType = g_ftdm_sngss7_data.cfg.mtpLinkSet[mtpRoute.linkSetId].linkType;
-	mtpRoute.switchType = g_ftdm_sngss7_data.cfg.mtpLinkSet[mtpRoute.linkSetId].switchType;
-	mtpRoute.ssf = g_ftdm_sngss7_data.cfg.mtpLinkSet[mtpRoute.linkSetId].ssf;
-
 	/* fill in the rest of the values in the mtpRoute struct  */
 	mtpRoute.nwId = mtpRoute.id;
 	mtpRoute.cmbLinkSetId = mtpRoute.id;
 
+	/* parse in the list of linksets this route is reachable by */
+	linkset = mtp_route->child->child;
+
+	while (linkset != NULL) {
+	/**************************************************************************/
+		/* extract the linkset Id */
+		ls_id = atoi(linkset->parameters->val);
+
+		if (g_ftdm_sngss7_data.cfg.mtpLinkSet[ls_id].id != 0) {
+			SS7_DEBUG("Found mtpRoute linkset id = %d that is valid\n",ls_id);
+		} else {
+			SS7_ERROR("Found mtpRoute linkset id = %d that is invalid\n",ls_id);
+			goto move_along;
+		}
+
+		/* pull up the linktype, switchtype, and SSF from the linkset */
+		mtpRoute.linkType = g_ftdm_sngss7_data.cfg.mtpLinkSet[ls_id].linkType;
+		mtpRoute.switchType = g_ftdm_sngss7_data.cfg.mtpLinkSet[ls_id].switchType;
+		mtpRoute.ssf = g_ftdm_sngss7_data.cfg.mtpLinkSet[ls_id].ssf;
+		
+		/* extract the number of cmbLinkSetId aleady on this linkset */
+		numLinks = g_ftdm_sngss7_data.cfg.mtpLinkSet[ls_id].numLinks;
+		
+		/* add this routes cmbLinkSetId to the list */
+		g_ftdm_sngss7_data.cfg.mtpLinkSet[ls_id].links[numLinks] = mtpRoute.cmbLinkSetId;
+
+		/* increment the number of cmbLinkSets on this linkset */
+		g_ftdm_sngss7_data.cfg.mtpLinkSet[ls_id].numLinks++;
+
+move_along:
+		/* move to the next linkset element */
+		linkset = linkset->next;
+
+	/**************************************************************************/
+	} /* while (linkset != null) */
+
+
 	ftmod_ss7_fill_in_mtp3_route(&mtpRoute);
 
 	ftmod_ss7_fill_in_nsap(&mtpRoute);
committer: Konrad Hammel
comments: 
chlog: freetdm: ss7 - added support for RELAY

diff --git a/libs/freetdm/Makefile.am b/libs/freetdm/Makefile.am
index 96f1c9a..b3353f3 100644
--- a/libs/freetdm/Makefile.am
+++ b/libs/freetdm/Makefile.am
@@ -240,7 +240,8 @@ ftmod_sangoma_ss7_la_SOURCES = \
 	$(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c \
 	$(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c \
 	$(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sts.c \
-	$(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c
+	$(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c \
+	$(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_relay.c
 
 ftmod_sangoma_ss7_la_CFLAGS  = $(AM_CFLAGS) $(FTDM_CFLAGS) -D_GNU_SOURCE
 ftmod_sangoma_ss7_la_LDFLAGS = -shared -module -avoid-version -lsng_ss7
diff --git a/libs/freetdm/configure.ac b/libs/freetdm/configure.ac
index a070e99..1f4fc9c 100644
--- a/libs/freetdm/configure.ac
+++ b/libs/freetdm/configure.ac
@@ -267,7 +267,7 @@ fi
 #
 HAVE_SNG_SS7="no"
 AC_MSG_RESULT([${as_nl}<<>> Sangoma SS7 stack])
-AC_CHECK_LIB([sng_ss7], [sng_isup_init], [HAVE_SNG_SS7="yes"])
+AC_CHECK_LIB([sng_ss7], [sng_isup_init_gen], [HAVE_SNG_SS7="yes"])
 AC_MSG_RESULT([checking whether to build ftmod_sangoma_ss7... ${HAVE_SNG_SS7}])
 AM_CONDITIONAL([HAVE_SNG_SS7], [test "${HAVE_SNG_SS7}" = "yes"])
 
diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c
index 970cb5b..d972cd7 100755
--- a/libs/freetdm/mod_freetdm/mod_freetdm.c
+++ b/libs/freetdm/mod_freetdm/mod_freetdm.c
@@ -2360,8 +2360,9 @@ static int add_config_list_nodes(switch_xml_t swnode, ftdm_conf_node_t *rootnode
 
 static ftdm_conf_node_t *get_ss7_config_node(switch_xml_t cfg, const char *confname)
 {
-	switch_xml_t signode, ss7configs, isup;
-	ftdm_conf_node_t *rootnode;
+	switch_xml_t signode, ss7configs, isup, gen, param;
+	ftdm_conf_node_t *rootnode, *list;
+	char *var, *val;
 
 	/* try to find the conf in the hash first */
 	rootnode = switch_core_hash_find(globals.ss7_configs, confname);
@@ -2405,8 +2406,56 @@ static ftdm_conf_node_t *get_ss7_config_node(switch_xml_t cfg, const char *confn
 		return NULL;
 	}
 
+	/* add sng_gen */
+	gen = switch_xml_child(isup, "sng_gen");
+	if (gen == NULL) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process sng_gen for sng_isup config %s\n", confname);
+		ftdm_conf_node_destroy(rootnode);
+		return NULL;
+	}
+
+	if ((FTDM_SUCCESS != ftdm_conf_node_create("sng_gen", &list, rootnode))) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create %s node for %s\n", "sng_gen", confname);
+		ftdm_conf_node_destroy(rootnode);
+		return NULL;
+	}
+
+	for (param = switch_xml_child(gen, "param"); param; param = param->next) {
+		var = (char *) switch_xml_attr_soft(param, "name");
+		val = (char *) switch_xml_attr_soft(param, "value");
+		ftdm_conf_node_add_param(list, var, val);
+	}
+
+	/* add relay channels */
+	if (add_config_list_nodes(isup, rootnode, "sng_relay", "relay_channel", NULL, NULL)) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process sng_relay for sng_isup config %s\n", confname);
+		ftdm_conf_node_destroy(rootnode);
+		return NULL;
+	}
+
+	/* add mtp1 links */
+	if (add_config_list_nodes(isup, rootnode, "mtp1_links", "mtp1_link", NULL, NULL)) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process mtp1_links for sng_isup config %s\n", confname);
+		ftdm_conf_node_destroy(rootnode);
+		return NULL;
+	}
+
+	/* add mtp2 links */
+	if (add_config_list_nodes(isup, rootnode, "mtp2_links", "mtp2_link", NULL, NULL)) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process mtp2_links for sng_isup config %s\n", confname);
+		ftdm_conf_node_destroy(rootnode);
+		return NULL;
+	}
+
+	/* add mtp3 links */
+	if (add_config_list_nodes(isup, rootnode, "mtp3_links", "mtp3_link", NULL, NULL)) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process mtp3_links for sng_isup config %s\n", confname);
+		ftdm_conf_node_destroy(rootnode);
+		return NULL;
+	}
+
 	/* add mtp linksets */
-	if (add_config_list_nodes(isup, rootnode, "mtp_linksets", "mtp_linkset", "mtp_links", "mtp_link")) {
+	if (add_config_list_nodes(isup, rootnode, "mtp_linksets", "mtp_linkset", NULL, NULL)) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process mtp_linksets for sng_isup config %s\n", confname);
 		ftdm_conf_node_destroy(rootnode);
 		return NULL;
@@ -2426,6 +2475,13 @@ static ftdm_conf_node_t *get_ss7_config_node(switch_xml_t cfg, const char *confn
 		return NULL;
 	}
 
+	/* add cc spans */
+	if (add_config_list_nodes(isup, rootnode, "cc_spans", "cc_span", NULL, NULL)) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process cc_spans for sng_isup config %s\n", confname);
+		ftdm_conf_node_destroy(rootnode);
+		return NULL;
+	}
+
 	switch_core_hash_insert(globals.ss7_configs, confname, rootnode);
 
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Added SS7 node configuration %s\n", confname);
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c
index e7378bf..42b95a1 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c
@@ -44,6 +44,7 @@
 /* PROTOTYPES *****************************************************************/
 int ft_to_sngss7_cfg_all(void);
 
+int ftmod_ss7_relay_gen_config(void);
 int ftmod_ss7_mtp1_gen_config(void);
 int ftmod_ss7_mtp2_gen_config(void);
 int ftmod_ss7_mtp3_gen_config(void);
@@ -65,6 +66,8 @@ int ftmod_ss7_isup_ckt_config(int id);
 int ftmod_ss7_isup_isap_config(int id);
 
 int ftmod_ss7_cc_isap_config(int id);
+
+int ftmod_ss7_relay_chan_config(int id);
 /******************************************************************************/
 
 /* FUNCTIONS ******************************************************************/
@@ -75,6 +78,7 @@ int  ft_to_sngss7_cfg_all(void)
 	/* check if we have done gen_config already */
 	if (!(g_ftdm_sngss7_data.gen_config)) {
 
+		/* start of by checking if the license and sig file are valid */
 		if (sng_validate_license(g_ftdm_sngss7_data.cfg.license,
 								 g_ftdm_sngss7_data.cfg.signature,
 								 g_ftdm_sngss7_data.cfg.spc)) {
@@ -83,50 +87,148 @@ int  ft_to_sngss7_cfg_all(void)
 			return 1;
 		}
 
-		if (ftmod_ss7_mtp1_gen_config()) {
-			SS7_CRITICAL("MTP1 General configuration FAILED!\n");
-			return 1;
-		} else {
-			SS7_INFO("MTP1 General configuration DONE\n");
+		/* if the procId is not 0 then we are using relay mode */
+		if (g_ftdm_sngss7_data.cfg.procId != 0) {
+			/* set the desired procID value */
+			sng_set_procId((uint16_t)g_ftdm_sngss7_data.cfg.procId);
 		}
 
-		if (ftmod_ss7_mtp2_gen_config()) {
-			SS7_CRITICAL("MTP2 General configuration FAILED!\n");
+		/* start up the stack manager */
+		if (sng_isup_init_sm()) {
+			SS7_CRITICAL("Failed to start Stack Manager\n");
 			return 1;
 		} else {
-			SS7_INFO("MTP2 General configuration DONE\n");
+			SS7_INFO("Started Stack Manager!\n");
 		}
 
-		if (ftmod_ss7_mtp3_gen_config()) {
-			SS7_CRITICAL("MTP3 General configuration FAILED!\n");
-			return 1;
-		} else {
-			SS7_INFO("MTP3 General configuration DONE\n");
-		}
+		/* check if the configuration had a Relay Channel */
+		if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY)) { 
+			/* start up the relay task */
+			if (sng_isup_init_relay()) {
+				SS7_CRITICAL("Failed to start Relay\n");
+				return 1;
+			} else {
+				SS7_INFO("Started Relay!\n");
+			}
 
-		if (ftmod_ss7_isup_gen_config()) {
-			SS7_CRITICAL("ISUP General configuration FAILED!\n");
-			return 1;
-		} else {
-			SS7_INFO("ISUP General configuration DONE\n");
-		}
+			/* run general configuration on the relay task */
+			if (ftmod_ss7_relay_gen_config()) {
+				SS7_CRITICAL("Relay General configuration FAILED!\n");
+				return 1;
+			} else {
+				SS7_INFO("Relay General configuration DONE\n");
+			}
 
-		if (ftmod_ss7_cc_gen_config()) {
-			SS7_CRITICAL("CC General configuration FAILED!\n");
-			return 1;
-		} else {
-			SS7_INFO("CC General configuration DONE\n");
-		}
+		} /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY)) */
+
+		if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC)) {
+			if (sng_isup_init_cc()) {
+				SS7_CRITICAL("Failed to start Call-Control\n");
+				return 1;
+			} else {
+				SS7_INFO("Started Call-Control!\n");
+			}
+			if (ftmod_ss7_cc_gen_config()) {
+				SS7_CRITICAL("CC General configuration FAILED!\n");
+				return 1;
+			} else {
+				SS7_INFO("CC General configuration DONE\n");
+			}
+			if (ftmod_ss7_cc_isap_config(1)) {
+				SS7_CRITICAL("CC ISAP configuration FAILED!\n");
+				return 1;
+			} else {
+				SS7_INFO("CC ISAP configuration DONE!\n");
+			}
+		} /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC)) */
+
+		if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP)) {
+			if (sng_isup_init_isup()) {
+				SS7_CRITICAL("Failed to start ISUP\n");
+				return 1;
+			} else {
+				SS7_INFO("Started ISUP!\n");
+			}	
+			if (ftmod_ss7_isup_gen_config()) {
+				SS7_CRITICAL("ISUP General configuration FAILED!\n");
+				return 1;
+			} else {
+				SS7_INFO("ISUP General configuration DONE\n");
+			}
+		} /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP)) */
+
+		if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3)) {
+			if (sng_isup_init_mtp3()) {
+				SS7_CRITICAL("Failed to start MTP3\n");
+				return 1;
+			} else {
+				SS7_INFO("Started MTP3!\n");
+			}
+
+			if (ftmod_ss7_mtp3_gen_config()) {
+				SS7_CRITICAL("MTP3 General configuration FAILED!\n");
+				return 1;
+			} else {
+				SS7_INFO("MTP3 General configuration DONE\n");
+			}
+		} /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3)) */
+
+		if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2)) {
+			if (sng_isup_init_mtp2()) {
+				SS7_CRITICAL("Failed to start MTP2\n");
+				return 1;
+			} else {
+				SS7_INFO("Started MTP2!\n");
+			}
+			if (sng_isup_init_mtp1()) {
+				SS7_CRITICAL("Failed to start MTP2\n");
+				return 1;
+			} else {
+				SS7_INFO("Started MTP1!\n");
+			}
+			if (ftmod_ss7_mtp1_gen_config()) {
+				SS7_CRITICAL("MTP1 General configuration FAILED!\n");
+				return 1;
+			} else {
+				SS7_INFO("MTP1 General configuration DONE\n");
+			}
+			if (ftmod_ss7_mtp2_gen_config()) {
+				SS7_CRITICAL("MTP2 General configuration FAILED!\n");
+				return 1;
+			} else {
+				SS7_INFO("MTP2 General configuration DONE\n");
+			}
+		} /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2)) */
 
 		/* update the global gen_config so we don't do it again */
 		g_ftdm_sngss7_data.gen_config = 1;
-	}
+	} /* if (!(g_ftdm_sngss7_data.gen_config)) */
+
+	/* go through all the relays channels and configure it */
+	x = 1;
+	while (g_ftdm_sngss7_data.cfg.relay[x].id != 0) {
+		/* check if this relay channel has been configured already */
+		if (!(g_ftdm_sngss7_data.cfg.relay[x].flags & SNGSS7_CONFIGURED)) {
 
+			/* send the specific configuration */
+			if (ftmod_ss7_relay_chan_config(x)) {
+				SS7_CRITICAL("Relay Channel %d configuration FAILED!\n", x);
+				return 1;
+			} else {
+				SS7_INFO("Relay Channel %d configuration DONE!\n", x);
+			}
+
+			/* set the SNGSS7_CONFIGURED flag */
+			g_ftdm_sngss7_data.cfg.relay[x].flags |= SNGSS7_CONFIGURED;
+		} /* if !SNGSS7_CONFIGURED */
+		x++;
+	} /* while (g_ftdm_sngss7_data.cfg.relay[x].id != 0) */
 
 	x = 1;
-	while (g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) {
+	while (x < (MAX_MTP_LINKS + 1)) {
 		/* check if this link has been configured already */
-		if (!(g_ftdm_sngss7_data.cfg.mtpLink[x].flags & CONFIGURED)) {
+		if (!(g_ftdm_sngss7_data.cfg.mtp1Link[x].flags & SNGSS7_CONFIGURED) &&
+			  (g_ftdm_sngss7_data.cfg.mtp1Link[x].id != 0)) {
 
 			/* configure mtp1 */
 			if (ftmod_ss7_mtp1_psap_config(x)) {
@@ -136,6 +238,18 @@ int  ft_to_sngss7_cfg_all(void)
 				SS7_INFO("MTP1 PSAP %d configuration DONE!\n", x);
 			}
 
+			/* set the SNGSS7_CONFIGURED flag */
+			g_ftdm_sngss7_data.cfg.mtp1Link[x].flags |= SNGSS7_CONFIGURED;
+		}
+		x++;
+	} /* while (g_ftdm_sngss7_data.cfg.mtp1Link[x].id != 0) */
+
+	x = 1;
+	while (x < (MAX_MTP_LINKS + 1)) {
+		/* check if this link has been configured already */
+		if (!(g_ftdm_sngss7_data.cfg.mtp2Link[x].flags & SNGSS7_CONFIGURED) &&
+			 (g_ftdm_sngss7_data.cfg.mtp2Link[x].id != 0)) {
+
 			/* configure mtp2 */
 			if (ftmod_ss7_mtp2_dlsap_config(x)) {
 				SS7_CRITICAL("MTP2 DLSAP %d configuration FAILED!\n",x);
@@ -144,6 +258,18 @@ int  ft_to_sngss7_cfg_all(void)
 				SS7_INFO("MTP2 DLSAP %d configuration DONE!\n", x);
 			}
 
+			/* set the SNGSS7_CONFIGURED flag */
+			g_ftdm_sngss7_data.cfg.mtp2Link[x].flags |= SNGSS7_CONFIGURED;
+		}
+		x++;
+	} /* while (g_ftdm_sngss7_data.cfg.mtp2Link[x].id != 0) */
+
+	x = 1;
+	while (x < (MAX_MTP_LINKS + 1)) {
+		/* check if this link has been configured already */
+		if (!(g_ftdm_sngss7_data.cfg.mtp3Link[x].flags & SNGSS7_CONFIGURED) &&
+			 (g_ftdm_sngss7_data.cfg.mtp3Link[x].id != 0)) {
+
 			/* configure mtp3 */
 			if (ftmod_ss7_mtp3_dlsap_config(x)) {
 				SS7_CRITICAL("MTP3 DLSAP %d configuration FAILED!\n", x);
@@ -152,17 +278,17 @@ int  ft_to_sngss7_cfg_all(void)
 				SS7_INFO("MTP3 DLSAP %d configuration DONE!\n", x);
 			}
 
-			/* set the CONFIGURED flag */
-			g_ftdm_sngss7_data.cfg.mtpLink[x].flags |= CONFIGURED;
+			/* set the SNGSS7_CONFIGURED flag */
+			g_ftdm_sngss7_data.cfg.mtp3Link[x].flags |= SNGSS7_CONFIGURED;
 		}
 		
 		x++;
-	} /* while (g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) */
+	} /* while (g_ftdm_sngss7_data.cfg.mtp3Link[x].id != 0) */
 
 	x = 1;
 	while (g_ftdm_sngss7_data.cfg.nsap[x].id != 0) {
 		/* check if this link has been configured already */
-		if (!(g_ftdm_sngss7_data.cfg.nsap[x].flags & CONFIGURED)) {
+		if (!(g_ftdm_sngss7_data.cfg.nsap[x].flags & SNGSS7_CONFIGURED)) {
 
 			if (ftmod_ss7_mtp3_nsap_config(x)) {
 				SS7_CRITICAL("MTP3 NSAP %d configuration FAILED!\n", x);
@@ -178,9 +304,9 @@ int  ft_to_sngss7_cfg_all(void)
 				SS7_INFO("ISUP NSAP %d configuration DONE!\n", x);
 			}
 
-			/* set the CONFIGURED flag */
-			g_ftdm_sngss7_data.cfg.nsap[x].flags |= CONFIGURED;
-		} /* if !CONFIGURED */
+			/* set the SNGSS7_CONFIGURED flag */
+			g_ftdm_sngss7_data.cfg.nsap[x].flags |= SNGSS7_CONFIGURED;
+		} /* if !SNGSS7_CONFIGURED */
 		
 		x++;
 	} /* while (g_ftdm_sngss7_data.cfg.nsap[x].id != 0) */
@@ -188,7 +314,7 @@ int  ft_to_sngss7_cfg_all(void)
 	x = 1;
 	while (g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) {
 		/* check if this link has been configured already */
-		if (!(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags & CONFIGURED)) {
+		if (!(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags & SNGSS7_CONFIGURED)) {
 
 			if (ftmod_ss7_mtp3_linkset_config(x)) {
 				SS7_CRITICAL("MTP3 LINKSET %d configuration FAILED!\n", x);
@@ -197,9 +323,9 @@ int  ft_to_sngss7_cfg_all(void)
 				SS7_INFO("MTP3 LINKSET %d configuration DONE!\n", x);
 			}
 
-			/* set the CONFIGURED flag */
-			g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags |= CONFIGURED;
-		} /* if !CONFIGURED */
+			/* set the SNGSS7_CONFIGURED flag */
+			g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags |= SNGSS7_CONFIGURED;
+		} /* if !SNGSS7_CONFIGURED */
 		
 		x++;
 	} /* while (g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) */
@@ -207,7 +333,7 @@ int  ft_to_sngss7_cfg_all(void)
 	x = 1;
 	while ((g_ftdm_sngss7_data.cfg.mtpRoute[x].id != 0)) {
 		/* check if this link has been configured already */
-		if (!(g_ftdm_sngss7_data.cfg.mtpRoute[x].flags & CONFIGURED)) {
+		if (!(g_ftdm_sngss7_data.cfg.mtpRoute[x].flags & SNGSS7_CONFIGURED)) {
 
 			if (ftmod_ss7_mtp3_route_config(x)) {
 				SS7_CRITICAL("MTP3 ROUTE %d configuration FAILED!\n", x);
@@ -216,31 +342,33 @@ int  ft_to_sngss7_cfg_all(void)
 				SS7_INFO("MTP3 ROUTE %d configuration DONE!\n",x);
 			}
 
-			/* set the CONFIGURED flag */
-			g_ftdm_sngss7_data.cfg.mtpRoute[x].flags |= CONFIGURED;
-		} /* if !CONFIGURED */
+			/* set the SNGSS7_CONFIGURED flag */
+			g_ftdm_sngss7_data.cfg.mtpRoute[x].flags |= SNGSS7_CONFIGURED;
+		} /* if !SNGSS7_CONFIGURED */
 		
 		x++;
 	} /* while (g_ftdm_sngss7_data.cfg.mtpRoute[x].id != 0) */
 
-	if (!(g_ftdm_sngss7_data.cfg.mtpRoute[0].flags & CONFIGURED)) {
-
-		if (ftmod_ss7_mtp3_route_config(0)) {
-			SS7_CRITICAL("MTP3 ROUTE 0 configuration FAILED!\n");
-			return 1;
-		} else {
-			SS7_INFO("MTP3 ROUTE 0 configuration DONE!\n");
-		}
-
-		/* set the CONFIGURED flag */
-		g_ftdm_sngss7_data.cfg.mtpRoute[0].flags |= CONFIGURED;
-	} /* if !CONFIGURED */
+	if (g_ftdm_sngss7_data.cfg.mtpRoute[1].id != 0) {
+		if (!(g_ftdm_sngss7_data.cfg.mtpRoute[0].flags & SNGSS7_CONFIGURED)) {
+	
+			if (ftmod_ss7_mtp3_route_config(0)) {
+				SS7_CRITICAL("MTP3 ROUTE 0 configuration FAILED!\n");
+				return 1;
+			} else {
+				SS7_INFO("MTP3 ROUTE 0 configuration DONE!\n");
+			}
+	
+			/* set the SNGSS7_CONFIGURED flag */
+			g_ftdm_sngss7_data.cfg.mtpRoute[0].flags |= SNGSS7_CONFIGURED;
+		} /* if !SNGSS7_CONFIGURED */
+	}
 
 
 	x = 1;
 	while (g_ftdm_sngss7_data.cfg.isap[x].id != 0) {
 		/* check if this link has been configured already */
-		if (!(g_ftdm_sngss7_data.cfg.isap[x].flags & CONFIGURED)) {
+		if (!(g_ftdm_sngss7_data.cfg.isap[x].flags & SNGSS7_CONFIGURED)) {
 			
 			if (ftmod_ss7_isup_isap_config(x)) {
 				SS7_CRITICAL("ISUP ISAP %d configuration FAILED!\n", x);
@@ -249,57 +377,51 @@ int  ft_to_sngss7_cfg_all(void)
 				SS7_INFO("ISUP ISAP %d configuration DONE!\n", x);
 			}
 
-			if (ftmod_ss7_cc_isap_config(x)) {
-				SS7_CRITICAL("CC ISAP %d configuration FAILED!\n", x);
-				return 1;
-			} else {
-				SS7_INFO("CC ISAP %d configuration DONE!\n", x);
-			}
-
-			/* set the CONFIGURED flag */
-			g_ftdm_sngss7_data.cfg.isap[x].flags |= CONFIGURED;
-		} /* if !CONFIGURED */
+			/* set the SNGSS7_CONFIGURED flag */
+			g_ftdm_sngss7_data.cfg.isap[x].flags |= SNGSS7_CONFIGURED;
+		} /* if !SNGSS7_CONFIGURED */
 		
 		x++;
 	} /* while (g_ftdm_sngss7_data.cfg.isap[x].id != 0) */
 
-	x = 1;
-	while (g_ftdm_sngss7_data.cfg.isupIntf[x].id != 0) {
-		/* check if this link has been configured already */
-		if (!(g_ftdm_sngss7_data.cfg.isupIntf[x].flags & CONFIGURED)) {
+	if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP)) {
+		x = 1;
+		while (g_ftdm_sngss7_data.cfg.isupIntf[x].id != 0) {
+			/* check if this link has been configured already */
+			if (!(g_ftdm_sngss7_data.cfg.isupIntf[x].flags & SNGSS7_CONFIGURED)) {
+	
+				if (ftmod_ss7_isup_intf_config(x)) {
+					SS7_CRITICAL("ISUP INTF %d configuration FAILED!\n", x);
+					return 1;
+				} else {
+					SS7_INFO("ISUP INTF %d configuration DONE!\n", x);
+					/* set the interface to paused */
+					sngss7_set_flag(&g_ftdm_sngss7_data.cfg.isupIntf[x], SNGSS7_PAUSED);
+				}
+	
+				/* set the SNGSS7_CONFIGURED flag */
+				g_ftdm_sngss7_data.cfg.isupIntf[x].flags |= SNGSS7_CONFIGURED;
+			} /* if !SNGSS7_CONFIGURED */
+			
+			x++;
+		} /* while (g_ftdm_sngss7_data.cfg.isupIntf[x].id != 0) */
+	} /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP)) */
+
+	x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
+	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+		if ( g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
 
-			if (ftmod_ss7_isup_intf_config(x)) {
-				SS7_CRITICAL("ISUP INTF %d configuration FAILED!\n", x);
+			if (ftmod_ss7_isup_ckt_config(x)) {
+				SS7_CRITICAL("ISUP CKT %d configuration FAILED!\n", x);
 				return 1;
 			} else {
-				SS7_INFO("ISUP INTF %d configuration DONE!\n", x);
-				/* set the interface to paused */
-				sngss7_set_flag(&g_ftdm_sngss7_data.cfg.isupIntf[x], SNGSS7_PAUSED);
+				SS7_INFO("ISUP CKT %d configuration DONE!\n", x);
 			}
 
-			/* set the CONFIGURED flag */
-			g_ftdm_sngss7_data.cfg.isupIntf[x].flags |= CONFIGURED;
-		} /* if !CONFIGURED */
-		
-		x++;
-	} /* while (g_ftdm_sngss7_data.cfg.isupIntf[x].id != 0) */
+		} /* if ( g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) */
 
-	x = 1;
-	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
-		/* check if this link has been configured already */
-		if (!(g_ftdm_sngss7_data.cfg.isupCkt[x].flags & CONFIGURED)) {
-			if ( g_ftdm_sngss7_data.cfg.isupCkt[x].type == 0) {
-				if (ftmod_ss7_isup_ckt_config(x)) {
-					SS7_CRITICAL("ISUP CKT %d configuration FAILED!\n", x);
-					return 1;
-				} else {
-					SS7_INFO("ISUP CKT %d configuration DONE!\n", x);
-				}
-			}
-
-			/* set the CONFIGURED flag */
-			g_ftdm_sngss7_data.cfg.isupCkt[x].flags |= CONFIGURED;
-		} /* if !CONFIGURED */
+		/* set the SNGSS7_CONFIGURED flag */
+		g_ftdm_sngss7_data.cfg.isupCkt[x].flags |= SNGSS7_CONFIGURED;
 		
 		x++;
 	} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */
@@ -308,6 +430,44 @@ int  ft_to_sngss7_cfg_all(void)
 }
 
 /******************************************************************************/
+int ftmod_ss7_relay_gen_config(void)
+{
+	RyMngmt	cfg;	/*configuration structure*/
+	Pst		pst;	/*post structure*/
+	
+	/* initalize the post structure */
+	smPstInit(&pst);
+	
+	/* insert the destination Entity */
+	pst.dstEnt = ENTRY;
+	
+	/* clear the configuration structure */
+	memset(&cfg, 0x0, sizeof(RyMngmt));
+	
+	/* fill in some general sections of the header */
+	smHdrInit(&cfg.hdr);
+
+	/* fill in the post structure */
+	smPstInit( &cfg.t.cfg.s.ryGenCfg.lmPst );
+	
+	/*fill in the specific fields of the header */
+	cfg.hdr.msgType						= TCFG;
+	cfg.hdr.entId.ent 					= ENTRY;
+	cfg.hdr.entId.inst					= S_INST;
+	cfg.hdr.elmId.elmnt 				= STGEN;
+
+	cfg.t.cfg.s.ryGenCfg.lmPst.srcEnt	= ENTRY;
+	cfg.t.cfg.s.ryGenCfg.lmPst.dstEnt	= ENTSM;
+
+	cfg.t.cfg.s.ryGenCfg.nmbChan		= 10;
+	cfg.t.cfg.s.ryGenCfg.tmrRes			= RY_PERIOD;
+	cfg.t.cfg.s.ryGenCfg.usta			= 1;
+	
+
+	return(sng_cfg_relay(&pst, &cfg));
+}
+
+/******************************************************************************/
 int ftmod_ss7_mtp1_gen_config(void)
 {
 	L1Mngmt	cfg;	/*configuration structure*/
@@ -575,7 +735,7 @@ int ftmod_ss7_mtp1_psap_config(int id)
 {
 	L1Mngmt			cfg;
 	Pst				pst;
-	sng_mtp_link_t	*k = &g_ftdm_sngss7_data.cfg.mtpLink[id];
+	sng_mtp1_link_t	*k = &g_ftdm_sngss7_data.cfg.mtp1Link[id];
 	
 	/* initalize the post structure */
 	smPstInit(&pst);
@@ -597,8 +757,8 @@ int ftmod_ss7_mtp1_psap_config(int id)
 	
 	cfg.hdr.elmId.elmntInst1	= k->id;
 	
-	cfg.t.cfg.s.l1PSAP.span		= k->mtp1.span;
-	cfg.t.cfg.s.l1PSAP.chan		= k->mtp1.chan;
+	cfg.t.cfg.s.l1PSAP.span		= k->span;
+	cfg.t.cfg.s.l1PSAP.chan		= k->chan;
 	cfg.t.cfg.s.l1PSAP.spId		= k->id;
 
 	return(sng_cfg_mtp1(&pst, &cfg));
@@ -609,7 +769,7 @@ int ftmod_ss7_mtp2_dlsap_config(int id)
 {
 	SdMngmt	cfg;
 	Pst		pst;
-	sng_mtp_link_t	*k = &g_ftdm_sngss7_data.cfg.mtpLink[id];
+	sng_mtp2_link_t	*k = &g_ftdm_sngss7_data.cfg.mtp2Link[id];
 
 	/* initalize the post structure */
 	smPstInit( &pst);
@@ -633,10 +793,15 @@ int ftmod_ss7_mtp2_dlsap_config(int id)
 
 	cfg.t.cfg.s.sdDLSAP.mem.region		= S_REG;					/* memory region */
 	cfg.t.cfg.s.sdDLSAP.mem.pool		= S_POOL;					/* memory pool */
-	cfg.t.cfg.s.sdDLSAP.swtch			= k->mtp2.linkType;			/* protocol type */
+	cfg.t.cfg.s.sdDLSAP.swtch			= k->linkType;			/* protocol type */
 	cfg.t.cfg.s.sdDLSAP.priorDl			= PRIOR0;					/* priority for data link layer */
 	cfg.t.cfg.s.sdDLSAP.routeDl			= RTESPEC;					/* route for data link layer */
 	cfg.t.cfg.s.sdDLSAP.selectorDl		= 0;						/* upper interface selector */
+	if (k->mtp1ProcId > 0) {
+		cfg.t.cfg.s.sdDLSAP.dstProcId	= k->mtp1ProcId;		/* the procid of MAC/L1/MTP1 */
+	} else {
+		cfg.t.cfg.s.sdDLSAP.dstProcId	= SFndProcId();				/* the procid of MAC/L1/MTP1 */
+	}
 	cfg.t.cfg.s.sdDLSAP.dstProcId		= SFndProcId();				/* the procid of MAC/L1/MTP1 */
 	cfg.t.cfg.s.sdDLSAP.entMac			= ENTL1;					/* entity for MAC */
 	cfg.t.cfg.s.sdDLSAP.instMac			= S_INST;					/* instance for MAC */
@@ -646,22 +811,22 @@ int ftmod_ss7_mtp2_dlsap_config(int id)
 	cfg.t.cfg.s.sdDLSAP.memMac.region	= S_REG;					/* memory region and pool id for MAC */
 	cfg.t.cfg.s.sdDLSAP.memMac.pool		= S_POOL;
 	cfg.t.cfg.s.sdDLSAP.maxOutsFrms		= MAX_SD_OUTSTANDING;		/* maximum outstanding frames */
-	cfg.t.cfg.s.sdDLSAP.errType			= k->mtp2.errorType;
+	cfg.t.cfg.s.sdDLSAP.errType			= k->errorType;
 	cfg.t.cfg.s.sdDLSAP.t1.enb			= TRUE;						/* timer 1 - Alignment Ready Timer */
-	cfg.t.cfg.s.sdDLSAP.t1.val			= k->mtp2.t1;
+	cfg.t.cfg.s.sdDLSAP.t1.val			= k->t1;
 	cfg.t.cfg.s.sdDLSAP.t2.enb			= TRUE;						/* timer 2 - Not Aligned Timer */
-	cfg.t.cfg.s.sdDLSAP.t2.val			= k->mtp2.t2;
+	cfg.t.cfg.s.sdDLSAP.t2.val			= k->t2;
 	cfg.t.cfg.s.sdDLSAP.t3.enb			= TRUE;						/* timer 3 - Aligned Timer */
-	cfg.t.cfg.s.sdDLSAP.t3.val			= k->mtp2.t3;
+	cfg.t.cfg.s.sdDLSAP.t3.val			= k->t3;
 	cfg.t.cfg.s.sdDLSAP.t5.enb			= TRUE;						/* timer 5 - Sending SIB timer */
-	cfg.t.cfg.s.sdDLSAP.t5.val			= k->mtp2.t5;
+	cfg.t.cfg.s.sdDLSAP.t5.val			= k->t5;
 	cfg.t.cfg.s.sdDLSAP.t6.enb			= TRUE;						/* timer 6 - Remote Congestion Timer */
-	cfg.t.cfg.s.sdDLSAP.t6.val			= k->mtp2.t6;
+	cfg.t.cfg.s.sdDLSAP.t6.val			= k->t6;
 	cfg.t.cfg.s.sdDLSAP.t7.enb			= TRUE;						/* timer 7 - Excessive delay of acknowledgement timer */
-	cfg.t.cfg.s.sdDLSAP.t7.val			= k->mtp2.t7;
-	cfg.t.cfg.s.sdDLSAP.provEmrgcy		= k->mtp2.t4e;				/* emergency proving period */
-	cfg.t.cfg.s.sdDLSAP.provNormal		= k->mtp2.t4n;				/* normal proving period */
-	cfg.t.cfg.s.sdDLSAP.lssuLen			= k->mtp2.lssuLength;			/* one or two byte LSSU length */
+	cfg.t.cfg.s.sdDLSAP.t7.val			= k->t7;
+	cfg.t.cfg.s.sdDLSAP.provEmrgcy		= k->t4e;				/* emergency proving period */
+	cfg.t.cfg.s.sdDLSAP.provNormal		= k->t4n;				/* normal proving period */
+	cfg.t.cfg.s.sdDLSAP.lssuLen			= k->lssuLength;			/* one or two byte LSSU length */
 	cfg.t.cfg.s.sdDLSAP.maxFrmLen		= MAX_SD_FRAME_LEN;			/* max frame length for MSU */
 	cfg.t.cfg.s.sdDLSAP.congDisc		= FALSE;					/* congestion discard TRUE or FALSE */
 	cfg.t.cfg.s.sdDLSAP.sdT				= MAX_SD_SUERM;				/* SUERM error rate threshold */
@@ -670,7 +835,7 @@ int ftmod_ss7_mtp2_dlsap_config(int id)
 	cfg.t.cfg.s.sdDLSAP.sdN1			= MAX_SD_MSU_RETRANS;		/* maximum number of MSUs for retransmission */
 	cfg.t.cfg.s.sdDLSAP.sdN2			= MAX_SD_OCTETS_RETRANS;	/* maximum number of MSU octets for retrans */
 	cfg.t.cfg.s.sdDLSAP.sdCp			= MAX_SD_ALIGN_ATTEMPTS;	/* maximum number of alignment attempts */
-	cfg.t.cfg.s.sdDLSAP.spIdSE			= k->mtp2.mtp1Id;				/* service provider id */
+	cfg.t.cfg.s.sdDLSAP.spIdSE			= k->mtp1Id;				/* service provider id */
 	cfg.t.cfg.s.sdDLSAP.sdtFlcStartTr	= 256;						/* SDT interface flow control start thresh */
 	cfg.t.cfg.s.sdDLSAP.sdtFlcEndTr		= 512;						/* SDT interface flow control end thresh */
 
@@ -707,7 +872,6 @@ int ftmod_ss7_mtp2_dlsap_config(int id)
 #endif /*RUG*/
 
 	return(sng_cfg_mtp2(&pst, &cfg));
-	return 0;
 }
 
 /******************************************************************************/
@@ -715,7 +879,7 @@ int ftmod_ss7_mtp3_dlsap_config(int id)
 {
 	Pst				pst;
 	SnMngmt			cfg;
-	sng_mtp_link_t	*k = &g_ftdm_sngss7_data.cfg.mtpLink[id];
+	sng_mtp3_link_t	*k = &g_ftdm_sngss7_data.cfg.mtp3Link[id];
 
 
 	/* initalize the post structure */
@@ -738,14 +902,14 @@ int ftmod_ss7_mtp3_dlsap_config(int id)
 
 	cfg.hdr.elmId.elmntInst1 			= k->id;
 
-	cfg.t.cfg.s.snDLSAP.lnkSetId		= k->mtp3.linkSetId;	/* link set ID */
-	cfg.t.cfg.s.snDLSAP.opc				= k->mtp3.spc;			/* Originating Postatic int Code */
-	cfg.t.cfg.s.snDLSAP.adjDpc			= k->mtp3.apc;			/* Adlacent Destination Postatic int Code */
+	cfg.t.cfg.s.snDLSAP.lnkSetId		= k->linkSetId;			/* link set ID */
+	cfg.t.cfg.s.snDLSAP.opc				= k->spc;				/* Originating Postatic int Code */
+	cfg.t.cfg.s.snDLSAP.adjDpc			= k->apc;				/* Adlacent Destination Postatic int Code */
 	cfg.t.cfg.s.snDLSAP.lnkPrior		= 0;					/* link priority within the link set */
 	cfg.t.cfg.s.snDLSAP.msgSize			= MAX_SN_MSG_SIZE;		/* message length */
 	cfg.t.cfg.s.snDLSAP.msgPrior		= 0;					/* management message priority */
-	cfg.t.cfg.s.snDLSAP.lnkType			= k->mtp3.linkType;		/* link type ANSI, ITU, BICI or CHINA */
-	cfg.t.cfg.s.snDLSAP.upSwtch			= k->mtp3.switchType;	/* user part switch type */
+	cfg.t.cfg.s.snDLSAP.lnkType			= k->linkType;			/* link type ANSI, ITU, BICI or CHINA */
+	cfg.t.cfg.s.snDLSAP.upSwtch			= k->switchType;		/* user part switch type */
 	cfg.t.cfg.s.snDLSAP.maxSLTtry		= MAX_SLTM_RETRIES;		/* maximun times to retry SLTM */
 	cfg.t.cfg.s.snDLSAP.p0QLen			= 32;					/* size of the priority 0 Q */
 	cfg.t.cfg.s.snDLSAP.p1QLen			= 32;					/* size of the priority 1 Q */
@@ -756,7 +920,7 @@ int ftmod_ss7_mtp3_dlsap_config(int id)
 	cfg.t.cfg.s.snDLSAP.maxCredit		= MAX_SN_CREDIT;		/* max credit */
 #endif /* SDT2 */
 	cfg.t.cfg.s.snDLSAP.lnkId			= 0;					/* signalling link allocation procedure identity */
-	cfg.t.cfg.s.snDLSAP.lnkTstSLC		= k->mtp3.slc;			/* link selection code for link test */
+	cfg.t.cfg.s.snDLSAP.lnkTstSLC		= k->slc;				/* link selection code for link test */
 	cfg.t.cfg.s.snDLSAP.tstLen			= 6;					/* link test pattern length */
 	cfg.t.cfg.s.snDLSAP.tst[0]			= 'K';					/* link test pattern */
 	cfg.t.cfg.s.snDLSAP.tst[1]			= 'O';					/* link test pattern */
@@ -764,8 +928,8 @@ int ftmod_ss7_mtp3_dlsap_config(int id)
 	cfg.t.cfg.s.snDLSAP.tst[3]			= 'R';					/* link test pattern */
 	cfg.t.cfg.s.snDLSAP.tst[4]			= 'A';					/* link test pattern */
 	cfg.t.cfg.s.snDLSAP.tst[5]			= 'D';					/* link test pattern */
-	cfg.t.cfg.s.snDLSAP.ssf				= k->mtp3.ssf;			/* sub service field */ 
-	cfg.t.cfg.s.snDLSAP.dstProcId		= SFndProcId();			/* destination processor id */
+	cfg.t.cfg.s.snDLSAP.ssf				= k->ssf;				/* sub service field */ 
+	cfg.t.cfg.s.snDLSAP.dstProcId		= k->mtp2ProcId;		/* destination processor id */
 	cfg.t.cfg.s.snDLSAP.dstEnt			= ENTSD;				/* entity */
 	cfg.t.cfg.s.snDLSAP.dstInst			= S_INST;				/* instance */
 	cfg.t.cfg.s.snDLSAP.prior			= PRIOR0;				/* priority */
@@ -773,9 +937,9 @@ int ftmod_ss7_mtp3_dlsap_config(int id)
 	cfg.t.cfg.s.snDLSAP.selector		= 0;					/* lower layer selector */
 	cfg.t.cfg.s.snDLSAP.mem.region		= S_REG;				/* memory region id */
 	cfg.t.cfg.s.snDLSAP.mem.pool		= S_POOL;				/* memory pool id */
-	cfg.t.cfg.s.snDLSAP.spId			= k->mtp3.mtp2Id		;/* service provider id */
+	cfg.t.cfg.s.snDLSAP.spId			= k->mtp2Id;			/* service provider id */
 
-	switch (k->mtp3.linkType) {
+	switch (k->linkType) {
 	/**************************************************************************/
 	case (LSN_SW_ANS):
 	case (LSN_SW_ANS96):
@@ -793,9 +957,9 @@ int ftmod_ss7_mtp3_dlsap_config(int id)
 		cfg.t.cfg.s.snDLSAP.dpcLen		= DPC14;				/* dpc length 14 bits */
 		break;
 	/**************************************************************************/
-	} /* switch (k->mtp3.linkType) */
+	} /* switch (k->linkType) */
 
-	switch (k->mtp3.linkType) {
+	switch (k->linkType) {
 	/**************************************************************************/
 	case (LSN_SW_ANS):
 	case (LSN_SW_ANS96):
@@ -811,51 +975,51 @@ int ftmod_ss7_mtp3_dlsap_config(int id)
 		cfg.t.cfg.s.snDLSAP.flushContFlag	= FALSE;			/* flush continue handling */
 		break;
 	/**************************************************************************/
-	} /* switch (k->mtp3.linkType) */
+	} /* switch (k->linkType) */
 
 	cfg.t.cfg.s.snDLSAP.tmr.t1.enb		= TRUE;					/* t1 - delay to avoid missequencing on changeover */
-	cfg.t.cfg.s.snDLSAP.tmr.t1.val		= k->mtp3.t1;
+	cfg.t.cfg.s.snDLSAP.tmr.t1.val		= k->t1;
 	cfg.t.cfg.s.snDLSAP.tmr.t2.enb		= TRUE;					/* t2 - waiting for changeover ack */
-	cfg.t.cfg.s.snDLSAP.tmr.t2.val		= k->mtp3.t2;
+	cfg.t.cfg.s.snDLSAP.tmr.t2.val		= k->t2;
 	cfg.t.cfg.s.snDLSAP.tmr.t3.enb		= TRUE;					/* t3 - delay to avoid missequencing on changeback */
-	cfg.t.cfg.s.snDLSAP.tmr.t3.val		= k->mtp3.t3;
+	cfg.t.cfg.s.snDLSAP.tmr.t3.val		= k->t3;
 	cfg.t.cfg.s.snDLSAP.tmr.t4.enb		= TRUE;					/* t4 - waiting for first changeback ack */
-	cfg.t.cfg.s.snDLSAP.tmr.t4.val		= k->mtp3.t4;
+	cfg.t.cfg.s.snDLSAP.tmr.t4.val		= k->t4;
 	cfg.t.cfg.s.snDLSAP.tmr.t5.enb		= TRUE;					/* t5 - waiting for second changeback ack */
-	cfg.t.cfg.s.snDLSAP.tmr.t5.val		= k->mtp3.t5;
+	cfg.t.cfg.s.snDLSAP.tmr.t5.val		= k->t5;
 	cfg.t.cfg.s.snDLSAP.tmr.t7.enb		= TRUE;					/* t7 - waiting for link connection ack */
-	cfg.t.cfg.s.snDLSAP.tmr.t7.val		= k->mtp3.t7;
+	cfg.t.cfg.s.snDLSAP.tmr.t7.val		= k->t7;
 	cfg.t.cfg.s.snDLSAP.tmr.t12.enb		= TRUE;					/* t12 - waiting for uninhibit ack */
-	cfg.t.cfg.s.snDLSAP.tmr.t12.val		= k->mtp3.t12;
+	cfg.t.cfg.s.snDLSAP.tmr.t12.val		= k->t12;
 	cfg.t.cfg.s.snDLSAP.tmr.t13.enb		= TRUE;					/* t13 - waiting for forced uninhibit */
-	cfg.t.cfg.s.snDLSAP.tmr.t13.val		= k->mtp3.t13;
+	cfg.t.cfg.s.snDLSAP.tmr.t13.val		= k->t13;
 	cfg.t.cfg.s.snDLSAP.tmr.t14.enb		= TRUE;					/* t14 - waiting for inhibition ack */
-	cfg.t.cfg.s.snDLSAP.tmr.t14.val		= k->mtp3.t14;
+	cfg.t.cfg.s.snDLSAP.tmr.t14.val		= k->t14;
 	cfg.t.cfg.s.snDLSAP.tmr.t17.enb		= TRUE;					/* t17 - delay to avoid oscillation of initial alignment failure */
-	cfg.t.cfg.s.snDLSAP.tmr.t17.val		= k->mtp3.t17;
+	cfg.t.cfg.s.snDLSAP.tmr.t17.val		= k->t17;
 	cfg.t.cfg.s.snDLSAP.tmr.t22.enb		= TRUE;					/* t22 - local inhibit test timer */
-	cfg.t.cfg.s.snDLSAP.tmr.t22.val		= k->mtp3.t22;
+	cfg.t.cfg.s.snDLSAP.tmr.t22.val		= k->t22;
 	cfg.t.cfg.s.snDLSAP.tmr.t23.enb		= TRUE;					/* t23 - remote inhibit test timer */
-	cfg.t.cfg.s.snDLSAP.tmr.t23.val		= k->mtp3.t23;
+	cfg.t.cfg.s.snDLSAP.tmr.t23.val		= k->t23;
 	cfg.t.cfg.s.snDLSAP.tmr.t24.enb		= TRUE;					/* t24 - stabilizing timer */
-	cfg.t.cfg.s.snDLSAP.tmr.t24.val		= k->mtp3.t24;
+	cfg.t.cfg.s.snDLSAP.tmr.t24.val		= k->t24;
 	cfg.t.cfg.s.snDLSAP.tmr.t31.enb		= TRUE;					/* t31 - BSN requested timer */
-	cfg.t.cfg.s.snDLSAP.tmr.t31.val		= k->mtp3.t31;
+	cfg.t.cfg.s.snDLSAP.tmr.t31.val		= k->t31;
 	cfg.t.cfg.s.snDLSAP.tmr.t32.enb		= TRUE;					/* t32 - SLT timer */
-	cfg.t.cfg.s.snDLSAP.tmr.t32.val		= k->mtp3.t32;
+	cfg.t.cfg.s.snDLSAP.tmr.t32.val		= k->t32;
 	cfg.t.cfg.s.snDLSAP.tmr.t33.enb		= TRUE;					/* t33 - connecting timer */
-	cfg.t.cfg.s.snDLSAP.tmr.t33.val		= k->mtp3.t33;
+	cfg.t.cfg.s.snDLSAP.tmr.t33.val		= k->t33;
 	cfg.t.cfg.s.snDLSAP.tmr.t34.enb		= TRUE;					/* t34 - periodic signalling link test timer */
-	cfg.t.cfg.s.snDLSAP.tmr.t34.val		= k->mtp3.t34;
+	cfg.t.cfg.s.snDLSAP.tmr.t34.val		= k->t34;
 #if (SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || defined(TDS_ROLL_UPGRADE_SUPPORT))
 	cfg.t.cfg.s.snDLSAP.tmr.t35.enb		= TRUE;					/* t35 - false link congestion timer, same as t31 of ANSI'96*/
-	cfg.t.cfg.s.snDLSAP.tmr.t35.val		= k->mtp3.t35;
+	cfg.t.cfg.s.snDLSAP.tmr.t35.val		= k->t35;
 	cfg.t.cfg.s.snDLSAP.tmr.t36.enb		= TRUE;					/* t36 - false link congestion timer, same as t33 of ANSI'96*/
-	cfg.t.cfg.s.snDLSAP.tmr.t36.val		= k->mtp3.t36;	
+	cfg.t.cfg.s.snDLSAP.tmr.t36.val		= k->t36;	
 	cfg.t.cfg.s.snDLSAP.tmr.t37.enb		= TRUE;					/* t37 - false link congestion timer, same as t34 of ANSI'96*/
-	cfg.t.cfg.s.snDLSAP.tmr.t37.val		= k->mtp3.t37;
+	cfg.t.cfg.s.snDLSAP.tmr.t37.val		= k->t37;
 	cfg.t.cfg.s.snDLSAP.tmr.tCraft.enb	= TRUE;					/* link referral craft timer - T19 in ANSI */
-	cfg.t.cfg.s.snDLSAP.tmr.tCraft.val	= k->mtp3.tcraft;
+	cfg.t.cfg.s.snDLSAP.tmr.tCraft.val	= k->tcraft;
 #endif
 #ifdef SDT2
 	cfg.t.cfg.s.snDLSAP.tmr.tFlc.enb	= TRUE;					/* flow control timer */
@@ -1217,6 +1381,11 @@ int ftmod_ss7_isup_ckt_config(int id)
 	/* insert the destination Entity */
 	pst.dstEnt = ENTSI;
 
+	/* check the for the correct ProcId and make sure it goes to the right system */
+	if (g_ftdm_sngss7_data.cfg.procId != 1) {
+		pst.dstProcId = 1;
+	}
+
 	/*clear the configuration structure*/
 	memset(&cfg, 0x0, sizeof(SiMngmt));
 
@@ -1417,11 +1586,11 @@ int ftmod_ss7_isup_isap_config(int id)
 }
 
 /******************************************************************************/
-int ftmod_ss7_cc_isap_config(int id)
+int ftmod_ss7_cc_isap_config(int dstProcId)
 {
 	CcMngmt	 cfg;
 	Pst		 pst;
-	sng_isap_t	*k = &g_ftdm_sngss7_data.cfg.isap[id];
+
 
 	/* initalize the post structure */
 	smPstInit(&pst);
@@ -1441,11 +1610,11 @@ int ftmod_ss7_cc_isap_config(int id)
 	cfg.hdr.entId.inst					= S_INST;
 	cfg.hdr.elmId.elmnt					= STISAP;
 
-	cfg.hdr.elmId.elmntInst1 			= k->id;
+	cfg.hdr.elmId.elmntInst1 			= 1;
 
-	cfg.t.cfg.s.ccISAP.suId			 	= k->suId;
-	cfg.t.cfg.s.ccISAP.spId			 	= k->spId;
-	cfg.t.cfg.s.ccISAP.pst.dstProcId	= SFndProcId();
+	cfg.t.cfg.s.ccISAP.suId			 	= 1;
+	cfg.t.cfg.s.ccISAP.spId			 	= 1;
+	cfg.t.cfg.s.ccISAP.pst.dstProcId	= dstProcId;
 	cfg.t.cfg.s.ccISAP.pst.dstEnt		= ENTSI;
 	cfg.t.cfg.s.ccISAP.pst.dstInst		= S_INST;
 	cfg.t.cfg.s.ccISAP.pst.srcProcId	= SFndProcId();
@@ -1461,6 +1630,70 @@ int ftmod_ss7_cc_isap_config(int id)
 }
 
 /******************************************************************************/
+int ftmod_ss7_relay_chan_config(int id)
+{
+	RyMngmt	cfg;	/*configuration structure*/
+	Pst		pst;	/*post structure*/
+	sng_relay_t		*k = &g_ftdm_sngss7_data.cfg.relay[id];
+	
+	/* initalize the post structure */
+	smPstInit(&pst);
+	
+	/* insert the destination Entity */
+	pst.dstEnt = ENTRY;
+	
+	/* clear the configuration structure */
+	memset(&cfg, 0x0, sizeof(RyMngmt));
+	
+	/* fill in some general sections of the header */
+	smHdrInit(&cfg.hdr);
+
+	/*fill in the specific fields of the header */
+	cfg.hdr.msgType							= TCFG;
+	cfg.hdr.entId.ent 						= ENTRY;
+	cfg.hdr.entId.inst						= S_INST;
+	cfg.hdr.elmId.elmnt 					= STCHCFG;
+
+	cfg.hdr.elmId.elmntInst1 				= k->id;
+
+	cfg.t.cfg.s.ryChanCfg.id				= k->id;					/* channel id */
+	cfg.t.cfg.s.ryChanCfg.type				= k->type;					/* channel type */
+/*	cfg.t.cfg.s.ryChanCfg.msInd				=;*/						/* master/slave indicator */
+	if (k->type == LRY_CT_TCP_LISTEN) {
+		cfg.t.cfg.s.ryChanCfg.low			= 0;						/* low proc id for channel */
+		cfg.t.cfg.s.ryChanCfg.high			= 0;						/* high proc id for channel */
+	} else {
+		cfg.t.cfg.s.ryChanCfg.low			= k->procId;				/* low proc id for channel */
+		cfg.t.cfg.s.ryChanCfg.high			= k->procId;				/* high proc id for channel */
+	}
+	cfg.t.cfg.s.ryChanCfg.nmbScanQ			= MAX_RELAY_NMBSCAN;		/* number of times to scan the queue */
+	cfg.t.cfg.s.ryChanCfg.flags				= LRY_FLG_INTR;				/* flags */
+	cfg.t.cfg.s.ryChanCfg.congThrsh			= MAX_RELAY_CONGTHRSH;		/* congestion threshold */
+	cfg.t.cfg.s.ryChanCfg.dropThrsh			= 0;						/* drop threshold */
+	cfg.t.cfg.s.ryChanCfg.contThrsh			= MAX_RELAY_CONGTHRSH + 1;	/* continue threshold */
+	cfg.t.cfg.s.ryChanCfg.kaTxTmr.enb		= 1;						/* keep alive transmit timer config */
+	cfg.t.cfg.s.ryChanCfg.kaTxTmr.val		= RY_TX_KP_ALIVE_TMR;
+	cfg.t.cfg.s.ryChanCfg.kaRxTmr.enb		= 1;						/* keep alive receive timer config */
+	cfg.t.cfg.s.ryChanCfg.kaRxTmr.val		= RY_RX_KP_ALIVE_TMR;
+	cfg.t.cfg.s.ryChanCfg.btTmr.enb			= 1;						/* boot timer */
+	cfg.t.cfg.s.ryChanCfg.btTmr.val			= RY_BT_TMR;
+	cfg.t.cfg.s.ryChanCfg.region			= S_REG;					/* Relay region */
+	cfg.t.cfg.s.ryChanCfg.pool				= S_POOL;					/* Relay pool */
+#if (RY_ENBUDPSOCK || RY_ENBTCPSOCK) 
+	cfg.t.cfg.s.ryChanCfg.listenPortNo		= k->port;					/* Listen Port of Rx Relay Channel*/
+	strncpy(cfg.t.cfg.s.ryChanCfg.transmittoHostName, k->hostname, (size_t)RY_REMHOSTNAME_SIZE);
+	cfg.t.cfg.s.ryChanCfg.transmittoPortNo	= k->port;					/* TransmitTo PortId for Tx Relay Channel */
+	cfg.t.cfg.s.ryChanCfg.targetProcId		= k->procId;				/* procId of the node present in the other end of this channel                     */
+# ifdef LRY1
+	cfg.t.cfg.s.ryChanCfg.sockParam			=;   /* Socket Parameters */
+# endif /* LRY1 */
+# ifdef LRYV2
+	cfg.t.cfg.s.ryChanCfg.selfHostName[RY_REMHOSTNAME_SIZE];
+# endif /* LRY2 */
+#endif /* RY_ENBUDPSOCK || RY_ENBTCPSOCK */
+
+	return(sng_cfg_relay(&pst, &cfg));
+}
 
 /******************************************************************************/
 /* For Emacs:
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c
index dc2d24f..4ab4359 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c
@@ -46,6 +46,8 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha
 
 static ftdm_status_t handle_print_usuage(ftdm_stream_handle_t *stream);
 
+static ftdm_status_t handle_show_procId(ftdm_stream_handle_t *stream);
+
 static ftdm_status_t handle_set_function_trace(ftdm_stream_handle_t *stream, int on, int level);
 static ftdm_status_t handle_set_message_trace(ftdm_stream_handle_t *stream, int on, int level);
 static ftdm_status_t handle_set_inhibit(ftdm_stream_handle_t *stream, char *name);
@@ -67,6 +69,8 @@ static ftdm_status_t handle_tx_ubl(ftdm_stream_handle_t *stream, int span, int c
 static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int chan, int range, int verbose);
 static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int chan, int range, int verbose);
 
+static ftdm_status_t handle_bind_link(ftdm_stream_handle_t *stream, char *name);
+static ftdm_status_t handle_unbind_link(ftdm_stream_handle_t *stream, char *name);
 static ftdm_status_t handle_activate_link(ftdm_stream_handle_t *stream, char *name);
 static ftdm_status_t handle_deactivate_link(ftdm_stream_handle_t *stream, char *name);
 
@@ -76,9 +80,12 @@ static ftdm_status_t handle_deactivate_linkset(ftdm_stream_handle_t *stream, cha
 static ftdm_status_t handle_tx_lpo(ftdm_stream_handle_t *stream, char *name);
 static ftdm_status_t handle_tx_lpr(ftdm_stream_handle_t *stream, char *name);
 
-static ftdm_status_t handle_status_link(ftdm_stream_handle_t *stream, char *name);
+static ftdm_status_t handle_status_mtp3link(ftdm_stream_handle_t *stream, char *name);
+static ftdm_status_t handle_status_mtp2link(ftdm_stream_handle_t *stream, char *name);
 static ftdm_status_t handle_status_linkset(ftdm_stream_handle_t *stream, char *name);
 
+static ftdm_status_t handle_status_relay(ftdm_stream_handle_t *stream, char *name);
+
 static ftdm_status_t extract_span_chan(char *argv[10], int pos, int *span, int *chan);
 static ftdm_status_t check_arg_count(int args, int min);
 /******************************************************************************/
@@ -111,18 +118,29 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha
 
 		if (!strcasecmp(argv[c], "status")) {
 		/**********************************************************************/
+			if (check_arg_count(argc, 3)) goto handle_cli_error_argc;
 			c++;
 
-			if (!strcasecmp(argv[c], "link")) {
+			if (!strcasecmp(argv[c], "mtp3")) {
+			/******************************************************************/
+				c++;
+				handle_status_mtp3link(stream, argv[c]);
+			/******************************************************************/
+			} else if (!strcasecmp(argv[c], "mtp2")) {
 			/******************************************************************/
 				c++;
-				handle_status_link(stream, argv[c]);
+				handle_status_mtp2link(stream, argv[c]);
 			/******************************************************************/
 			} else if (!strcasecmp(argv[c], "linkset")) {
 			/******************************************************************/
 				c++;
 				handle_status_linkset(stream, argv[c]);
 			/******************************************************************/
+			} else if (!strcasecmp(argv[c], "relay")) {
+			/******************************************************************/
+				c++;
+				handle_status_relay(stream, argv[c]);
+			/******************************************************************/
 			} else if (!strcasecmp(argv[c], "span")) {
 			/******************************************************************/
 				if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
@@ -256,6 +274,10 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha
 											sts.rx_frm, sts.rx_err, sts.rx_fisu, sts.rx_lssu, sts.rx_msu);
 */
 		/**********************************************************************/
+		} else if (!strcasecmp(argv[c], "procid")) {
+		/**********************************************************************/
+			handle_show_procId(stream);
+		/**********************************************************************/
 		} else {
 		/**********************************************************************/
 			stream->write_function(stream, "Unknown \"show\" command\n");
@@ -534,6 +556,44 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha
 		/**********************************************************************/
 		}
 	/**************************************************************************/
+	} else if (!strcasecmp(argv[c], "bind")) {
+	/**************************************************************************/
+		if (check_arg_count(argc, 2)) goto handle_cli_error_argc;
+		c++;
+
+		if (!strcasecmp(argv[c], "link")) {
+		/**********************************************************************/
+			if (check_arg_count(argc, 3)) goto handle_cli_error_argc;
+			c++;
+			
+			handle_bind_link(stream, argv[c]);
+		/**********************************************************************/
+		} else {
+		/**********************************************************************/
+			stream->write_function(stream, "Unknown \"bind\" command\n");
+			goto handle_cli_error;
+		/**********************************************************************/
+		}
+	/**************************************************************************/
+	} else if (!strcasecmp(argv[c], "unbind")) {
+	/**************************************************************************/
+		if (check_arg_count(argc, 2)) goto handle_cli_error_argc;
+		c++;
+
+		if (!strcasecmp(argv[c], "link")) {
+		/**********************************************************************/
+			if (check_arg_count(argc, 3)) goto handle_cli_error_argc;
+			c++;
+			
+			handle_unbind_link(stream, argv[c]);
+		/**********************************************************************/
+		} else {
+		/**********************************************************************/
+			stream->write_function(stream, "Unknown \"bind\" command\n");
+			goto handle_cli_error;
+		/**********************************************************************/
+		}
+	/**************************************************************************/
 	} else if (!strcasecmp(argv[c], "activate")) {
 	/**************************************************************************/
 		if (check_arg_count(argc, 2)) goto handle_cli_error_argc;
@@ -650,6 +710,16 @@ static ftdm_status_t handle_print_usuage(ftdm_stream_handle_t *stream)
 }
 
 /******************************************************************************/
+static ftdm_status_t handle_show_procId(ftdm_stream_handle_t *stream)
+{
+	int	procId = sng_get_procId();
+
+	stream->write_function(stream, "Local ProcId = %d\n", procId);
+
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
 static ftdm_status_t handle_set_function_trace(ftdm_stream_handle_t *stream, int on, int level)
 {
 	stream->write_function(stream, "ftmod_sangoma_ss7 Function Trace was %s, level = %d\n",
@@ -693,7 +763,7 @@ static ftdm_status_t handle_show_free(ftdm_stream_handle_t *stream, int span, in
 	int				 lspan;
 	int				 lchan;
 
-	x=1;
+	x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
 	free = 0;
 	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
 		if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
@@ -756,7 +826,7 @@ static ftdm_status_t handle_show_inuse(ftdm_stream_handle_t *stream, int span, i
 	int				 lspan;
 	int				 lchan;
 
-	x=1;
+	x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
 	in_use = 0;
 	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
 		if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
@@ -826,7 +896,7 @@ static ftdm_status_t handle_show_inreset(ftdm_stream_handle_t *stream, int span,
 	int				 lspan;
 	int				 lchan;
 
-	x=1;
+	x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
 	in_reset = 0;
 	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
 		if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
@@ -848,10 +918,10 @@ static ftdm_status_t handle_show_inreset(ftdm_stream_handle_t *stream, int span,
 			}
 
 			if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) {
-				if ((sngss7_test_flag(ss7_info, FLAG_RESET_RX)) ||
-					(sngss7_test_flag(ss7_info, FLAG_RESET_TX)) ||
-					(sngss7_test_flag(ss7_info, FLAG_GRP_RESET_RX)) ||
-					(sngss7_test_flag(ss7_info, FLAG_GRP_RESET_TX))) {
+				if ((sngss7_test_ckt_flag(ss7_info, FLAG_RESET_RX)) ||
+					(sngss7_test_ckt_flag(ss7_info, FLAG_RESET_TX)) ||
+					(sngss7_test_ckt_flag(ss7_info, FLAG_GRP_RESET_RX)) ||
+					(sngss7_test_ckt_flag(ss7_info, FLAG_GRP_RESET_TX))) {
 					
 					if (verbose) {
 						stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|in_reset=Y\n",
@@ -862,7 +932,7 @@ static ftdm_status_t handle_show_inreset(ftdm_stream_handle_t *stream, int span,
 		
 					/*increment the count of circuits in reset */
 					in_reset++;
-				} /* if ((sngss7_test_flag(ss7_info, FLAG_RESET_RX) ... */
+				} /* if ((sngss7_test_ckt_flag(ss7_info, FLAG_RESET_RX) ... */
 			} /* if ( span and chan) */
 		} /* if ( cic != 0) */
 
@@ -885,7 +955,7 @@ static ftdm_status_t handle_show_flags(ftdm_stream_handle_t *stream, int span, i
 	int				 lspan;
 	int				 lchan;
 
-	x=1;
+	x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
 	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
 		if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
 			ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
@@ -913,7 +983,7 @@ static ftdm_status_t handle_show_flags(ftdm_stream_handle_t *stream, int span, i
 	
 				for (bit = 0; bit < 33; bit++) {
 					stream->write_function(stream, "|");
-					if (ss7_info->flags & ( 0x1 << bit)) {
+					if (ss7_info->ckt_flags & ( 0x1 << bit)) {
 						stream->write_function(stream, "%2d=1", bit);
 					} else {
 						stream->write_function(stream, "%2d=0", bit);
@@ -941,7 +1011,7 @@ static ftdm_status_t handle_show_blocks(ftdm_stream_handle_t *stream, int span,
 	int				 lspan;
 	int				 lchan;
 
-	x=1;
+	x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
 	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
 		if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
 			ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
@@ -967,37 +1037,37 @@ static ftdm_status_t handle_show_blocks(ftdm_stream_handle_t *stream, int span,
 							ftdmchan->physical_chan_id,
 							ss7_info->circuit->cic);
 
-				if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX))) {
+				if((sngss7_test_ckt_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || (sngss7_test_ckt_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX))) {
 					stream->write_function(stream, "l_mn=Y|");
 				}else {
 					stream->write_function(stream, "l_mn=N|");
 				}
 
-				if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) {
+				if((sngss7_test_ckt_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || (sngss7_test_ckt_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) {
 					stream->write_function(stream, "r_mn=Y|");
 				}else {
 					stream->write_function(stream, "r_mn=N|");
 				}
 
-				if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) {
+				if(sngss7_test_ckt_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) {
 					stream->write_function(stream, "l_hw=Y|");
 				}else {
 					stream->write_function(stream, "l_hw=N|");
 				}
 
-				if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) {
+				if(sngss7_test_ckt_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) {
 					stream->write_function(stream, "r_hw=Y|");
 				}else {
 					stream->write_function(stream, "r_hw=N|");
 				}
 
-				if(sngss7_test_flag(ss7_info, FLAG_CKT_LC_BLOCK_RX)) {
+				if(sngss7_test_ckt_flag(ss7_info, FLAG_CKT_LC_BLOCK_RX)) {
 					stream->write_function(stream, "l_mngmt=Y|");
 				}else {
 					stream->write_function(stream, "l_mngmt=N|");
 				}
 
-				if(sngss7_test_flag(ss7_info, FLAG_CKT_UCIC_BLOCK)) {
+				if(sngss7_test_ckt_flag(ss7_info, FLAG_CKT_UCIC_BLOCK)) {
 					stream->write_function(stream, "l_ucic=Y|");
 				}else {
 					stream->write_function(stream, "l_ucic=N|");
@@ -1026,7 +1096,7 @@ static ftdm_status_t handle_show_status(ftdm_stream_handle_t *stream, int span,
 	ftdm_signaling_status_t		sigstatus = FTDM_SIG_STATE_DOWN;
 	sng_isup_ckt_t				*ckt;
 
-	x=1;
+	x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
 	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
 			/* extract the circuit to make it easier to work with */
 			ckt = &g_ftdm_sngss7_data.cfg.isupCkt[x];
@@ -1071,43 +1141,37 @@ static ftdm_status_t handle_show_status(ftdm_stream_handle_t *stream, int span,
 													ftdm_signaling_status2str(sigstatus),
 													ftdm_channel_state2str(ftdmchan->state));
 	
-					if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX))) {
+					if((sngss7_test_ckt_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || (sngss7_test_ckt_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX))) {
 						stream->write_function(stream, "l_mn=Y|");
 					}else {
 						stream->write_function(stream, "l_mn=N|");
 					}
 	
-					if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) {
+					if((sngss7_test_ckt_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || (sngss7_test_ckt_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) {
 						stream->write_function(stream, "r_mn=Y|");
 					}else {
 						stream->write_function(stream, "r_mn=N|");
 					}
 	
-					if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) {
+					if(sngss7_test_ckt_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) {
 						stream->write_function(stream, "l_hw=Y|");
 					}else {
 						stream->write_function(stream, "l_hw=N|");
 					}
 	
-					if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) {
+					if(sngss7_test_ckt_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) {
 						stream->write_function(stream, "r_hw=Y|");
 					}else {
 						stream->write_function(stream, "r_hw=N|");
 					}
-	
-					if(sngss7_test_flag(ss7_info, FLAG_CKT_LC_BLOCK_RX)) {
-						stream->write_function(stream, "l_mngmt=Y|");
-					}else {
-						stream->write_function(stream, "l_mngmt=N|");
-					}
-	
-					if(sngss7_test_flag(ss7_info, FLAG_CKT_UCIC_BLOCK)) {
-						stream->write_function(stream, "l_ucic=Y|");
+
+					if(sngss7_test_ckt_flag(ss7_info, FLAG_RELAY_DOWN)) {
+						stream->write_function(stream, "relay=Y|");
 					}else {
-						stream->write_function(stream, "l_ucic=N|");
-					}				
+						stream->write_function(stream, "relay=N|");
+					}		
 	
-					stream->write_function(stream, "flags=0x%X",ss7_info->flags);
+					stream->write_function(stream, "flags=0x%X",ss7_info->ckt_flags);
 	
 					stream->write_function(stream, "\n");
 				} /* if ( hole, sig, voice) */
@@ -1127,7 +1191,7 @@ static ftdm_status_t handle_tx_blo(ftdm_stream_handle_t *stream, int span, int c
 	int				 lspan;
 	int				 lchan;
 
-	x=1;
+	x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
 	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
 		if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
 			ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
@@ -1162,7 +1226,7 @@ static ftdm_status_t handle_tx_blo(ftdm_stream_handle_t *stream, int span, int c
 					continue;
 				} else {
 					/* throw the ckt block flag */
-					sngss7_set_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX);
+					sngss7_set_ckt_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX);
 
 					/* set the channel to suspended state */
 					ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
@@ -1193,7 +1257,7 @@ static ftdm_status_t handle_tx_ubl(ftdm_stream_handle_t *stream, int span, int c
 	int				 lspan;
 	int				 lchan;
 
-	x=1;
+	x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
 	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
 		if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
 			ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
@@ -1228,10 +1292,10 @@ static ftdm_status_t handle_tx_ubl(ftdm_stream_handle_t *stream, int span, int c
 					continue;
 				} else {
 					/* throw the ckt block flag */
-					sngss7_set_flag(ss7_info, FLAG_CKT_MN_UNBLK_TX);
+					sngss7_set_ckt_flag(ss7_info, FLAG_CKT_MN_UNBLK_TX);
 
 					/* clear the block flag */
-					sngss7_clear_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX);
+					sngss7_clear_ckt_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX);
 
 					/* set the channel to suspended state */
 					ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
@@ -1254,18 +1318,18 @@ static ftdm_status_t handle_tx_ubl(ftdm_stream_handle_t *stream, int span, int c
 }
 
 /******************************************************************************/
-static ftdm_status_t handle_status_link(ftdm_stream_handle_t *stream, char *name)
+static ftdm_status_t handle_status_mtp3link(ftdm_stream_handle_t *stream, char *name)
 {
 	int 		x = 0;
 	SnMngmt		sta;
 	
 	/* find the link request by it's name */
 	x = 1;
-	while(g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) {
-		if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLink[x].name, name)) {
+	while(g_ftdm_sngss7_data.cfg.mtp3Link[x].id != 0) {
+		if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3Link[x].name, name)) {
 
 			/* send the status request */
-			if (ftmod_ss7_mtplink_sta(x, &sta)) {
+			if (ftmod_ss7_mtp3link_sta(x, &sta)) {
 				stream->write_function(stream, "Failed to read link=%s status\n", name);
 				return FTDM_FAIL;
 			}
@@ -1273,9 +1337,9 @@ static ftdm_status_t handle_status_link(ftdm_stream_handle_t *stream, char *name
 			/* print the results */
 			stream->write_function(stream, "%s|span=%d|chan=%d|sap=%d|state=%s|l_blk=%s|r_blk=%s|l_inhbt=%s|r_inhbt=%s\n",
 						name,
-						g_ftdm_sngss7_data.cfg.mtpLink[x].mtp1.span,
-						g_ftdm_sngss7_data.cfg.mtpLink[x].mtp1.chan,
-						g_ftdm_sngss7_data.cfg.mtpLink[x].id,
+						g_ftdm_sngss7_data.cfg.mtp1Link[x].span,
+						g_ftdm_sngss7_data.cfg.mtp1Link[x].chan,
+						g_ftdm_sngss7_data.cfg.mtp3Link[x].id,
 						DECODE_LSN_LINK_STATUS(sta.t.ssta.s.snDLSAP.state),
 						(sta.t.ssta.s.snDLSAP.locBlkd) ? "Y":"N",
 						(sta.t.ssta.s.snDLSAP.remBlkd) ? "Y":"N",
@@ -1296,6 +1360,50 @@ success:
 }
 
 /******************************************************************************/
+static ftdm_status_t handle_status_mtp2link(ftdm_stream_handle_t *stream, char *name)
+{
+	int 		x = 0;
+	SdMngmt		sta;
+	
+	/* find the link request by it's name */
+	x = 1;
+	while(g_ftdm_sngss7_data.cfg.mtp2Link[x].id != 0) {
+		if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp2Link[x].name, name)) {
+
+			/* send the status request */
+			if (ftmod_ss7_mtp2link_sta(x, &sta)) {
+				stream->write_function(stream, "Failed to read link=%s status\n", name);
+				return FTDM_FAIL;
+			}
+
+			/* print the results */
+			stream->write_function(stream, "%s|span=%d|chan=%d|sap=%d|state=%s|outsFrm=%d|drpdFrm=%d|lclStatus=%s|rmtStatus=%s|fsn=%d|bsn=%d\n",
+						name,
+						g_ftdm_sngss7_data.cfg.mtp1Link[x].span,
+						g_ftdm_sngss7_data.cfg.mtp1Link[x].chan,
+						g_ftdm_sngss7_data.cfg.mtp2Link[x].id,
+						DECODE_LSD_LINK_STATUS(sta.t.ssta.s.sdDLSAP.hlSt),
+						sta.t.ssta.s.sdDLSAP.psOutsFrm,
+						sta.t.ssta.s.sdDLSAP.cntMaDrop,
+						(sta.t.ssta.s.sdDLSAP.lclBsy) ? "Y":"N",
+						(sta.t.ssta.s.sdDLSAP.remBsy) ? "Y":"N",
+						sta.t.ssta.s.sdDLSAP.fsn,
+						sta.t.ssta.s.sdDLSAP.bsn);
+
+			goto success;
+		}
+		
+		/* move to the next link */
+		x++;
+	} /* while (id != 0) */
+
+	stream->write_function(stream, "Failed to find link=\"%s\"\n", name);
+
+success:
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
 static ftdm_status_t handle_status_linkset(ftdm_stream_handle_t *stream, char *name)
 {
 	int 		x = 0;
@@ -1338,17 +1446,17 @@ static ftdm_status_t handle_set_inhibit(ftdm_stream_handle_t *stream, char *name
 
 	/* find the link request by it's name */
 	x = 1;
-	while(g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) {
-		if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLink[x].name, name)) {
+	while(g_ftdm_sngss7_data.cfg.mtp3Link[x].id != 0) {
+		if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3Link[x].name, name)) {
 
 			/* send the inhibit request */
-			if (ftmod_ss7_inhibit_mtplink(x)) {
+			if (ftmod_ss7_inhibit_mtp3link(x)) {
 				stream->write_function(stream, "Failed to inhibit link=%s\n", name);
 				return FTDM_FAIL;
 			}
 
 			/* print the new status of the link */
-			handle_status_link(stream, &name[0]);
+			handle_status_mtp3link(stream, &name[0]);
 
 			goto success;
 		}
@@ -1370,17 +1478,17 @@ static ftdm_status_t handle_set_uninhibit(ftdm_stream_handle_t *stream, char *na
 
 	/* find the link request by it's name */
 	x = 1;
-	while(g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) {
-		if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLink[x].name, name)) {
+	while(g_ftdm_sngss7_data.cfg.mtp3Link[x].id != 0) {
+		if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3Link[x].name, name)) {
 
 			/* send the uninhibit request */
-			if (ftmod_ss7_uninhibit_mtplink(x)) {
+			if (ftmod_ss7_uninhibit_mtp3link(x)) {
 				stream->write_function(stream, "Failed to uninhibit link=%s\n", name);
 				return FTDM_FAIL;
 			}
 
 			/* print the new status of the link */
-			handle_status_link(stream, &name[0]);
+			handle_status_mtp3link(stream, &name[0]);
 
 			goto success;
 		}
@@ -1404,7 +1512,7 @@ static ftdm_status_t handle_tx_rsc(ftdm_stream_handle_t *stream, int span, int c
 	int				 	lspan;
 	int				 	lchan;
 
-	x=1;
+	x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
 	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
 		if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
 			sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
@@ -1429,7 +1537,7 @@ static ftdm_status_t handle_tx_rsc(ftdm_stream_handle_t *stream, int span, int c
 				ftdm_mutex_lock(ftdmchan->mutex);
 
 				/* throw the reset flag */
-				sngss7_set_flag(sngss7_info, FLAG_RESET_TX);
+				sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX);
 
 				switch (ftdmchan->state) {
 				/**************************************************************************/
@@ -1476,7 +1584,7 @@ static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int c
 		return FTDM_SUCCESS;
 	}
 
-	x=1;
+	x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
 	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
 		if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
 
@@ -1500,9 +1608,9 @@ static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int c
 					continue;
 				} else {
 					/* throw the grp reset flag */
-					sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX);
+					sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX);
 					if (ftdmchan->physical_chan_id == chan) {
-						sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_BASE);
+						sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_BASE);
 						sngss7_span->tx_grs.circuit = sngss7_info->circuit->id;
 						sngss7_span->tx_grs.range = range-1;
 					}
@@ -1523,7 +1631,7 @@ static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int c
 		x++;
 	} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
 	
-	x=1;
+	x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
 	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
 		if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
 
@@ -1565,7 +1673,7 @@ static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int c
 		return FTDM_SUCCESS;
 	}
 
-	x=1;
+	x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
 	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
 		if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
 
@@ -1582,7 +1690,7 @@ static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int c
 				ftdm_mutex_lock(ftdmchan->mutex);
 
 				/* throw the grp maint. block flag */
-				sngss7_set_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX);
+				sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX);
 
 				/* bring the sig status down */
 				sigev.chan_id = ftdmchan->chan_id;
@@ -1622,7 +1730,7 @@ static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int c
 	/* send the circuit group block */
 	ft_to_sngss7_cgb(main_chan);
 
-	x=1;
+	x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
 	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
 		if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
 
@@ -1665,7 +1773,7 @@ static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int c
 		return FTDM_SUCCESS;
 	}
 
-	x=1;
+	x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
 	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
 		if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
 
@@ -1682,7 +1790,7 @@ static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int c
 				ftdm_mutex_lock(ftdmchan->mutex);
 
 				/* throw the grp maint. block flag */
-				sngss7_clear_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX);
+				sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX);
 
 				/* bring the sig status up */
 				sigev.chan_id = ftdmchan->chan_id;
@@ -1722,7 +1830,7 @@ static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int c
 	/* send the circuit group block */
 	ft_to_sngss7_cgu(main_chan);
 
-	x=1;
+	x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
 	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
 		if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
 
@@ -1746,23 +1854,85 @@ static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int c
 }
 
 /******************************************************************************/
+static ftdm_status_t handle_bind_link(ftdm_stream_handle_t *stream, char *name)
+{
+	int		x = 0;
+
+	/* find the link request by it's name */
+	x = 1;
+	while(g_ftdm_sngss7_data.cfg.mtp3Link[x].id != 0) {
+		if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3Link[x].name, name)) {
+
+			/* send the uninhibit request */
+			if (ftmod_ss7_bind_mtp3link(g_ftdm_sngss7_data.cfg.mtp3Link[x].mtp2Id)) {
+				stream->write_function(stream, "Failed to bind link=%s\n", name);
+				return FTDM_FAIL;
+			}
+
+			/* print the new status of the link */
+			handle_status_mtp3link(stream, &name[0]);
+			goto success;
+		}
+ 
+		/* move to the next link */
+		x++;
+	} /* while (id != 0) */
+
+	stream->write_function(stream, "Could not find link=%s\n", name);
+
+success:
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+static ftdm_status_t handle_unbind_link(ftdm_stream_handle_t *stream, char *name)
+{
+	int		x = 0;
+
+	/* find the link request by it's name */
+	x = 1;
+	while(g_ftdm_sngss7_data.cfg.mtp3Link[x].id != 0) {
+		if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3Link[x].name, name)) {
+
+			/* send the uninhibit request */
+			if (ftmod_ss7_unbind_mtp3link(g_ftdm_sngss7_data.cfg.mtp3Link[x].mtp2Id)) {
+				stream->write_function(stream, "Failed to bind link=%s\n", name);
+				return FTDM_FAIL;
+			}
+
+			/* print the new status of the link */
+			handle_status_mtp3link(stream, &name[0]);
+			goto success;
+		}
+ 
+		/* move to the next link */
+		x++;
+	} /* while (id != 0) */
+
+	stream->write_function(stream, "Could not find link=%s\n", name);
+
+success:
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
 static ftdm_status_t handle_activate_link(ftdm_stream_handle_t *stream, char *name)
 {
 	int		x = 0;
 
 	/* find the link request by it's name */
 	x = 1;
-	while(g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) {
-		if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLink[x].name, name)) {
+	while(g_ftdm_sngss7_data.cfg.mtp3Link[x].id != 0) {
+		if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3Link[x].name, name)) {
 
 			/* send the uninhibit request */
-			if (ftmod_ss7_activate_mtplink(x)) {
+			if (ftmod_ss7_activate_mtp3link(x)) {
 				stream->write_function(stream, "Failed to activate link=%s\n", name);
 				return FTDM_FAIL;
 			}
 
 			/* print the new status of the link */
-			handle_status_link(stream, &name[0]);
+			handle_status_mtp3link(stream, &name[0]);
 			goto success;
 		}
  
@@ -1783,17 +1953,17 @@ static ftdm_status_t handle_deactivate_link(ftdm_stream_handle_t *stream, char *
 
 	/* find the link request by it's name */
 	x = 1;
-	while(g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) {
-		if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLink[x].name, name)) {
+	while(g_ftdm_sngss7_data.cfg.mtp3Link[x].id != 0) {
+		if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3Link[x].name, name)) {
 
 			/* send the deactivate request */
-			if (ftmod_ss7_deactivate2_mtplink(x)) {
+			if (ftmod_ss7_deactivate2_mtp3link(x)) {
 				stream->write_function(stream, "Failed to deactivate link=%s\n", name);
 				return FTDM_FAIL;
 			}
 
 			/* print the new status of the link */
-			handle_status_link(stream, &name[0]);
+			handle_status_mtp3link(stream, &name[0]);
 			goto success;
 		}
  
@@ -1877,17 +2047,17 @@ static ftdm_status_t handle_tx_lpo(ftdm_stream_handle_t *stream, char *name)
 
 	/* find the link request by it's name */
 	x = 1;
-	while(g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) {
-		if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLink[x].name, name)) {
+	while(g_ftdm_sngss7_data.cfg.mtp3Link[x].id != 0) {
+		if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3Link[x].name, name)) {
 
 			/* send the uninhibit request */
-			if (ftmod_ss7_lpo_mtplink(x)) {
+			if (ftmod_ss7_lpo_mtp3link(x)) {
 				stream->write_function(stream, "Failed set LPO link=%s\n", name);
 				return FTDM_FAIL;
 			}
 
 			/* print the new status of the link */
-			handle_status_link(stream, &name[0]);
+			handle_status_mtp3link(stream, &name[0]);
 			goto success;
 		}
  
@@ -1908,17 +2078,17 @@ static ftdm_status_t handle_tx_lpr(ftdm_stream_handle_t *stream, char *name)
 
 	/* find the link request by it's name */
 	x = 1;
-	while(g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) {
-		if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLink[x].name, name)) {
+	while(g_ftdm_sngss7_data.cfg.mtp3Link[x].id != 0) {
+		if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3Link[x].name, name)) {
 
 			/* send the uninhibit request */
-			if (ftmod_ss7_lpr_mtplink(x)) {
+			if (ftmod_ss7_lpr_mtp3link(x)) {
 				stream->write_function(stream, "Failed set LPR link=%s\n", name);
 				return FTDM_FAIL;
 			}
 
 			/* print the new status of the link */
-			handle_status_link(stream, &name[0]);
+			handle_status_mtp3link(stream, &name[0]);
 			goto success;
 		}
  
@@ -1933,6 +2103,47 @@ success:
 }
 
 /******************************************************************************/
+static ftdm_status_t handle_status_relay(ftdm_stream_handle_t *stream, char *name)
+{
+	RyMngmt	sta;
+	int		x = 0;
+
+	memset(&sta, 0x0, sizeof(sta));
+
+
+	/* find the channel request by it's name */
+	x = 1;
+	while(g_ftdm_sngss7_data.cfg.relay[x].id != 0) {
+		if (!strcasecmp(g_ftdm_sngss7_data.cfg.relay[x].name, name)) {
+
+			if (ftmod_ss7_relay_status(g_ftdm_sngss7_data.cfg.relay[x].id, &sta)) {
+				stream->write_function(stream, "Failed to read relay =%s status\n", name);
+				return FTDM_FAIL;
+			}
+
+			/* print the results */
+			stream->write_function(stream, "%s|sap=%d|type=%d|port=%d|hostname=%s|procId=%d|status=%s\n",
+						name,
+						g_ftdm_sngss7_data.cfg.relay[x].id,	
+						g_ftdm_sngss7_data.cfg.relay[x].type,
+						g_ftdm_sngss7_data.cfg.relay[x].port,
+						g_ftdm_sngss7_data.cfg.relay[x].hostname,
+						g_ftdm_sngss7_data.cfg.relay[x].procId,
+						DECODE_LRY_CHAN_STATUS(sta.t.ssta.rySta.cStatus));
+
+			goto success;
+		}
+		
+		/* move to the next link */
+		x++;
+
+	} /* g_ftdm_sngss7_data.cfg.relay[x].id */
+
+success:
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
 static ftdm_status_t extract_span_chan(char *argv[10], int pos, int *span, int *chan)
 {
 
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c
index 87733dd..c1b18e5 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c
@@ -48,19 +48,31 @@ static int ftmod_ss7_enable_isap(int suId);
 static int ftmod_ss7_enable_nsap(int suId);
 static int ftmod_ss7_enable_mtpLinkSet(int lnkSetId);
 
-int ftmod_ss7_inhibit_mtplink(uint32_t id);
-int ftmod_ss7_uninhibit_mtplink(uint32_t id);
+int ftmod_ss7_inhibit_mtp3link(uint32_t id);
+int ftmod_ss7_uninhibit_mtp3link(uint32_t id);
 
-int ftmod_ss7_activate_mtplink(uint32_t id);
-int ftmod_ss7_deactivate_mtplink(uint32_t id);
-int ftmod_ss7_deactivate2_mtplink(uint32_t id);
+int ftmod_ss7_bind_mtp3link(uint32_t id);
+int ftmod_ss7_unbind_mtp3link(uint32_t id);
+int ftmod_ss7_activate_mtp3link(uint32_t id);
+int ftmod_ss7_deactivate_mtp3link(uint32_t id);
+int ftmod_ss7_deactivate2_mtp3link(uint32_t id);
 
 int ftmod_ss7_activate_mtplinkSet(uint32_t id);
 int ftmod_ss7_deactivate_mtplinkSet(uint32_t id);
 int ftmod_ss7_deactivate2_mtplinkSet(uint32_t id);
 
-int ftmod_ss7_lpo_mtplink(uint32_t id);
-int ftmod_ss7_lpr_mtplink(uint32_t id);
+int ftmod_ss7_lpo_mtp3link(uint32_t id);
+int ftmod_ss7_lpr_mtp3link(uint32_t id);
+
+int ftmod_ss7_shutdown_isup(void);
+int ftmod_ss7_shutdown_mtp3(void);
+int ftmod_ss7_shutdown_mtp2(void);
+int ftmod_ss7_shutdown_relay(void);
+
+int ftmod_ss7_disable_grp_mtp3Link(uint32_t procId);
+int ftmod_ss7_enable_grp_mtp3Link(uint32_t procId);
+
+int ftmod_ss7_disable_grp_mtp2Link(uint32_t procId);
 /******************************************************************************/
 
 /* FUNCTIONS ******************************************************************/
@@ -71,7 +83,7 @@ int ft_to_sngss7_activate_all(void)
 	x = 1;
 	while (g_ftdm_sngss7_data.cfg.isap[x].id != 0) {
 		/* check if this link has already been actived */
-		if (!(g_ftdm_sngss7_data.cfg.isap[x].flags & ACTIVE)) {
+		if (!(g_ftdm_sngss7_data.cfg.isap[x].flags & SNGSS7_ACTIVE)) {
 
 			if (ftmod_ss7_enable_isap(x)) {	
 				SS7_CRITICAL("ISAP %d Enable: NOT OK\n", x);
@@ -80,9 +92,9 @@ int ft_to_sngss7_activate_all(void)
 				SS7_INFO("ISAP %d Enable: OK\n", x);
 			}
 
-			/* set the ACTIVE flag */
-			g_ftdm_sngss7_data.cfg.isap[x].flags |= ACTIVE;
-		} /* if !ACTIVE */
+			/* set the SNGSS7_ACTIVE flag */
+			g_ftdm_sngss7_data.cfg.isap[x].flags |= SNGSS7_ACTIVE;
+		} /* if !SNGSS7_ACTIVE */
 		
 		x++;
 	} /* while (g_ftdm_sngss7_data.cfg.isap[x].id != 0) */
@@ -90,7 +102,7 @@ int ft_to_sngss7_activate_all(void)
 	x = 1;
 	while (g_ftdm_sngss7_data.cfg.nsap[x].id != 0) {
 		/* check if this link has already been actived */
-		if (!(g_ftdm_sngss7_data.cfg.nsap[x].flags & ACTIVE)) {
+		if (!(g_ftdm_sngss7_data.cfg.nsap[x].flags & SNGSS7_ACTIVE)) {
 
 			if (ftmod_ss7_enable_nsap(x)) {	
 				SS7_CRITICAL("NSAP %d Enable: NOT OK\n", x);
@@ -99,31 +111,33 @@ int ft_to_sngss7_activate_all(void)
 				SS7_INFO("NSAP %d Enable: OK\n", x);
 			}
 
-			/* set the ACTIVE flag */
-			g_ftdm_sngss7_data.cfg.nsap[x].flags |= ACTIVE;
-		} /* if !ACTIVE */
+			/* set the SNGSS7_ACTIVE flag */
+			g_ftdm_sngss7_data.cfg.nsap[x].flags |= SNGSS7_ACTIVE;
+		} /* if !SNGSS7_ACTIVE */
 		
 		x++;
 	} /* while (g_ftdm_sngss7_data.cfg.nsap[x].id != 0) */
 
-	x = 1;
-	while (g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) {
-		/* check if this link has already been actived */
-		if (!(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags & ACTIVE)) {
-
-			if (ftmod_ss7_enable_mtpLinkSet(x)) {	
-				SS7_CRITICAL("LinkSet \"%s\" Enable: NOT OK\n", g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name);
-				return 1;
-			} else {
-				SS7_INFO("LinkSet \"%s\" Enable: OK\n", g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name);
-			}
-
-			/* set the ACTIVE flag */
-			g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags |= ACTIVE;
-		} /* if !ACTIVE */
-		
-		x++;
-	} /* while (g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) */
+	if (g_ftdm_sngss7_data.cfg.mtpRoute[1].id != 0) {
+		x = 1;
+		while (g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) {
+			/* check if this link has already been actived */
+			if (!(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags & SNGSS7_ACTIVE)) {
+	
+				if (ftmod_ss7_enable_mtpLinkSet(x)) {	
+					SS7_CRITICAL("LinkSet \"%s\" Enable: NOT OK\n", g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name);
+					return 1;
+				} else {
+					SS7_INFO("LinkSet \"%s\" Enable: OK\n", g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name);
+				}
+	
+				/* set the SNGSS7_ACTIVE flag */
+				g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags |= SNGSS7_ACTIVE;
+			} /* if !SNGSS7_ACTIVE */
+			
+			x++;
+		} /* while (g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) */
+	}
 
 	return 0;
 }
@@ -223,7 +237,7 @@ static int ftmod_ss7_enable_mtpLinkSet(int lnkSetId)
 }
 
 /******************************************************************************/
-int ftmod_ss7_inhibit_mtplink(uint32_t id)
+int ftmod_ss7_inhibit_mtp3link(uint32_t id)
 {
 	SnMngmt cntrl;
 	Pst pst;
@@ -253,7 +267,7 @@ int ftmod_ss7_inhibit_mtplink(uint32_t id)
 }
 
 /******************************************************************************/
-int ftmod_ss7_uninhibit_mtplink(uint32_t id)
+int ftmod_ss7_uninhibit_mtp3link(uint32_t id)
 {
 	SnMngmt cntrl;
 	Pst pst;
@@ -283,7 +297,67 @@ int ftmod_ss7_uninhibit_mtplink(uint32_t id)
 }
 
 /******************************************************************************/
-int ftmod_ss7_activate_mtplink(uint32_t id)
+int ftmod_ss7_bind_mtp3link(uint32_t id)
+{
+	SnMngmt cntrl;
+	Pst pst;
+
+	/* initalize the post structure */
+	smPstInit(&pst);
+
+	/* insert the destination Entity */
+	pst.dstEnt = ENTSN;
+
+	/* initalize the control structure */
+	memset(&cntrl, 0x0, sizeof(SnMngmt));
+
+	/* initalize the control header */
+	smHdrInit(&cntrl.hdr);
+
+	cntrl.hdr.msgType			= TCNTRL;	/* this is a control request */
+	cntrl.hdr.entId.ent			= ENTSN;
+	cntrl.hdr.entId.inst		= S_INST;
+	cntrl.hdr.elmId.elmnt		= STDLSAP;
+	cntrl.hdr.elmId.elmntInst1	= g_ftdm_sngss7_data.cfg.mtp3Link[id].id;
+
+	cntrl.t.cntrl.action		= ABND;		/* Activate */
+	cntrl.t.cntrl.subAction		= SAELMNT;	/* specificed element */
+
+	return (sng_cntrl_mtp3(&pst, &cntrl));
+}
+
+/******************************************************************************/
+int ftmod_ss7_unbind_mtp3link(uint32_t id)
+{
+	SnMngmt cntrl;
+	Pst pst;
+
+	/* initalize the post structure */
+	smPstInit(&pst);
+
+	/* insert the destination Entity */
+	pst.dstEnt = ENTSN;
+
+	/* initalize the control structure */
+	memset(&cntrl, 0x0, sizeof(SnMngmt));
+
+	/* initalize the control header */
+	smHdrInit(&cntrl.hdr);
+
+	cntrl.hdr.msgType			= TCNTRL;	/* this is a control request */
+	cntrl.hdr.entId.ent			= ENTSN;
+	cntrl.hdr.entId.inst		= S_INST;
+	cntrl.hdr.elmId.elmnt		= STDLSAP;
+	cntrl.hdr.elmId.elmntInst1	= g_ftdm_sngss7_data.cfg.mtp3Link[id].id;
+
+	cntrl.t.cntrl.action		= AUBND_DIS;		/* unbind and disable */
+	cntrl.t.cntrl.subAction		= SAELMNT;			/* specificed element */
+
+	return (sng_cntrl_mtp3(&pst, &cntrl));
+}
+
+/******************************************************************************/
+int ftmod_ss7_activate_mtp3link(uint32_t id)
 {
 	SnMngmt cntrl;
 	Pst pst;
@@ -304,7 +378,7 @@ int ftmod_ss7_activate_mtplink(uint32_t id)
 	cntrl.hdr.entId.ent			= ENTSN;
 	cntrl.hdr.entId.inst		= S_INST;
 	cntrl.hdr.elmId.elmnt		= STDLSAP;
-	cntrl.hdr.elmId.elmntInst1	= g_ftdm_sngss7_data.cfg.mtpLink[id].id;
+	cntrl.hdr.elmId.elmntInst1	= g_ftdm_sngss7_data.cfg.mtp3Link[id].id;
 
 	cntrl.t.cntrl.action		= AENA;		/* Activate */
 	cntrl.t.cntrl.subAction		= SAELMNT;	/* specificed element */
@@ -313,7 +387,7 @@ int ftmod_ss7_activate_mtplink(uint32_t id)
 }
 
 /******************************************************************************/
-int ftmod_ss7_deactivate_mtplink(uint32_t id)
+int ftmod_ss7_deactivate_mtp3link(uint32_t id)
 {
 	SnMngmt cntrl;
 	Pst pst;
@@ -334,7 +408,7 @@ int ftmod_ss7_deactivate_mtplink(uint32_t id)
 	cntrl.hdr.entId.ent			= ENTSN;
 	cntrl.hdr.entId.inst		= S_INST;
 	cntrl.hdr.elmId.elmnt		= STDLSAP;
-	cntrl.hdr.elmId.elmntInst1	= g_ftdm_sngss7_data.cfg.mtpLink[id].id;
+	cntrl.hdr.elmId.elmntInst1	= g_ftdm_sngss7_data.cfg.mtp3Link[id].id;
 
 	cntrl.t.cntrl.action		= ADISIMM;	/* Deactivate */
 	cntrl.t.cntrl.subAction		= SAELMNT;	/* specificed element */
@@ -343,7 +417,7 @@ int ftmod_ss7_deactivate_mtplink(uint32_t id)
 }
 
 /******************************************************************************/
-int ftmod_ss7_deactivate2_mtplink(uint32_t id)
+int ftmod_ss7_deactivate2_mtp3link(uint32_t id)
 {
 	SnMngmt cntrl;
 	Pst pst;
@@ -364,7 +438,7 @@ int ftmod_ss7_deactivate2_mtplink(uint32_t id)
 	cntrl.hdr.entId.ent			= ENTSN;
 	cntrl.hdr.entId.inst		= S_INST;
 	cntrl.hdr.elmId.elmnt		= STDLSAP;
-	cntrl.hdr.elmId.elmntInst1	= g_ftdm_sngss7_data.cfg.mtpLink[id].id;
+	cntrl.hdr.elmId.elmntInst1	= g_ftdm_sngss7_data.cfg.mtp3Link[id].id;
 
 	cntrl.t.cntrl.action		= ADISIMM_L2;	/* Deactivate...layer 2 only */
 	cntrl.t.cntrl.subAction		= SAELMNT;		/* specificed element */
@@ -463,7 +537,7 @@ int ftmod_ss7_deactivate2_mtplinkSet(uint32_t id)
 }
 
 /******************************************************************************/
-int ftmod_ss7_lpo_mtplink(uint32_t id)
+int ftmod_ss7_lpo_mtp3link(uint32_t id)
 {
 	SnMngmt cntrl;
 	Pst pst;
@@ -484,7 +558,7 @@ int ftmod_ss7_lpo_mtplink(uint32_t id)
 	cntrl.hdr.entId.ent			= ENTSN;
 	cntrl.hdr.entId.inst		= S_INST;
 	cntrl.hdr.elmId.elmnt		= STDLSAP;
-	cntrl.hdr.elmId.elmntInst1	= g_ftdm_sngss7_data.cfg.mtpLink[id].id;
+	cntrl.hdr.elmId.elmntInst1	= g_ftdm_sngss7_data.cfg.mtp3Link[id].id;
 
 	cntrl.t.cntrl.action		= ACTION_LPO;	/* Activate */
 	cntrl.t.cntrl.subAction		= SAELMNT;			/* specificed element */
@@ -493,7 +567,7 @@ int ftmod_ss7_lpo_mtplink(uint32_t id)
 }
 
 /******************************************************************************/
-int ftmod_ss7_lpr_mtplink(uint32_t id)
+int ftmod_ss7_lpr_mtp3link(uint32_t id)
 {
 	SnMngmt cntrl;
 	Pst pst;
@@ -514,7 +588,7 @@ int ftmod_ss7_lpr_mtplink(uint32_t id)
 	cntrl.hdr.entId.ent			= ENTSN;
 	cntrl.hdr.entId.inst		= S_INST;
 	cntrl.hdr.elmId.elmnt		= STDLSAP;
-	cntrl.hdr.elmId.elmntInst1	= g_ftdm_sngss7_data.cfg.mtpLink[id].id;
+	cntrl.hdr.elmId.elmntInst1	= g_ftdm_sngss7_data.cfg.mtp3Link[id].id;
 
 	cntrl.t.cntrl.action		= ACTION_LPR;	/* Activate */
 	cntrl.t.cntrl.subAction		= SAELMNT;			/* specificed element */
@@ -523,6 +597,216 @@ int ftmod_ss7_lpr_mtplink(uint32_t id)
 }
 
 /******************************************************************************/
+int ftmod_ss7_shutdown_isup(void)
+{
+	SiMngmt cntrl;
+	Pst pst;
+
+	/* initalize the post structure */
+	smPstInit(&pst);
+
+	/* insert the destination Entity */
+	pst.dstEnt = ENTSI;
+
+	/* initalize the control structure */
+	memset(&cntrl, 0x0, sizeof(SiMngmt));
+
+	/* initalize the control header */
+	smHdrInit(&cntrl.hdr);
+
+	cntrl.hdr.msgType			= TCNTRL;	   /* this is a control request */
+	cntrl.hdr.entId.ent			= ENTSI;
+	cntrl.hdr.entId.inst		= S_INST;
+	cntrl.hdr.elmId.elmnt		= STGEN;
+
+	cntrl.t.cntrl.action		= ASHUTDOWN;	/* shutdown */
+	cntrl.t.cntrl.subAction		= SAELMNT;		/* specificed element */
+
+	return (sng_cntrl_isup(&pst, &cntrl));
+}
+
+/******************************************************************************/
+int ftmod_ss7_shutdown_mtp3(void)
+{
+	SnMngmt cntrl;
+	Pst pst;
+
+	/* initalize the post structure */
+	smPstInit(&pst);
+
+	/* insert the destination Entity */
+	pst.dstEnt = ENTSN;
+
+	/* initalize the control structure */
+	memset(&cntrl, 0x0, sizeof(SnMngmt));
+
+	/* initalize the control header */
+	smHdrInit(&cntrl.hdr);
+
+	cntrl.hdr.msgType			= TCNTRL;	/* this is a control request */
+	cntrl.hdr.entId.ent			= ENTSN;
+	cntrl.hdr.entId.inst		= S_INST;
+	cntrl.hdr.elmId.elmnt		= STGEN;
+
+	cntrl.t.cntrl.action		= ASHUTDOWN;	/* Activate */
+	cntrl.t.cntrl.subAction		= SAELMNT;			/* specificed element */
+
+	return (sng_cntrl_mtp3(&pst, &cntrl));
+}
+
+/******************************************************************************/
+int ftmod_ss7_shutdown_mtp2(void)
+{
+	SdMngmt cntrl;
+	Pst pst;
+
+	/* initalize the post structure */
+	smPstInit(&pst);
+
+	/* insert the destination Entity */
+	pst.dstEnt = ENTSD;
+
+	/* initalize the control structure */
+	memset(&cntrl, 0x0, sizeof(SdMngmt));
+
+	/* initalize the control header */
+	smHdrInit(&cntrl.hdr);
+
+	cntrl.hdr.msgType			= TCNTRL;	/* this is a control request */
+	cntrl.hdr.entId.ent			= ENTSD;
+	cntrl.hdr.entId.inst		= S_INST;
+	cntrl.hdr.elmId.elmnt		= STGEN;
+
+	cntrl.t.cntrl.action		= ASHUTDOWN;	/* Activate */
+	cntrl.t.cntrl.subAction		= SAELMNT;			/* specificed element */
+
+	return (sng_cntrl_mtp2(&pst, &cntrl));
+}
+
+/******************************************************************************/
+int ftmod_ss7_shutdown_relay(void)
+{
+	RyMngmt cntrl;
+	Pst pst;
+
+	/* initalize the post structure */
+	smPstInit(&pst);
+
+	/* insert the destination Entity */
+	pst.dstEnt = ENTRY;
+
+	/* initalize the control structure */
+	memset(&cntrl, 0x0, sizeof(RyMngmt));
+
+	/* initalize the control header */
+	smHdrInit(&cntrl.hdr);
+
+	cntrl.hdr.msgType			= TCNTRL;	/* this is a control request */
+	cntrl.hdr.entId.ent			= ENTRY;
+	cntrl.hdr.entId.inst		= S_INST;
+	cntrl.hdr.elmId.elmnt		= STGEN;
+
+	cntrl.t.cntrl.action		= ASHUTDOWN;	/* Activate */
+	cntrl.t.cntrl.subAction		= SAELMNT;			/* specificed element */
+
+	return (sng_cntrl_relay(&pst, &cntrl));
+}
+
+/******************************************************************************/
+int ftmod_ss7_disable_grp_mtp3Link(uint32_t procId)
+{
+	SnMngmt cntrl;
+	Pst pst;
+
+	/* initalize the post structure */
+	smPstInit(&pst);
+
+	/* insert the destination Entity */
+	pst.dstEnt = ENTSN;
+
+	/* initalize the control structure */
+	memset(&cntrl, 0x0, sizeof(SnMngmt));
+
+	/* initalize the control header */
+	smHdrInit(&cntrl.hdr);
+
+	cntrl.hdr.msgType			= TCNTRL;			/* this is a control request */
+	cntrl.hdr.entId.ent			= ENTSN;
+	cntrl.hdr.entId.inst		= S_INST;
+	cntrl.hdr.elmId.elmnt		= STGRDLSAP;		/* group DLSAP */
+
+	cntrl.t.cntrl.ctlType.groupKey.dstProcId = procId;	/* all SAPS to this ProcId */
+
+	cntrl.t.cntrl.action		= AUBND_DIS;		/* disable and unbind */
+	cntrl.t.cntrl.subAction		= SAGR_DSTPROCID;			/* specificed element */
+
+	return (sng_cntrl_mtp3(&pst, &cntrl));
+
+}
+
+/******************************************************************************/
+int ftmod_ss7_enable_grp_mtp3Link(uint32_t procId)
+{
+	SnMngmt cntrl;
+	Pst pst;
+
+	/* initalize the post structure */
+	smPstInit(&pst);
+
+	/* insert the destination Entity */
+	pst.dstEnt = ENTSN;
+
+	/* initalize the control structure */
+	memset(&cntrl, 0x0, sizeof(SnMngmt));
+
+	/* initalize the control header */
+	smHdrInit(&cntrl.hdr);
+
+	cntrl.hdr.msgType			= TCNTRL;			/* this is a control request */
+	cntrl.hdr.entId.ent			= ENTSN;
+	cntrl.hdr.entId.inst		= S_INST;
+	cntrl.hdr.elmId.elmnt		= STGRDLSAP;		/* group DLSAP */
+
+	cntrl.t.cntrl.ctlType.groupKey.dstProcId = procId;	/* all SAPS to this ProcId */
+
+	cntrl.t.cntrl.action		= ABND_ENA;			/* bind and enable */
+	cntrl.t.cntrl.subAction		= SAGR_DSTPROCID;			/* specificed element */
+
+	return (sng_cntrl_mtp3(&pst, &cntrl));
+
+}
+
+/******************************************************************************/
+int ftmod_ss7_disable_grp_mtp2Link(uint32_t procId)
+{
+	SdMngmt cntrl;
+	Pst pst;
+
+	/* initalize the post structure */
+	smPstInit(&pst);
+
+	/* insert the destination Entity */
+	pst.dstEnt = ENTSD;
+
+	/* initalize the control structure */
+	memset(&cntrl, 0x0, sizeof(cntrl));
+
+	/* initalize the control header */
+	smHdrInit(&cntrl.hdr);
+
+	cntrl.hdr.msgType			= TCNTRL;			/* this is a control request */
+	cntrl.hdr.entId.ent			= ENTSD;
+	cntrl.hdr.entId.inst		= S_INST;
+	cntrl.hdr.elmId.elmnt		= STGRNSAP;			/* group NSAP */
+
+	cntrl.t.cntrl.par.dstProcId = procId;			/* all SAPS to this ProcId */
+
+	cntrl.t.cntrl.action		= AUBND_DIS;		/* disable and unbind */
+	cntrl.t.cntrl.subAction		= SAGR_DSTPROCID;			/* specificed element */
+
+	return (sng_cntrl_mtp2(&pst, &cntrl));
+
+}
 
 /******************************************************************************/
 /* For Emacs:
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c
index dcfb7f7..3a6fca7 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c
@@ -99,21 +99,21 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
 	/* lock the channel */
 	ftdm_mutex_lock(ftdmchan->mutex);
 
-	if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) {
+	if (sngss7_test_ckt_flag(sngss7_info, FLAG_GLARE)) {
 		SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx IAM (glare)\n", sngss7_info->circuit->cic);
 	} else {
 		SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx IAM\n", sngss7_info->circuit->cic);
 	}
 
 	/* check if the circuit has a remote block */
-	if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) ||
-		(sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) ||
-		(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) {
+	if ((sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) ||
+		(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) ||
+		(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) {
 
 		/* as per Q.764, 2.8.2.3 xiv ... remove the block from this channel */
-		sngss7_clear_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX);
-		sngss7_clear_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX);
-		sngss7_clear_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX);
+		sngss7_clear_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX);
+		sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX);
+		sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX);
 
 		/* KONRAD FIX ME : check in case there is a ckt and grp block */
 	}
@@ -134,7 +134,7 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
 						ftdmchan->physical_chan_id);
 
 			 /* set the flag to indicate this hangup is started from the local side */
-			sngss7_set_flag(sngss7_info, FLAG_LOCAL_REL);
+			sngss7_set_ckt_flag(sngss7_info, FLAG_LOCAL_REL);
 
 			ftdmchan->caller_data.hangup_cause = 41;
 
@@ -253,26 +253,26 @@ handle_glare:
 		sngss7_info->glare.circuit = circuit;
 		memcpy(&sngss7_info->glare.iam, siConEvnt, sizeof(*siConEvnt));
 
-		if (!(sngss7_test_flag(sngss7_info, FLAG_GLARE))) {
+		if (!(sngss7_test_ckt_flag(sngss7_info, FLAG_GLARE))) {
 			/* glare, throw the flag */
-			sngss7_set_flag(sngss7_info, FLAG_GLARE);
+			sngss7_set_ckt_flag(sngss7_info, FLAG_GLARE);
 		
 			/* setup the hangup cause */
 			ftdmchan->caller_data.hangup_cause = 34;	/* Circuit Congrestion */
 		
 			/* this is a remote hangup request */
-			sngss7_set_flag(sngss7_info, FLAG_REMOTE_REL);
+			sngss7_set_ckt_flag(sngss7_info, FLAG_REMOTE_REL);
 		
 			/* move the state of the channel to Terminating to end the call */
 			ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
-		} /* if (!(sngss7_test_flag(sngss7_info, FLAG_GLARE))) */
+		} /* if (!(sngss7_test_ckt_flag(sngss7_info, FLAG_GLARE))) */
 		break;
 	/**************************************************************************/
 	default:	/* should not have gotten an IAM while in this state */
 		SS7_ERROR_CHAN(ftdmchan, "Got IAM on channel in invalid state(%s)...reset!\n", ftdm_channel_state2str (ftdmchan->state));
 
 		/* reset the cic */
-		sngss7_set_flag(sngss7_info, FLAG_RESET_TX);
+		sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX);
 
 		/* move the state of the channel to RESTART to force a reset */
 		ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
@@ -341,7 +341,7 @@ ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circ
 									ftdm_channel_state2str (ftdmchan->state));
 
 			/* reset the cic */
-			sngss7_set_flag(sngss7_info, FLAG_RESET_TX);
+			sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX);
 
 			/* go to RESTART */
 			ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
@@ -545,7 +545,7 @@ ftdm_status_t handle_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circ
 		SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx ANM/CON\n", sngss7_info->circuit->cic);
 
 		/* throw the TX reset flag */
-		sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX);
+		sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX);
 
 		/* go to RESTART */
 		ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
@@ -597,7 +597,7 @@ ftdm_status_t handle_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
 		}
 
 		/* this is a remote hangup request */
-		sngss7_set_flag(sngss7_info, FLAG_REMOTE_REL);
+		sngss7_set_ckt_flag(sngss7_info, FLAG_REMOTE_REL);
 ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL);
 		/* move the state of the channel to CANCEL to end the call */
 		ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
@@ -618,7 +618,7 @@ ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL);
 		}
 
 		/* this is a remote hangup request */
-		sngss7_set_flag(sngss7_info, FLAG_REMOTE_REL);
+		sngss7_set_ckt_flag(sngss7_info, FLAG_REMOTE_REL);
 
 		/* move the state of the channel to TERMINATING to end the call */
 		ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
@@ -631,7 +631,7 @@ ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL);
 		ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL);
 
 		/* since we need to acknowledge the hang up set the flag for remote release */
-		sngss7_set_flag(sngss7_info, FLAG_REMOTE_REL);
+		sngss7_set_ckt_flag(sngss7_info, FLAG_REMOTE_REL);
 
 		/* go to hangup complete to send the RLC */
 		ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
@@ -645,7 +645,7 @@ ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL);
 	default:
 
 		/* throw the reset flag */
-		sngss7_set_flag(sngss7_info, FLAG_RESET_RX);
+		sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_RX);
 
 		/* set the state to RESTART */
 		ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
@@ -1134,13 +1134,13 @@ ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t ci
 	/* lock the channel */
 	ftdm_mutex_lock(ftdmchan->mutex);
 
-	if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) {
+	if (sngss7_test_ckt_flag(sngss7_info, FLAG_GLARE)) {
 		/* the glare flag is already up so it was caught ... do nothing */
 		SS7_DEBUG_CHAN(ftdmchan, "Glare flag is already up...nothing to do!%s\n", " ");
 	} else {
 		SS7_DEBUG_CHAN(ftdmchan, "Glare flag is not up yet...indicating glare from reattempt!%s\n", " ");
 		/* glare, throw the flag */
-		sngss7_set_flag(sngss7_info, FLAG_GLARE);
+		sngss7_set_ckt_flag(sngss7_info, FLAG_GLARE);
 
 		/* clear any existing glare data from the channel */
 		memset(&sngss7_info->glare, 0x0, sizeof(sngss7_glare_data_t));
@@ -1149,7 +1149,7 @@ ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t ci
 		ftdmchan->caller_data.hangup_cause = 34;	/* Circuit Congrestion */
 
 		/* this is a remote hangup request */
-		sngss7_set_flag(sngss7_info, FLAG_REMOTE_REL);
+		sngss7_set_ckt_flag(sngss7_info, FLAG_REMOTE_REL);
 
 		/* move the state of the channel to Terminating to end the call */
 		ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
@@ -1179,7 +1179,7 @@ ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circui
 	sngss7_set_flag(&g_ftdm_sngss7_data.cfg.isupIntf[infId], SNGSS7_PAUSED);
 	
 	/* go through all the circuits now and find any other circuits on this infId */
-	i = 1;
+	i = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
 	while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) {
 		
 		/* check that the infId matches and that this is not a siglink */
@@ -1200,7 +1200,7 @@ ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circui
 			if (ftdm_test_flag(ftdmchan->span, FTDM_SPAN_IN_THREAD)) {
 				SS7_DEBUG_CHAN(ftdmchan, "Rx PAUSE%s\n", "");
 				/* set the pause flag on the channel */
-				sngss7_set_flag(sngss7_info, FLAG_INFID_PAUSED);
+				sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_PAUSED);
 			}
 	
 			/* unlock the channel again before we exit */
@@ -1234,7 +1234,7 @@ ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circu
 	sngss7_clear_flag(&g_ftdm_sngss7_data.cfg.isupIntf[infId], SNGSS7_PAUSED);
 
 	/* go through all the circuits now and find any other circuits on this infId */
-	i = 1;
+	i = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
 	while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) {
 
 		/* check that the infId matches and that this is not a siglink */
@@ -1252,14 +1252,14 @@ ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circu
 			ftdm_mutex_lock(ftdmchan->mutex);
 
 			/* only resume if we are paused */
-			if (sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED)) {
+			if (sngss7_test_ckt_flag(sngss7_info, FLAG_INFID_PAUSED)) {
 				SS7_DEBUG_CHAN(ftdmchan, "Rx RESUME%s\n", "");
 
 				/* set the resume flag on the channel */
-				sngss7_set_flag(sngss7_info, FLAG_INFID_RESUME);
+				sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_RESUME);
 
 				/* clear the paused flag */
-				sngss7_clear_flag(sngss7_info, FLAG_INFID_PAUSED);
+				sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_PAUSED);
 			}
 			
 			/* unlock the channel again before we exit */
@@ -1421,12 +1421,12 @@ ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
 	ftdm_mutex_lock(ftdmchan->mutex);
 
 	/* check if the circuit is already blocked or not */
-	if (sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) {
+	if (sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) {
 		SS7_WARN("Received BLO on circuit that is already blocked!\n");
 	}
 
 	/* throw the ckt block flag */
-	sngss7_set_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX);
+	sngss7_set_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX);
 
 	/* set the channel to suspended state */
 	ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
@@ -1484,15 +1484,15 @@ ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
 	ftdm_mutex_lock(ftdmchan->mutex);
 
 	/* check if the channel is blocked */
-	if (!(sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX))) {
+	if (!(sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX))) {
 		SS7_WARN("Received UBL on circuit that is not blocked!\n");
 	}
 
 	/* throw the unblock flag */
-	sngss7_set_flag(sngss7_info, FLAG_CKT_MN_UNBLK_RX);
+	sngss7_set_ckt_flag(sngss7_info, FLAG_CKT_MN_UNBLK_RX);
 
 	/* clear the block flag */
-	sngss7_clear_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX);
+	sngss7_clear_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX);
 
 	/* set the channel to suspended state */
 	ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
@@ -1550,7 +1550,7 @@ ftdm_status_t handle_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
 	ftdm_mutex_lock(ftdmchan->mutex);
 
 	/* throw the reset flag */
-	sngss7_set_flag(sngss7_info, FLAG_RESET_RX);
+	sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_RX);
 
 	switch (ftdmchan->state) {
 	/**************************************************************************/
@@ -1595,7 +1595,7 @@ ftdm_status_t handle_local_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_
 	ftdm_mutex_lock(ftdmchan->mutex);
 
 	/* throw the reset flag */
-	sngss7_set_flag(sngss7_info, FLAG_RESET_RX);
+	sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_RX);
 
 	switch (ftdmchan->state) {
 	/**************************************************************************/
@@ -1643,9 +1643,9 @@ ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ
 	/**********************************************************************/
 	case FTDM_CHANNEL_STATE_RESTART:
 		
-		if ( sngss7_test_flag(sngss7_info, FLAG_RESET_TX) ) {
+		if ( sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX) ) {
 			/* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */
-			sngss7_set_flag(sngss7_info, FLAG_RESET_TX_RSP);
+			sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX_RSP);
 
 			/* go to DOWN */
 			ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
@@ -1667,7 +1667,7 @@ ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ
 	case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
 		
 		/* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */
-		sngss7_set_flag(sngss7_info, FLAG_RESET_TX_RSP);
+		sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX_RSP);
 
 		/* go to DOWN */
 		/*ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);*/
@@ -1795,12 +1795,12 @@ ftdm_status_t handle_local_blk(uint32_t suInstId, uint32_t spInstId, uint32_t ci
 	ftdm_mutex_lock(ftdmchan->mutex);
 
 	/* check if the circuit is already blocked or not */
-	if (sngss7_test_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX)) {
+	if (sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX)) {
 		SS7_WARN("Received local BLO on circuit that is already blocked!\n");
 	}
 
 	/* throw the ckt block flag */
-	sngss7_set_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX);
+	sngss7_set_ckt_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX);
 
 	/* set the channel to suspended state */
 	ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
@@ -1831,12 +1831,12 @@ ftdm_status_t handle_local_ubl(uint32_t suInstId, uint32_t spInstId, uint32_t ci
 	ftdm_mutex_lock(ftdmchan->mutex);
 
 	/* check if the circuit is already blocked or not */
-	if (sngss7_test_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX)) {
+	if (sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX)) {
 		SS7_WARN("Received local UBL on circuit that is already unblocked!\n");
 	}
 
 	/* throw the ckt block flag */
-	sngss7_set_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX);
+	sngss7_set_ckt_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX);
 
 	/* set the channel to suspended state */
 	ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
@@ -1878,7 +1878,7 @@ ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit
 	ftdm_mutex_lock(ftdmchan->mutex);
 
 	/* throw the ckt block flag */
-	sngss7_set_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK);
+	sngss7_set_ckt_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK);
 
 	/* set the channel to suspended state */
 	ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
@@ -1982,11 +1982,11 @@ ftdm_status_t handle_cgb_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
 			switch (blockType) {
 			/**********************************************************************/
 			case 0:	/* maintenance oriented */
-				sngss7_set_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX);
+				sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX);
 				break;
 			/**********************************************************************/
 			case 1: /* hardware failure oriented */
-				sngss7_set_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX);
+				sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX);
 				break;
 			/**********************************************************************/
 			case 2: /* reserved for national use */
@@ -2113,11 +2113,11 @@ ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
 			switch (blockType) {
 			/**********************************************************************/
 			case 0:	/* maintenance oriented */
-				sngss7_clear_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX);
+				sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX);
 				break;
 			/**********************************************************************/
 			case 1: /* hardware failure oriented */
-				sngss7_clear_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX);
+				sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX);
 				break;
 			/**********************************************************************/
 			case 2: /* reserved for national use */
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c
index 72bd1c3..76984b9 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c
@@ -409,13 +409,80 @@ void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint
 	sngss7_chan_data_t	*sngss7_info = NULL;
 	ftdm_channel_t		*ftdmchan = NULL;
 	sngss7_event_data_t	*sngss7_event = NULL;
-
-	/* get the ftdmchan and ss7_chan_data from the circuit */
-	if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
-		SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
-		SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-		return;
-	}
+	uint32_t			intfId;
+	int 				x;
+
+	/* check if the eventType is a pause/resume */
+	switch (evntType) {
+	/**************************************************************************/
+	case (SIT_STA_PAUSEIND):
+	case (SIT_STA_RESUMEIND):
+
+		/* the circuit for this type of event may not exist on the local system
+		 * so first check if the circuit is local
+		 */
+		if ((circuit >= (g_ftdm_sngss7_data.cfg.procId * 1000)) &&
+			(circuit < ((g_ftdm_sngss7_data.cfg.procId +1) * 1000))) {
+
+			/* the circuit is on the local system, handle normally */
+			goto sta_ind_local;
+		}
+
+		/* the circuit is not local, so find a local circuit with the same intfId
+		 * by finding the orginial circuit in our array first, finding the intfId 
+		 * from there, then go through the local circuits to see if we find a 
+		 * match and use that circuit instead
+		 */
+		intfId = g_ftdm_sngss7_data.cfg.isupCkt[circuit].infId;
+
+		x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
+		while ((g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) &&
+			   (g_ftdm_sngss7_data.cfg.isupCkt[x].id < ((g_ftdm_sngss7_data.cfg.procId +1) * 1000))) {
+		/**********************************************************************/
+			/* confirm this is a voice channel and not a gap/sig (no ftdmchan there) */
+			if (g_ftdm_sngss7_data.cfg.isupCkt[x].type != VOICE) goto move_along;
+
+			/* compare the intfIds */
+			if (g_ftdm_sngss7_data.cfg.isupCkt[x].infId == intfId) {
+				/* we have a match, setup the pointers to the correct values */
+				circuit = x;
+				
+				if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+					SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+					SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+					return;
+				}
+
+				/* bounce out of the loop */
+				break;
+			} /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].intfId == intfId) */
+
+move_along:
+			/* move along ... nothing to see here */
+			x++;
+
+		/**********************************************************************/
+		} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */
+
+		/* check if we found any circuits that are on the intfId, drop the message
+		 * if none are found
+		 */
+		if (ftdmchan == NULL) goto sta_ind_end;
+
+		break;
+	/**************************************************************************/
+	default:
+sta_ind_local:
+		/* get the ftdmchan and ss7_chan_data from the circuit */
+		if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+			SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+			SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+			return;
+		}
+		
+		break;
+	/**************************************************************************/
+	} /* switch (evntType) */
 
 	/* initalize the sngss7_event */
 	sngss7_event = ftdm_malloc(sizeof(*sngss7_event));
@@ -440,6 +507,7 @@ void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint
 	/* enqueue this event */
 	ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event);
 
+sta_ind_end:
 	SS7_FUNC_TRACE_EXIT(__FUNCTION__);
 }
 
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c
index 3f507d6..1dfcab4 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c
@@ -48,6 +48,8 @@ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta);
 void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta);
 void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta);
 void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta);
+void handle_sng_relay_alarm(Pst *pst, RyMngmt *sta);
+
 /******************************************************************************/
 
 /* FUNCTIONS ******************************************************************/
@@ -132,17 +134,17 @@ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta)
 
 			/* find the name for the sap in question */
 			x = 1;
-			while (g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) {
-				if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == sta->t.usta.evntParm[0]) {
+			while (g_ftdm_sngss7_data.cfg.mtp2Link[x].id != 0) {
+				if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == sta->t.usta.evntParm[0]) {
 					break;
 				}
 				x++;
 			}
 
-			if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == 0) {
+			if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == 0) {
 				sprintf(buf, "[SAPID:%d]", sta->t.usta.evntParm[0]);
 			} else {
-				sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtpLink[x].name);
+				sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtp2Link[x].name);
 			}
 					
 
@@ -173,17 +175,17 @@ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta)
 			
 			/* find the name for the sap in question */
 			x = 1;
-			while (g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) {
-				if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == sta->t.usta.evntParm[0]) {
+			while (g_ftdm_sngss7_data.cfg.mtp2Link[x].id != 0) {
+				if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == sta->t.usta.evntParm[0]) {
 					break;
 				}
 				x++;
 			}
 
-			if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == 0) {
+			if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == 0) {
 				sprintf(buf, "[SAPID:%d]", sta->t.usta.evntParm[0]);
 			} else {
-				sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtpLink[x].name);
+				sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtp2Link[x].name);
 			}
 
 			ftdm_log(FTDM_LOG_ERROR,"[MTP2]%s %s : %s\n",
@@ -196,17 +198,17 @@ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta)
 			
 			/* find the name for the sap in question */
 			x = 1;
-			while (g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) {
-				if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == sta->t.usta.evntParm[0]) {
+			while (g_ftdm_sngss7_data.cfg.mtp2Link[x].id != 0) {
+				if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == sta->t.usta.evntParm[0]) {
 					break;
 				}
 				x++;
 			}
 
-			if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == 0) {
+			if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == 0) {
 				sprintf(buf, "[SAPID:%d]", sta->t.usta.evntParm[0]);
 			} else {
-				sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtpLink[x].name);
+				sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtp2Link[x].name);
 			}
 
 			ftdm_log(FTDM_LOG_ERROR,"[MTP2]%s %s : %s\n",
@@ -220,17 +222,17 @@ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta)
 
 			/* find the name for the sap in question */
 			x = 1;
-			while (g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) {
-				if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == sta->t.usta.evntParm[0]) {
+			while (g_ftdm_sngss7_data.cfg.mtp2Link[x].id != 0) {
+				if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == sta->t.usta.evntParm[0]) {
 					break;
 				}
 				x++;
 			}
 
-			if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == 0) {
+			if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == 0) {
 				sprintf(buf, "[SAPID:%d]", sta->t.usta.evntParm[0]);
 			} else {
-				sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtpLink[x].name);
+				sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtp2Link[x].name);
 			}
 
 			ftdm_log(FTDM_LOG_ERROR,"[MTP2]%s %s : RTB Queue Len(%d)|Oldest BSN(%d)|Tx Queue Len(%d)|Outstanding Frames(%d)\n",
@@ -246,17 +248,17 @@ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta)
 
 			/* find the name for the sap in question */
 			x = 1;
-			while (g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) {
-				if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == sta->t.usta.evntParm[0]) {
+			while (g_ftdm_sngss7_data.cfg.mtp2Link[x].id != 0) {
+				if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == sta->t.usta.evntParm[0]) {
 					break;
 				}
 				x++;
 			}
 
-			if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == 0) {
+			if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == 0) {
 				sprintf(buf, "[SAPID:%d]", sta->t.usta.evntParm[0]);
 			} else {
-				sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtpLink[x].name);
+				sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtp2Link[x].name);
 			}
 
 			ftdm_log(FTDM_LOG_ERROR,"[MTP2]%s %s : RTB Queue Len(%d)\n",
@@ -269,17 +271,17 @@ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta)
 
 			/* find the name for the sap in question */
 			x = 1;
-			while (g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) {
-				if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == sta->t.usta.evntParm[0]) {
+			while (g_ftdm_sngss7_data.cfg.mtp2Link[x].id != 0) {
+				if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == sta->t.usta.evntParm[0]) {
 					break;
 				}
 				x++;
 			}
 
-			if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == 0) {
+			if (g_ftdm_sngss7_data.cfg.mtp2Link[x].id == 0) {
 				sprintf(buf, "[SAPID:%d]", sta->t.usta.evntParm[0]);
 			} else {
-				sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtpLink[x].name);
+				sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtp2Link[x].name);
 			}
 
 			ftdm_log(FTDM_LOG_ERROR,"[MTP2]%s %s : %d\n",
@@ -290,9 +292,11 @@ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta)
 		/**********************************************************************/
 		case (LCM_EVENT_UI_INV_EVT):
 		case (LCM_EVENT_LI_INV_EVT):
-			ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s : %s : Primitive (%d)\n",
+			ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s(%d) : %s(%d) : Primitive (%d)\n",
 										DECODE_LSD_EVENT(sta->t.usta.alarm.event),
+										sta->t.usta.alarm.event,
 										DECODE_LCM_CAUSE(sta->t.usta.alarm.cause),
+										sta->t.usta.alarm.cause,
 										sta->t.usta.evntParm[0]);
 			break;
 		/**********************************************************************/
@@ -362,22 +366,23 @@ void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta)
 
 			/* find the name for the sap in question */
 			x = 1;
-			while (g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) {
-				if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == sta->hdr.elmId.elmntInst1) {
+			while (g_ftdm_sngss7_data.cfg.mtp3Link[x].id != 0) {
+				if (g_ftdm_sngss7_data.cfg.mtp3Link[x].id == sta->hdr.elmId.elmntInst1) {
 					break;
 				}
 				x++;
 			}
 
-			if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == 0) {
+			if (g_ftdm_sngss7_data.cfg.mtp3Link[x].id == 0) {
 				sprintf(buf, "[SAPID:%d]", sta->hdr.elmId.elmntInst1);
 			} else {
-				sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtpLink[x].name);
+				sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtp3Link[x].name);
 			}
 
 		switch (sta->t.usta.alarm.event) {
 		/**********************************************************************/
 		case (LSN_EVENT_INV_OPC_OTHER_END):
+			
 			ftdm_log(FTDM_LOG_ERROR,"[MTP3]%s %s : %s : OPC(0x%X%X%X%X)\n",
 										buf,
 										DECODE_LSN_EVENT(sta->t.usta.alarm.event),
@@ -460,7 +465,7 @@ void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta)
 			break;
 		/**********************************************************************/
 		default:
-			ftdm_log(FTDM_LOG_ERROR,"[MTP3][DPC:0x%d%d%d%d] %s : %s\n",
+			ftdm_log(FTDM_LOG_ERROR,"[MTP3][DPC:0x%X%X%X%X] %s : %s\n",
 										sta->t.usta.evntParm[0],
 										sta->t.usta.evntParm[1],
 										sta->t.usta.evntParm[2],
@@ -744,7 +749,63 @@ void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta)
 
 	return;
 }   /* handle_cc_alarm */
+
 /******************************************************************************/
+void handle_sng_relay_alarm(Pst *pst, RyMngmt *sta)
+{
+
+
+	switch (sta->hdr.elmId.elmnt) {
+	/**************************************************************************/
+	case (LRY_USTA_ERR): /* ERROR */
+		ftdm_log(FTDM_LOG_ERROR,"[RELAY] Error: tx procId %d: err procId %d: channel %d: seq %s: reason %s\n",
+												sta->t.usta.s.ryErrUsta.sendPid,
+												sta->t.usta.s.ryErrUsta.errPid,
+												sta->t.usta.s.ryErrUsta.id,
+												DECODE_LRY_SEQ(sta->t.usta.s.ryErrUsta.sequence),
+												DECODE_LRY_REASON(sta->t.usta.s.ryErrUsta.reason));
+
+		/* process the event */
+		handle_relay_disconnect_on_error(sta);
+
+		break;
+	/**************************************************************************/
+	case (LRY_USTA_CNG): /* Congestion */
+		ftdm_log(FTDM_LOG_ERROR,"[RELAY] Congestion: tx procId %d: rem procId %d: channel %d: %s\n",
+												sta->t.usta.s.ryCongUsta.sendPid,
+												sta->t.usta.s.ryCongUsta.remPid,
+												sta->t.usta.s.ryCongUsta.id,
+												DECODE_LRY_CONG_FLAGS(sta->t.usta.s.ryCongUsta.flags));
+		break;
+	/**************************************************************************/
+	case (LRY_USTA_UP): /* channel up */
+		ftdm_log(FTDM_LOG_ERROR,"[RELAY] Channel UP: tx procId %d: channel %d\n",
+												sta->t.usta.s.ryUpUsta.sendPid,
+												sta->t.usta.s.ryUpUsta.id);
+
+		/* process the event */
+		handle_relay_connect(sta);
+
+		break;
+	/**************************************************************************/
+	case (LRY_USTA_DN): /* channel down */
+		ftdm_log(FTDM_LOG_ERROR,"[RELAY] Channel DOWN: tx procId %d: channel %d\n",
+												sta->t.usta.s.ryUpUsta.sendPid,
+												sta->t.usta.s.ryUpUsta.id);
+
+		/* process the event */
+		handle_relay_disconnect_on_down(sta);
+
+		break;
+	/**************************************************************************/
+	default:
+		ftdm_log(FTDM_LOG_ERROR,"Unknown Relay Alram\n");
+		break;
+	/**************************************************************************/
+	} /* switch (sta->hdr.elmId.elmnt) */
+
+	return;
+}
 
 /******************************************************************************/
 /* For Emacs:
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
index 9016771..c971179 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
@@ -543,7 +543,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 					ftdmchan->caller_data.hangup_cause = 41;
 		
 					/* set the flag to indicate this hangup is started from the local side */
-					sngss7_set_flag (sngss7_info, FLAG_LOCAL_REL);
+					sngss7_set_ckt_flag (sngss7_info, FLAG_LOCAL_REL);
 		
 					/* end the call */
 					ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
@@ -673,7 +673,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 		}
 
 		/* set the flag to indicate this hangup is started from the remote side */
-		sngss7_set_flag (sngss7_info, FLAG_REMOTE_REL);
+		sngss7_set_ckt_flag (sngss7_info, FLAG_REMOTE_REL);
 
 		/*this state is set when the line is hanging up */
 		sigev.event_id = FTDM_SIGEVENT_STOP;
@@ -689,15 +689,15 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 		}
 
 		/* check for remote hangup flag */
-		if (sngss7_test_flag (sngss7_info, FLAG_REMOTE_REL)) {
+		if (sngss7_test_ckt_flag (sngss7_info, FLAG_REMOTE_REL)) {
 			/* remote release ...do nothing here */
 			SS7_DEBUG_CHAN(ftdmchan,"Hanging up remotely requested call!%s\n", "");
-		} else if (sngss7_test_flag (sngss7_info, FLAG_GLARE)) {
+		} else if (sngss7_test_ckt_flag (sngss7_info, FLAG_GLARE)) {
 			/* release due to glare */
 			SS7_DEBUG_CHAN(ftdmchan,"Hanging up requested call do to glare%s\n", "");
 		} else 	{
 			/* set the flag to indicate this hangup is started from the local side */
-			sngss7_set_flag (sngss7_info, FLAG_LOCAL_REL);
+			sngss7_set_ckt_flag (sngss7_info, FLAG_LOCAL_REL);
 
 			/*this state is set when FS is hanging up...so tell the stack */
 			ft_to_sngss7_rel (ftdmchan);
@@ -718,16 +718,16 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 			break;
 		}
 
-		if (sngss7_test_flag (sngss7_info, FLAG_REMOTE_REL)) {
+		if (sngss7_test_ckt_flag (sngss7_info, FLAG_REMOTE_REL)) {
 			/* check if this hangup is from a tx RSC */
-			if (sngss7_test_flag (sngss7_info, FLAG_RESET_TX)) {
+			if (sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_TX)) {
 				/* go to RESTART State until RSCa is received */
 				ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RESTART);
 			} else {
 				/* if the hangup is from a rx RSC, rx GRS, or glare don't sent RLC */
-				if (!(sngss7_test_flag(sngss7_info, FLAG_RESET_RX)) &&
-					!(sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX)) &&
-					!(sngss7_test_flag(sngss7_info, FLAG_GLARE))) {
+				if (!(sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_RX)) &&
+					!(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX)) &&
+					!(sngss7_test_ckt_flag(sngss7_info, FLAG_GLARE))) {
 
 					/* send out the release complete */
 					ft_to_sngss7_rlc (ftdmchan);
@@ -738,17 +738,17 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 			}
 
 			SS7_DEBUG_CHAN(ftdmchan,"Completing remotely requested hangup!%s\n", "");
-		} else if (sngss7_test_flag (sngss7_info, FLAG_LOCAL_REL)) {
+		} else if (sngss7_test_ckt_flag (sngss7_info, FLAG_LOCAL_REL)) {
 
 			/* if this hang up is do to a rx RESET we need to sit here till the RSP arrives */
-			if (sngss7_test_flag (sngss7_info, FLAG_RESET_TX_RSP)) {
+			if (sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_TX_RSP)) {
 				/* go to the down state as we have already received RSC-RLC */
 				ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DOWN);
 			}
 
 			/* if it's a local release the user sends us to down */
 			SS7_DEBUG_CHAN(ftdmchan,"Completing locally requested hangup!%s\n", "");
-		} else if (sngss7_test_flag (sngss7_info, FLAG_GLARE)) {
+		} else if (sngss7_test_ckt_flag (sngss7_info, FLAG_GLARE)) {
 			SS7_DEBUG_CHAN(ftdmchan,"Completing requested hangup due to glare!%s\n", "");
 
 			ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DOWN);
@@ -767,18 +767,18 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 		}
 
 		/* check if there is a reset response that needs to be sent */
-		if (sngss7_test_flag (sngss7_info, FLAG_RESET_RX)) {
+		if (sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_RX)) {
 			/* send a RSC-RLC */
 			ft_to_sngss7_rsca (ftdmchan);
 
 			/* clear the reset flag  */
 			clear_rx_rsc_flags(sngss7_info);
-		} /* if (sngss7_test_flag (sngss7_info, FLAG_RESET_RX)) */
+		} /* if (sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_RX)) */
 
 		/* check if there was a GRS that needs a GRA */
-		if ((sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX)) &&
-			(sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) &&
-			(sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT))) {
+		if ((sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX)) &&
+			(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) &&
+			(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT))) {
 
 			/* check if this is the base circuit and send out the GRA
 			 * we insure that this is the last circuit to have the state change queued
@@ -794,40 +794,40 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 
 			/* clear the grp reset flag */
 			clear_rx_grs_flags(sngss7_info);
-		}/*  if ( sngss7_test_flag ( sngss7_info, FLAG_GRP_RESET_RX ) ) */
+		}/*  if ( sngss7_test_ckt_flag ( sngss7_info, FLAG_GRP_RESET_RX ) ) */
 
 		/* check if we got the reset response */
-		if (sngss7_test_flag(sngss7_info, FLAG_RESET_TX_RSP)) {
+		if (sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX_RSP)) {
 			/* clear the reset flag  */
 			clear_tx_rsc_flags(sngss7_info);
-		} /* if (sngss7_test_flag(sngss7_info, FLAG_RESET_TX_RSP)) */
+		} /* if (sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX_RSP)) */
 
-		if (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) {
+		if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) {
 			/* clear the reset flag  */
 			clear_tx_grs_flags(sngss7_info);
 			
 			/* clean out the spans GRA structure */
 			clear_rx_gra_data(sngss7_info);
-		} /* if (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) */
+		} /* if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) */
 
 		/* check if we came from reset (aka we just processed a reset) */
 		if ((ftdmchan->last_state == FTDM_CHANNEL_STATE_RESTART) || 
 			(ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED)) {
 
 			/* check if reset flags are up indicating there is more processing to do yet */
-			if (!(sngss7_test_flag (sngss7_info, FLAG_RESET_TX)) &&
-				!(sngss7_test_flag (sngss7_info, FLAG_RESET_RX)) &&
-				!(sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_TX)) &&
-				!(sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_RX))) {
+			if (!(sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_TX)) &&
+				!(sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_RX)) &&
+				!(sngss7_test_ckt_flag (sngss7_info, FLAG_GRP_RESET_TX)) &&
+				!(sngss7_test_ckt_flag (sngss7_info, FLAG_GRP_RESET_RX))) {
 
 				/* now check if there is an active block */
-				if (!(sngss7_test_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX)) &&
-					!(sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) &&
-					!(sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) &&
-					!(sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) &&
-					!(sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX)) &&
-					!(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) &&
-					!(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX))) {
+				if (!(sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX)) &&
+					!(sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) &&
+					!(sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) &&
+					!(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) &&
+					!(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX)) &&
+					!(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) &&
+					!(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX))) {
 				
 					/* check if the sig status is down, and bring it up if it isn't */
 					if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) {
@@ -839,7 +839,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 					} /* if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) */
 				} /* if !blocked */
 			} else {
-				SS7_DEBUG_CHAN(ftdmchan,"Reset flags present (0x%X)\n", sngss7_info->flags);
+				SS7_DEBUG_CHAN(ftdmchan,"Reset flags present (0x%X)\n", sngss7_info->ckt_flags);
 			
 				/* there is still another reset pending so go back to reset*/
 				ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
@@ -858,8 +858,8 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 		sngss7_info->spId = 0;
 
 		/* clear any call related flags */
-		sngss7_clear_flag (sngss7_info, FLAG_REMOTE_REL);
-		sngss7_clear_flag (sngss7_info, FLAG_LOCAL_REL);
+		sngss7_clear_ckt_flag (sngss7_info, FLAG_REMOTE_REL);
+		sngss7_clear_ckt_flag (sngss7_info, FLAG_LOCAL_REL);
 
 
 		if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OPEN)) {
@@ -869,10 +869,10 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 		} /* if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OPEN)) */
 
 		/* check if there is a glared call that needs to be processed */
-		if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) {
+		if (sngss7_test_ckt_flag(sngss7_info, FLAG_GLARE)) {
 			
 			/* clear the glare flag */
-			sngss7_clear_flag (sngss7_info, FLAG_GLARE);
+			sngss7_clear_ckt_flag (sngss7_info, FLAG_GLARE);
 
 			/* check if we have an IAM stored...if we don't have one just exit */
 			if (sngss7_info->glare.circuit != 0) {
@@ -885,23 +885,23 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 				/* clear the glare info */
 				memset(&sngss7_info->glare, 0x0, sizeof(sngss7_glare_data_t));
 			} /* if (sngss7_info->glare.circuit != 0) */
-		} /* if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) */
+		} /* if (sngss7_test_ckt_flag(sngss7_info, FLAG_GLARE)) */
 
 		break;
 	/**************************************************************************/
 	case FTDM_CHANNEL_STATE_RESTART:	/* CICs needs a Reset */
 
-		if (sngss7_test_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK)) {
-			if ((sngss7_test_flag(sngss7_info, FLAG_RESET_RX)) ||
-				(sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX))) {
+		if (sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK)) {
+			if ((sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_RX)) ||
+				(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX))) {
 
 				SS7_DEBUG_CHAN(ftdmchan,"Incoming Reset request on CIC in UCIC block, removing UCIC block%s\n", "");
 
 				/* set the unblk flag */
-				sngss7_set_flag(sngss7_info, FLAG_CKT_UCIC_UNBLK);
+				sngss7_set_ckt_flag(sngss7_info, FLAG_CKT_UCIC_UNBLK);
 
 				/* clear the block flag */
-				sngss7_clear_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK);
+				sngss7_clear_ckt_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK);
 
 				/* process the flag */
 				ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
@@ -915,28 +915,28 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 		 * we can also check if we are in a PAUSED state (no point in sending message
 		 */
 		if ((ftdmchan->last_state != FTDM_CHANNEL_STATE_HANGUP_COMPLETE) &&
-			(!sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED))) {
+			(!sngss7_test_ckt_flag(sngss7_info, FLAG_INFID_PAUSED))) {
 
 			/* check if this is an outgoing RSC */
-			if ((sngss7_test_flag(sngss7_info, FLAG_RESET_TX)) &&
-				!(sngss7_test_flag(sngss7_info, FLAG_RESET_SENT))) {
+			if ((sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX)) &&
+				!(sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_SENT))) {
 
 				/* send a reset request */
 				ft_to_sngss7_rsc (ftdmchan);
-				sngss7_set_flag(sngss7_info, FLAG_RESET_SENT);
+				sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_SENT);
 
-			} /* if (sngss7_test_flag(sngss7_info, FLAG_RESET_TX)) */
+			} /* if (sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX)) */
 	
 			/* check if this is the first channel of a GRS (this flag is thrown when requesting reset) */
-			if ( (sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_TX)) &&
-				!(sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_SENT)) &&
-				(sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_BASE))) {
+			if ( (sngss7_test_ckt_flag (sngss7_info, FLAG_GRP_RESET_TX)) &&
+				!(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_SENT)) &&
+				(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_BASE))) {
 
 					/* send out the grs */
 					ft_to_sngss7_grs (ftdmchan);
-					sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_SENT);
+					sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_SENT);
 
-			}/* if ( sngss7_test_flag ( sngss7_info, FLAG_GRP_RESET_TX ) ) */
+			}/* if ( sngss7_test_ckt_flag ( sngss7_info, FLAG_GRP_RESET_TX ) ) */
 		} /* if ( last_state != HANGUP && !PAUSED */
 	
 		/* if the sig_status is up...bring it down */
@@ -946,10 +946,10 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 			ftdm_span_send_signal (ftdmchan->span, &sigev);
 		}
 
-		if (sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_RX)) {
+		if (sngss7_test_ckt_flag (sngss7_info, FLAG_GRP_RESET_RX)) {
 			/* set the grp reset done flag so we know we have finished this reset */
-			sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX_DN);
-		} /* if (sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_RX)) */
+			sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_DN);
+		} /* if (sngss7_test_ckt_flag (sngss7_info, FLAG_GRP_RESET_RX)) */
 
 
 		if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_INUSE)) {
@@ -987,17 +987,17 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 			} /* switch (ftdmchan->last_state) */
 		} else {
 			/* check if this an incoming RSC or we have a response already */
-			if (sngss7_test_flag (sngss7_info, FLAG_RESET_RX) ||
-				sngss7_test_flag (sngss7_info, FLAG_RESET_TX_RSP) ||
-				sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_TX_RSP) ||
-				sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_RX_CMPLT)) {
+			if (sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_RX) ||
+				sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_TX_RSP) ||
+				sngss7_test_ckt_flag (sngss7_info, FLAG_GRP_RESET_TX_RSP) ||
+				sngss7_test_ckt_flag (sngss7_info, FLAG_GRP_RESET_RX_CMPLT)) {
 	
-				SS7_DEBUG_CHAN(ftdmchan, "Reset processed moving to DOWN (0x%X)\n", sngss7_info->flags);
+				SS7_DEBUG_CHAN(ftdmchan, "Reset processed moving to DOWN (0x%X)\n", sngss7_info->ckt_flags);
 	
 				/* go to a down state to clear the channel and send the response */
 				ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DOWN);
 			} else {
-				SS7_DEBUG_CHAN(ftdmchan, "Waiting on Reset Rsp/Grp Reset to move to DOWN (0x%X)\n", sngss7_info->flags);
+				SS7_DEBUG_CHAN(ftdmchan, "Waiting on Reset Rsp/Grp Reset to move to DOWN (0x%X)\n", sngss7_info->ckt_flags);
 			}
 		}
 
@@ -1005,20 +1005,20 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 	/**************************************************************************/
 	case FTDM_CHANNEL_STATE_SUSPENDED:	/* circuit has been blocked */
 
-		  SS7_DEBUG_CHAN(ftdmchan,"Current flags: 0x%X\n", sngss7_info->flags);
+		  SS7_DEBUG_CHAN(ftdmchan,"Current flags: 0x%X\n", sngss7_info->ckt_flags);
 
 		/**********************************************************************/
-		if (sngss7_test_flag(sngss7_info, FLAG_INFID_RESUME)) {
+		if (sngss7_test_ckt_flag(sngss7_info, FLAG_INFID_RESUME)) {
 			SS7_DEBUG_CHAN(ftdmchan, "Processing RESUME%s\n", "");
 
 			/* clear the RESUME flag */
-			sngss7_clear_flag(sngss7_info, FLAG_INFID_RESUME);
+			sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_RESUME);
 
 			/* if there are any resets present */
-			if ((sngss7_test_flag (sngss7_info, FLAG_RESET_TX)) ||
-				(sngss7_test_flag (sngss7_info, FLAG_RESET_RX)) ||
-				(sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_TX)) ||
-				(sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_RX))) {
+			if ((sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_TX)) ||
+				(sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_RX)) ||
+				(sngss7_test_ckt_flag (sngss7_info, FLAG_GRP_RESET_TX)) ||
+				(sngss7_test_ckt_flag (sngss7_info, FLAG_GRP_RESET_RX))) {
 
 				/* go back to the reset state */
 				goto suspend_goto_restart;
@@ -1034,7 +1034,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 			goto suspend_goto_last;
 		} /* if (sngss7_test_flag(sngss7_info, FLAG_INFID_RESUME)) */
 
-		if (sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED)) {
+		if (sngss7_test_ckt_flag(sngss7_info, FLAG_INFID_PAUSED)) {
 			SS7_DEBUG_CHAN(ftdmchan, "Processing PAUSE%s\n", "");
 
 			/* bring the sig status down */
@@ -1044,9 +1044,9 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 
 			/* go back to the last state */
 			goto suspend_goto_last;
-		} /* if (sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED)) { */
+		} /* if (sngss7_test_ckt_flag(sngss7_info, FLAG_INFID_PAUSED)) { */
 		/**********************************************************************/
-		if (sngss7_test_flag (sngss7_info, FLAG_CKT_MN_BLOCK_RX)) {
+		if (sngss7_test_ckt_flag (sngss7_info, FLAG_CKT_MN_BLOCK_RX)) {
 			SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_BLOCK_RX flag %s\n", "");
 
 			/* bring the sig status down */
@@ -1061,11 +1061,11 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 			goto suspend_goto_last;
 		}
 
-		if (sngss7_test_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX)){
+		if (sngss7_test_ckt_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX)){
 			SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_UNBLK_RX flag %s\n", "");
 
 			/* clear the unblock flag */
-			sngss7_clear_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX);
+			sngss7_clear_ckt_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX);
 
 			/* bring the sig status up */
 			sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
@@ -1080,7 +1080,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 		}
 
 		/**********************************************************************/
-		if (sngss7_test_flag (sngss7_info, FLAG_CKT_MN_BLOCK_TX)) {
+		if (sngss7_test_ckt_flag (sngss7_info, FLAG_CKT_MN_BLOCK_TX)) {
 			SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_BLOCK_TX flag %s\n", "");
 
 			/* bring the sig status down */
@@ -1095,11 +1095,11 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 			goto suspend_goto_last;
 		}
 
-		if (sngss7_test_flag (sngss7_info, FLAG_CKT_MN_UNBLK_TX)){
+		if (sngss7_test_ckt_flag (sngss7_info, FLAG_CKT_MN_UNBLK_TX)){
 			SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_UNBLK_TX flag %s\n", "");
 
 			/* clear the unblock flag */
-			sngss7_clear_flag (sngss7_info, FLAG_CKT_MN_UNBLK_TX);
+			sngss7_clear_ckt_flag (sngss7_info, FLAG_CKT_MN_UNBLK_TX);
 
 			/* bring the sig status up */
 			sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
@@ -1114,7 +1114,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 		}
 
 		/**********************************************************************/
-		if (sngss7_test_flag (sngss7_info, FLAG_CKT_LC_BLOCK_RX)) {
+		if (sngss7_test_ckt_flag (sngss7_info, FLAG_CKT_LC_BLOCK_RX)) {
 			SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_LC_BLOCK_RX flag %s\n", "");
 
 			/* send a BLA */
@@ -1124,11 +1124,11 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 			goto suspend_goto_last;
 		}
 
-		if (sngss7_test_flag (sngss7_info, FLAG_CKT_LC_UNBLK_RX)) {
+		if (sngss7_test_ckt_flag (sngss7_info, FLAG_CKT_LC_UNBLK_RX)) {
 			SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_LC_UNBLK_RX flag %s\n", "");
 			
 			/* clear the unblock flag */
-			sngss7_clear_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX);
+			sngss7_clear_ckt_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX);
 
 			/* send a uba */
 			/*ft_to_sngss7_uba(ftdmchan);*/
@@ -1137,7 +1137,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 			goto suspend_goto_last;
 		}
 		/**********************************************************************/
-		if (sngss7_test_flag (sngss7_info, FLAG_CKT_UCIC_BLOCK)) {
+		if (sngss7_test_ckt_flag (sngss7_info, FLAG_CKT_UCIC_BLOCK)) {
 			SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_UCIC_BLOCK flag %s\n", "");
 
 			/* bring the channel signaling status to down */
@@ -1157,17 +1157,17 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 			goto suspend_goto_last;
 		}
 
-		if (sngss7_test_flag (sngss7_info, FLAG_CKT_UCIC_UNBLK)) {
+		if (sngss7_test_ckt_flag (sngss7_info, FLAG_CKT_UCIC_UNBLK)) {
 			SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_UCIC_UNBLK flag %s\n", "");;
 
 			/* remove the UCIC block flag */
-			sngss7_clear_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK);
+			sngss7_clear_ckt_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK);
 
 			/* remove the UCIC unblock flag */
-			sngss7_clear_flag(sngss7_info, FLAG_CKT_UCIC_UNBLK);
+			sngss7_clear_ckt_flag(sngss7_info, FLAG_CKT_UCIC_UNBLK);
 
 			/* throw the channel into reset to sync states */
-			sngss7_set_flag(sngss7_info, FLAG_RESET_TX);
+			sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX);
 
 			/* bring the channel into restart again */
 			goto suspend_goto_restart;
@@ -1232,9 +1232,9 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call)
 	}
 
 	/* check if there is a remote block */
-	if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) ||
-		(sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) ||
-		(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) {
+	if ((sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) ||
+		(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) ||
+		(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) {
 
 		/* the channel is blocked...can't send any calls here */
 		SS7_ERROR_CHAN(ftdmchan, "Requested channel is remotely blocked, re-hunt channel!%s\n", " ");
@@ -1242,9 +1242,9 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call)
 	}
 
 	/* check if there is a local block */
-	if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) ||
-		(sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX)) ||
-		(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX))) {
+	if ((sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) ||
+		(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX)) ||
+		(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX))) {
 
 		/* KONRAD FIX ME : we should check if this is a TEST call and allow it */
 
@@ -1339,6 +1339,25 @@ static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span)
 
 	SS7_INFO ("Starting span %s:%u.\n", span->name, span->span_id);
 
+	/* clear the monitor thread stop flag */
+	ftdm_clear_flag (span, FTDM_SPAN_STOP_THREAD);
+	ftdm_clear_flag (span, FTDM_SPAN_IN_THREAD);
+
+	/* activate all the configured ss7 links */
+	if (ft_to_sngss7_activate_all()) {
+		SS7_CRITICAL ("Failed to activate LibSngSS7!\n");
+		return FTDM_FAIL;
+	}
+
+	/*start the span monitor thread */
+	if (ftdm_thread_create_detached (ftdm_sangoma_ss7_run, span) != FTDM_SUCCESS) {
+		SS7_CRITICAL ("Failed to start Span Monitor Thread!\n");
+		return FTDM_FAIL;
+	}
+
+	/* confirm the state of all isup interfaces*/
+	check_status_of_all_isup_intf();
+
 	/* throw the channels in pause */
 	for (x = 1; x < (span->chan_count + 1); x++) {
 		/* extract the channel structure and sngss7 channel data */
@@ -1348,23 +1367,24 @@ static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span)
 		sngss7_span = ftdmchan->span->signal_data;
 		sngss7_intf = &g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId];
 
-
 		/* lock the channel */
 		ftdm_mutex_lock(ftdmchan->mutex);
 
 		/* check if the interface is paused or resumed */
 		if (sngss7_test_flag(sngss7_intf, SNGSS7_PAUSED)) {
+			SS7_DEBUG_CHAN(ftdmchan, "ISUP intf %d is PAUSED\n", sngss7_intf->id);
 			/* throw the pause flag */
-			sngss7_clear_flag(sngss7_info, FLAG_INFID_RESUME);
-			sngss7_set_flag(sngss7_info, FLAG_INFID_PAUSED);
+			sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_RESUME);
+			sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_PAUSED);
 		} else {
-			/* throw the pause flag */
-			sngss7_clear_flag(sngss7_info, FLAG_INFID_PAUSED);
-			sngss7_set_flag(sngss7_info, FLAG_INFID_RESUME);
+			SS7_DEBUG_CHAN(ftdmchan, "ISUP intf %d is RESUMED\n", sngss7_intf->id);
+			/* throw the resume flag */
+			sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_PAUSED);
+			sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_RESUME);
 		}
 #if 0
 		/* throw the grp reset flag */
-		sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX);
+		sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX);
 		if (x == 1) {
 			sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_BASE);
 			sngss7_span->tx_grs.circuit = sngss7_info->circuit->id;
@@ -1372,7 +1392,7 @@ static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span)
 		}
 #else
 		/* throw the channel into reset */
-		sngss7_set_flag(sngss7_info, FLAG_RESET_TX);
+		sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX);
 #endif
 		/* throw the channel to suspend */
 		ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
@@ -1381,22 +1401,6 @@ static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span)
 		ftdm_mutex_unlock(ftdmchan->mutex);
 	}
 
-	/* clear the monitor thread stop flag */
-	ftdm_clear_flag (span, FTDM_SPAN_STOP_THREAD);
-	ftdm_clear_flag (span, FTDM_SPAN_IN_THREAD);
-
-	/* activate all the configured ss7 links */
-	if (ft_to_sngss7_activate_all()) {
-		SS7_CRITICAL ("Failed to activate LibSngSS7!\n");
-		return FTDM_FAIL;
-	}
-
-	/*start the span monitor thread */
-	if (ftdm_thread_create_detached (ftdm_sangoma_ss7_run, span) != FTDM_SUCCESS) {
-		SS7_CRITICAL ("Failed to start Span Monitor Thread!\n");
-		return FTDM_FAIL;
-	}
-
 	SS7_DEBUG ("Finished starting span %s:%u.\n", span->name, span->span_id);
 
 	return FTDM_SUCCESS;
@@ -1537,7 +1541,6 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_ss7_init)
 	sng_event.cc.sng_umsg_ind = sngss7_umsg_ind;
 	sng_event.cc.sng_susp_ind = sngss7_susp_ind;
 	sng_event.cc.sng_resm_ind = sngss7_resm_ind;
-	sng_event.cc.sng_ssp_sta_cfm = sngss7_ssp_sta_cfm;
 
 	sng_event.sm.sng_log = handle_sng_log;
 	sng_event.sm.sng_mtp1_alarm = handle_sng_mtp1_alarm;
@@ -1545,9 +1548,10 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_ss7_init)
 	sng_event.sm.sng_mtp3_alarm = handle_sng_mtp3_alarm;
 	sng_event.sm.sng_isup_alarm = handle_sng_isup_alarm;
 	sng_event.sm.sng_cc_alarm = handle_sng_cc_alarm;
+	sng_event.sm.sng_relay_alarm = handle_sng_relay_alarm;
 
 	/* initalize sng_ss7 library */
-	sng_isup_init (&sng_event);
+	sng_isup_init_gen(&sng_event);
 
 	/* print the version of the library being used */
 	sng_isup_version(&major, &minor, &build);
@@ -1566,7 +1570,32 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_ss7_unload)
 
 	ftdm_log (FTDM_LOG_INFO, "Starting ftmod_sangoma_ss7 unload...\n");
 
-	sng_isup_free();
+	if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC)) {
+		sng_isup_free_cc();
+	}
+
+	if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP)) {
+		ftmod_ss7_shutdown_isup();
+		sng_isup_free_isup();
+	}
+
+	if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3)) {
+		ftmod_ss7_shutdown_mtp3();
+		sng_isup_free_mtp3();
+	}
+
+	if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2)) {
+		ftmod_ss7_shutdown_mtp2();
+		sng_isup_free_mtp2();
+		sng_isup_free_mtp1();
+	}
+
+	ftmod_ss7_shutdown_relay();
+	sng_isup_free_relay();
+
+	sng_isup_free_sm();
+
+	sng_isup_free_gen();
 
 	ftdm_log (FTDM_LOG_INFO, "Finished ftmod_sangoma_ss7 unload!\n");
 	return FTDM_SUCCESS;
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
index f28547f..5272aa8 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
@@ -83,12 +83,6 @@ typedef enum {
 } sng_ckt_type_t;
 
 typedef enum {
-	CONFIGURED		= (1 << 0),
-	ACTIVE			= (1 << 1),
-	SNGSS7_PAUSED	= (1 << 7)
-} sng_flag_t;
-
-typedef enum {
 	SNGSS7_LPA_FOR_COT		= (1 << 0),	/* send LPA when COT arrives */
 	SNGSS7_ACM_OBCI_BITA	= (1 << 10)	/* in-band indication */
 } sng_intf_options_t;
@@ -98,84 +92,124 @@ typedef enum {
 	SNG_CALLING			= 2
 } sng_addr_type_t;
 
-typedef struct sng_mtp_link {
-	char			name[MAX_NAME_LEN];
-	uint32_t		id;
-	uint32_t		flags;
-	struct {
-		uint32_t	span;
-		uint32_t	chan;
-	} mtp1;
-	struct {
-		uint32_t	lssuLength;
-		uint32_t	errorType;
-		uint32_t	linkType;
-		uint32_t	mtp1Id;
-		uint32_t	t1;
-		uint32_t	t2;
-		uint32_t	t3;
-		uint32_t	t4n;
-		uint32_t	t4e;
-		uint32_t	t5;
-		uint32_t	t6;
-		uint32_t	t7;
-	} mtp2;
-	struct {
-		uint32_t	priority;
-		uint32_t	linkType;
-		uint32_t	switchType;
-		uint32_t	apc;
-		uint32_t	spc;
-		uint32_t	ssf;
-		uint32_t	slc;
-		uint32_t	linkSetId;
-		uint32_t	mtp2Id;
-		uint32_t	t1;
-		uint32_t	t2;
-		uint32_t	t3;
-		uint32_t	t4;
-		uint32_t	t5;
-		uint32_t	t6;
-		uint32_t	t7;
-		uint32_t	t8;
-		uint32_t	t9;
-		uint32_t	t10;
-		uint32_t	t11;
-		uint32_t	t12;
-		uint32_t	t13;
-		uint32_t	t14;
-		uint32_t	t15;
-		uint32_t	t16;
-		uint32_t	t17;
-		uint32_t	t18;
-		uint32_t	t19;
-		uint32_t	t20;
-		uint32_t	t21;
-		uint32_t	t22;
-		uint32_t	t23;
-		uint32_t	t24;
-		uint32_t	t25;
-		uint32_t	t27;
-		uint32_t	t28;
-		uint32_t	t29;
-		uint32_t	t30;
-		uint32_t	t31;
-		uint32_t	t32;
-		uint32_t	t33;
-		uint32_t	t34;
-		uint32_t	t35;
-		uint32_t	t36;
-		uint32_t	t37;
-		uint32_t	tcraft;
-		uint32_t	tflc;
-		uint32_t	tbnd;
-	} mtp3;
-} sng_mtp_link_t;
+typedef struct sng_mtp2_error_type {
+	int	init;
+	char sng_type[MAX_NAME_LEN];
+	uint32_t tril_type;
+} sng_mtp2_error_type_t;
+
+typedef struct sng_link_type {
+	int init;
+	char sng_type[MAX_NAME_LEN];
+	uint32_t tril_mtp2_type;
+	uint32_t tril_mtp3_type;
+} sng_link_type_t;
+
+typedef struct sng_switch_type {
+	int init;
+	char sng_type[MAX_NAME_LEN];
+	uint32_t tril_mtp3_type;
+	uint32_t tril_isup_type;
+} sng_switch_type_t;
+
+typedef struct sng_ssf_type {
+	int init;
+	char sng_type[MAX_NAME_LEN];
+	uint32_t tril_type;
+} sng_ssf_type_t;
+
+typedef struct sng_cic_cntrl_type {
+	int init;
+	char sng_type[MAX_NAME_LEN];
+	uint32_t tril_type;
+} sng_cic_cntrl_type_t;
+
+typedef struct sng_mtp1_link {
+	char		name[MAX_NAME_LEN];
+	uint32_t	flags;
+	uint32_t	id;
+	uint32_t	span;
+	uint32_t	chan;
+} sng_mtp1_link_t;
+
+typedef struct sng_mtp2_link {
+	char		name[MAX_NAME_LEN];
+	uint32_t	flags;
+	uint32_t	id;
+	uint32_t	lssuLength;
+	uint32_t	errorType;
+	uint32_t	linkType;
+	uint32_t	mtp1Id;
+	uint32_t	mtp1ProcId;
+	uint32_t	t1;
+	uint32_t	t2;
+	uint32_t	t3;
+	uint32_t	t4n;
+	uint32_t	t4e;
+	uint32_t	t5;
+	uint32_t	t6;
+	uint32_t	t7;
+} sng_mtp2_link_t;
+
+typedef struct sng_mtp3_link {
+	char		name[MAX_NAME_LEN];
+	uint32_t	flags;
+	uint32_t	id;
+	uint32_t	priority;
+	uint32_t	linkType;
+	uint32_t	switchType;
+	uint32_t	apc;
+	uint32_t	spc;
+	uint32_t	ssf;
+	uint32_t	slc;
+	uint32_t	linkSetId;
+	uint32_t	mtp2Id;
+	uint32_t	mtp2ProcId;
+	uint32_t	t1;
+	uint32_t	t2;
+	uint32_t	t3;
+	uint32_t	t4;
+	uint32_t	t5;
+	uint32_t	t6;
+	uint32_t	t7;
+	uint32_t	t8;
+	uint32_t	t9;
+	uint32_t	t10;
+	uint32_t	t11;
+	uint32_t	t12;
+	uint32_t	t13;
+	uint32_t	t14;
+	uint32_t	t15;
+	uint32_t	t16;
+	uint32_t	t17;
+	uint32_t	t18;
+	uint32_t	t19;
+	uint32_t	t20;
+	uint32_t	t21;
+	uint32_t	t22;
+	uint32_t	t23;
+	uint32_t	t24;
+	uint32_t	t25;
+	uint32_t	t27;
+	uint32_t	t28;
+	uint32_t	t29;
+	uint32_t	t30;
+	uint32_t	t31;
+	uint32_t	t32;
+	uint32_t	t33;
+	uint32_t	t34;
+	uint32_t	t35;
+	uint32_t	t36;
+	uint32_t	t37;
+	uint32_t	tcraft;
+	uint32_t	tflc;
+	uint32_t	tbnd;
+} sng_mtp3_link_t;
 
 typedef struct sng_link_set {
-	uint32_t		id;
 	char			name[MAX_NAME_LEN];
 	uint32_t		flags;
+	uint32_t		id;
 	uint32_t		apc;
 	uint32_t		linkType;
 	uint32_t		switchType;
@@ -186,9 +220,9 @@ typedef struct sng_link_set {
 } sng_link_set_t;
 
 typedef struct sng_route {
-	uint32_t		id;
 	char			name[MAX_NAME_LEN];
 	uint32_t		flags;
+	uint32_t		id;
 	uint32_t		dpc;
 	uint32_t		cmbLinkSetId;
 	uint32_t		linkSetId;
@@ -211,10 +245,10 @@ typedef struct sng_route {
 } sng_route_t;
 
 typedef struct sng_isup_intf {
-	uint32_t		id;
 	char			name[MAX_NAME_LEN];
 	uint32_t		options;
 	uint32_t		flags;
+	uint32_t		id;
 	uint32_t		spc;
 	uint32_t		dpc;
 	uint32_t		switchType;
@@ -222,9 +256,6 @@ typedef struct sng_isup_intf {
 	uint32_t		mtpRouteId;
 	uint32_t		ssf;
 	uint32_t		isap;
-	uint32_t		clg_nadi;
-	uint32_t		cld_nadi;
-	uint32_t		min_digits;
 	uint16_t		t4;
 	uint32_t		t10;
 	uint32_t		t11;
@@ -241,7 +272,6 @@ typedef struct sng_isup_intf {
 	uint32_t		t29;
 	uint32_t		t30;
 	uint32_t		t32;
-	uint32_t		t35;
 	uint32_t		t37;
 	uint32_t		t38;
 	uint32_t		t39;
@@ -251,15 +281,23 @@ typedef struct sng_isup_intf {
 } sng_isup_inf_t;
 
 typedef struct sng_isup_ckt {
-	uint32_t		id;
+	uint32_t		options;
 	uint32_t		flags;
+	uint32_t		ckt_flags;
+	uint32_t		procId;
+	uint32_t		id;
+	uint32_t		ccSpanId;
 	uint32_t		span;
 	uint32_t		chan;
 	uint32_t		type;	/* VOICE/SIG/HOLE */
 	uint32_t		cic;
 	uint32_t		infId;
-	uint32_t		ssf;
 	uint32_t		typeCntrl;
+	uint32_t		ssf;
+	uint32_t		switchType;
+	uint32_t		clg_nadi;
+	uint32_t		cld_nadi;
+	uint32_t		min_digits;
 	void			*obj;
 	uint16_t		t3;
 	uint16_t		t12;
@@ -268,12 +306,13 @@ typedef struct sng_isup_ckt {
 	uint16_t		t15;
 	uint16_t		t16;
 	uint16_t		t17;
+	uint32_t		t35;
 	uint16_t		tval;
 } sng_isup_ckt_t;
 
 typedef struct sng_nsap {
-	uint32_t		id;
 	uint32_t		flags;
+	uint32_t		id;
 	uint32_t		suId;
 	uint32_t		spId;
 	uint32_t		nwId;
@@ -311,15 +350,30 @@ typedef struct sng_isap {
 	uint32_t		tfnlrelrsp;
 } sng_isap_t;
 
+typedef struct sng_relay {
+	uint32_t		id;
+	char			name[MAX_NAME_LEN];
+	uint32_t		flags;
+	uint32_t		type;
+	uint32_t		port;
+	char			hostname[RY_REMHOSTNAME_SIZE];
+	uint32_t		procId;
+} sng_relay_t;
+
 typedef struct sng_ss7_cfg {
 	uint32_t			spc;
+	uint32_t			procId;
 	char				license[MAX_PATH];
 	char				signature[MAX_PATH];
-	sng_mtp_link_t		mtpLink[MAX_MTP_LINKS+1];
+	uint32_t			flags;
+	sng_relay_t			relay[MAX_RELAY_CHANNELS+1];
+	sng_mtp1_link_t		mtp1Link[MAX_MTP_LINKS+1];
+	sng_mtp2_link_t		mtp2Link[MAX_MTP_LINKS+1];
+	sng_mtp3_link_t		mtp3Link[MAX_MTP_LINKS+1];
 	sng_link_set_t		mtpLinkSet[MAX_MTP_LINKSETS+1];
 	sng_route_t			mtpRoute[MAX_MTP_ROUTES+1];
 	sng_isup_inf_t		isupIntf[MAX_ISUP_INFS+1];
-	sng_isup_ckt_t		isupCkt[MAX_ISUP_CKTS+1];
+	sng_isup_ckt_t		isupCkt[10000]; 	/* KONRAD - only need 2000 ( and 0-1000 aren't used) since other servers are registerd else where */
 	sng_nsap_t			nsap[MAX_NSAPS+1];
 	sng_isap_t			isap[MAX_ISAPS+1];	
 }sng_ss7_cfg_t;
@@ -365,7 +419,7 @@ typedef struct sngss7_chan_data {
 	uint32_t				spInstId;
 	uint32_t				spId;
 	uint8_t					globalFlg;
-	uint32_t				flags;
+	uint32_t				ckt_flags;
 	sngss7_glare_data_t		glare;
 	sngss7_timer_data_t		t35;
 }sngss7_chan_data_t;
@@ -407,8 +461,6 @@ typedef struct sngss7_event_data
 } sngss7_event_data_t;
 
 
-
-
 typedef enum {
 	FLAG_RESET_RX			= (1 << 0),
 	FLAG_RESET_TX			= (1 << 1),
@@ -439,15 +491,39 @@ typedef enum {
 	FLAG_GRP_MN_BLOCK_RX	= (1 << 26),
 	FLAG_GRP_MN_BLOCK_TX	= (1 << 27),
 	FLAG_GRP_HW_UNBLK_TX	= (1 << 28),
-	FLAG_GRP_MN_UNBLK_TX	= (1 << 29)
-} flag_t;
+	FLAG_GRP_MN_UNBLK_TX	= (1 << 29),
+	FLAG_RELAY_DOWN			= (1 << 30)
+} sng_ckt_flag_t;
+
+/* valid for every cfg array except circuits */
+typedef enum {
+	SNGSS7_CONFIGURED		= (1 << 0),
+	SNGSS7_ACTIVE			= (1 << 1),
+	SNGSS7_RELAY_INIT		= (1 << 3),
+	SNGSS7_PAUSED			= (1 << 7) /* for isup interfaces */
+} sng_cfg_flag_t;
+
+typedef enum {
+	SNGSS7_SM		= (1 << 0),
+	SNGSS7_RY		= (1 << 1),
+	SNGSS7_MTP1		= (1 << 2),
+	SNGSS7_MTP2		= (1 << 3),
+	SNGSS7_MTP3		= (1 << 4),
+	SNGSS7_ISUP		= (1 << 5),
+	SNGSS7_CC		= (1 << 6)
+} sng_task_flag_t;
 /******************************************************************************/
 
 /* GLOBALS ********************************************************************/
-extern ftdm_sngss7_data_t   g_ftdm_sngss7_data;
-extern uint32_t			 sngss7_id;
-extern ftdm_sched_t		 *sngss7_sched;
-extern int				cmbLinkSetId;
+extern ftdm_sngss7_data_t		g_ftdm_sngss7_data;
+extern sng_ssf_type_t			sng_ssf_type_map[];
+extern sng_switch_type_t		sng_switch_type_map[];
+extern sng_link_type_t			sng_link_type_map[];
+extern sng_mtp2_error_type_t	sng_mtp2_error_type_map[];
+extern sng_cic_cntrl_type_t 	sng_cic_cntrl_type_map[];
+extern uint32_t					sngss7_id;
+extern ftdm_sched_t				*sngss7_sched;
+extern int						cmbLinkSetId;
 /******************************************************************************/
 
 /* PROTOTYPES *****************************************************************/
@@ -461,6 +537,12 @@ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta);
 void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta);
 void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta);
 void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta);
+void handle_sng_relay_alarm(Pst *pst, RyMngmt *sta);
+
+/* in ftmod_sangoma_ss7_relay.c */
+ftdm_status_t handle_relay_connect(RyMngmt *sta);
+ftdm_status_t handle_relay_disconnect_on_down(RyMngmt *sta);
+ftdm_status_t handle_relay_disconnect_on_error(RyMngmt *sta);
 
 /* in ftmod_sangoma_ss7_cfg.c */
 int ft_to_sngss7_cfg_all(void);
@@ -484,20 +566,36 @@ int ftmod_ss7_cc_isap_config(int id);
 /* in ftmod_sangoma_ss7_cntrl.c */
 int  ft_to_sngss7_activate_all(void);
 
-int ftmod_ss7_inhibit_mtplink(uint32_t id);
-int ftmod_ss7_uninhibit_mtplink(uint32_t id);
-int ftmod_ss7_activate_mtplink(uint32_t id);
-int ftmod_ss7_deactivate_mtplink(uint32_t id);
-int ftmod_ss7_deactivate2_mtplink(uint32_t id);
+int ftmod_ss7_inhibit_mtp3link(uint32_t id);
+int ftmod_ss7_uninhibit_mtp3link(uint32_t id);
+int ftmod_ss7_bind_mtp3link(uint32_t id);
+int ftmod_ss7_unbind_mtp3link(uint32_t id);
+int ftmod_ss7_activate_mtp3link(uint32_t id);
+int ftmod_ss7_deactivate_mtp3link(uint32_t id);
+int ftmod_ss7_deactivate2_mtp3link(uint32_t id);
 int ftmod_ss7_activate_mtplinkSet(uint32_t id);
 int ftmod_ss7_deactivate_mtplinkSet(uint32_t id);
 int ftmod_ss7_deactivate2_mtplinkSet(uint32_t id);
-int ftmod_ss7_lpo_mtplink(uint32_t id);
-int ftmod_ss7_lpr_mtplink(uint32_t id);
+int ftmod_ss7_lpo_mtp3link(uint32_t id);
+int ftmod_ss7_lpr_mtp3link(uint32_t id);
+
+int ftmod_ss7_shutdown_isup(void);
+int ftmod_ss7_shutdown_mtp3(void);
+int ftmod_ss7_shutdown_mtp2(void);
+int ftmod_ss7_shutdown_relay(void);
+
+int ftmod_ss7_disable_grp_mtp3Link(uint32_t procId);
+int ftmod_ss7_enable_grp_mtp3Link(uint32_t procId);
+
+int ftmod_ss7_disable_grp_mtp2Link(uint32_t procId);
 
 /* in ftmod_sangoma_ss7_sta.c */
-int ftmod_ss7_mtplink_sta(uint32_t id, SnMngmt *cfm);
+int ftmod_ss7_mtp1link_sta(uint32_t id, L1Mngmt *cfm);
+int ftmod_ss7_mtp2link_sta(uint32_t id, SdMngmt *cfm);
+int ftmod_ss7_mtp3link_sta(uint32_t id, SnMngmt *cfm);
 int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm);
+int ftmod_ss7_isup_intf_sta(uint32_t id, uint8_t *status);
+int ftmod_ss7_relay_status(uint32_t id, RyMngmt *cfm);
 
 
 /* in ftmod_sangoma_ss7_out.c */
@@ -607,6 +705,14 @@ ftdm_status_t clear_tx_grs_data(sngss7_chan_data_t *sngss7_info);
 ftdm_status_t encode_subAddrIE_nsap(const char *subAddr, char *subAddrIE, int type);
 ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int type);
 
+int find_mtp2_error_type_in_map(const char *err_type);
+int find_link_type_in_map(const char *linkType);
+int find_switch_type_in_map(const char *switchType);
+int find_ssf_type_in_map(const char *ssfType);
+int find_cic_cntrl_in_map(const char *cntrlType);
+
+ftdm_status_t check_status_of_all_isup_intf(void);
+
 /* in ftmod_sangoma_ss7_timers.c */
 void handle_isup_t35(void *userdata);
 /******************************************************************************/
@@ -739,6 +845,10 @@ void handle_isup_t35(void *userdata);
 #define sngss7_clear_flag(obj, flag) ((obj)->flags &= ~(flag))
 #define sngss7_set_flag(obj, flag)   ((obj)->flags |= (flag))
 
+#define sngss7_test_ckt_flag(obj, flag)  ((obj)->ckt_flags & flag)
+#define sngss7_clear_ckt_flag(obj, flag) ((obj)->ckt_flags &= ~(flag))
+#define sngss7_set_ckt_flag(obj, flag)   ((obj)->ckt_flags |= (flag))
+
 #define sngss7_test_options(obj, option) ((obj)->options & option)
 #define sngss7_clear_options(obj, option) ((obj)->options &= ~(option))
 #define sngss7_set_options(obj, option)   ((obj)->options |= (option))
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c
index ec8d7df..06b0b21 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c
@@ -125,9 +125,9 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
 	iam.txMedReq.trMedReq.pres 			= PRSNT_NODEF;
 	iam.txMedReq.trMedReq.val 			= ftdmchan->caller_data.bearer_capability;
 
-	if ((g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].switchType == LSI_SW_ANS88) ||
-		(g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].switchType == LSI_SW_ANS92) ||
-		(g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].switchType == LSI_SW_ANS95)) {
+	if ((g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS88) ||
+		(g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS92) ||
+		(g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS95)) {
 
 		/* include only if we're running ANSI */
 		iam.fwdCallInd.transCallNInd.pres   = PRSNT_NODEF;
@@ -178,7 +178,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
 		iam.usrServInfoA.rateMultiplier.pres	= PRSNT_NODEF;
 		iam.usrServInfoA.rateMultiplier.val		= 0x1;				/* 1x rate multipler */
 	} /* if ANSI */
-	
+
 	/* copy down the called number information */
 	copy_cdPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cdPtyNum);
 	
@@ -192,7 +192,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
 		SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Calling NADI value \"%s\"\n", clg_nadi);
 		iam.cgPtyNum.natAddrInd.val	= atoi(clg_nadi);
 	} else {
-		iam.cgPtyNum.natAddrInd.val	= g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].clg_nadi;
+		iam.cgPtyNum.natAddrInd.val	= g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].clg_nadi;
 		SS7_DEBUG_CHAN(ftdmchan,"No user supplied NADI value found for CLG, using \"%d\"\n", iam.cgPtyNum.natAddrInd.val);
 	}
 
@@ -201,7 +201,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
 		SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Called NADI value \"%s\"\n", cld_nadi);
 		iam.cdPtyNum.natAddrInd.val	= atoi(cld_nadi);
 	} else {
-		iam.cdPtyNum.natAddrInd.val	= g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].cld_nadi;
+		iam.cdPtyNum.natAddrInd.val	= g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].cld_nadi;
 		SS7_DEBUG_CHAN(ftdmchan,"No user supplied NADI value found for CLD, using \"%d\"\n", iam.cdPtyNum.natAddrInd.val);
 	}
 
@@ -310,7 +310,6 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
 	SS7_FUNC_TRACE_ENTER (__FUNCTION__);
 	
 	sngss7_chan_data_t	*sngss7_info = ftdmchan->call_data;
-	sng_isup_inf_t		*isup_intf =  &g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId];
 	SiCnStEvnt acm;
 	
 	memset (&acm, 0x0, sizeof (acm));
@@ -360,8 +359,8 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
 	acm.bckCallInd.sccpMethInd.val		= SCCPMTH_NOIND;
 
 	/* fill in any optional parameters */
-	if (sngss7_test_options(isup_intf, SNGSS7_ACM_OBCI_BITA)) {
-		SS7_DEBUG_CHAN(ftdmchan, "Found ACM_OBCI_BITA flag:0x%X\n", isup_intf->options);
+	if (sngss7_test_options(&g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id], SNGSS7_ACM_OBCI_BITA)) {
+		SS7_DEBUG_CHAN(ftdmchan, "Found ACM_OBCI_BITA flag:0x%X\n", g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].options);
 		acm.optBckCalInd.eh.pres				= PRSNT_NODEF;
 		acm.optBckCalInd.inbndInfoInd.pres		= PRSNT_NODEF;
 		acm.optBckCalInd.inbndInfoInd.val		= 0x1;
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_relay.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_relay.c
new file mode 100644
index 0000000..05ea69e
--- /dev/null
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_relay.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2009|Konrad Hammel <konrad@sangoma.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms|with or without
+ * modification|are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice|this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice|this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT
+ * LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL,
+ * EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* INCLUDE ********************************************************************/
+#include "ftmod_sangoma_ss7_main.h"
+/******************************************************************************/
+
+/* DEFINES ********************************************************************/
+/******************************************************************************/
+
+/* GLOBALS ********************************************************************/
+/******************************************************************************/
+
+/* PROTOTYPES *****************************************************************/
+ftdm_status_t handle_relay_connect(RyMngmt *sta);
+ftdm_status_t handle_relay_disconnect(RyMngmt *sta);
+
+static ftdm_status_t enable_all_ckts_for_relay(void);
+static ftdm_status_t reconfig_all_ckts_for_relay(void);
+static ftdm_status_t disable_all_ckts_for_relay(void);
+static ftdm_status_t block_all_ckts_for_relay(uint32_t procId);
+static ftdm_status_t disable_all_sigs_for_relay(uint32_t procId);
+static ftdm_status_t disble_all_mtp2_sigs_for_relay(void);
+/******************************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+ftdm_status_t handle_relay_connect(RyMngmt *sta)
+{
+	sng_relay_t	*sng_relay = &g_ftdm_sngss7_data.cfg.relay[sta->t.usta.s.ryUpUsta.id];
+
+
+	/* test if this is the first time the channel comes up */
+	if (!sngss7_test_flag(sng_relay, SNGSS7_RELAY_INIT)) {
+		SS7_DEBUG("Relay Channel %d initial connection UP\n", sng_relay->id);
+
+		/* mark the channel as being up */
+		sngss7_set_flag(sng_relay, SNGSS7_RELAY_INIT);
+	} else {
+		SS7_DEBUG("Relay Channel %d connection UP\n", sng_relay->id);
+
+		/* react based on type of channel */
+		switch (sng_relay->type) {
+		/******************************************************************/
+		case (LRY_CT_TCP_CLIENT):
+			/* reconfigure all ISUP ckts, since the main system would have lost all configs */
+			if (reconfig_all_ckts_for_relay()) {
+				SS7_ERROR("Failed to reconfigure ISUP Ckts!\n");
+
+				/* we're done....this is very bad! */
+			} else {				
+				enable_all_ckts_for_relay();
+			}
+
+			break;
+		/******************************************************************/
+		case (LRY_CT_TCP_SERVER):
+			/*unblock_all_ckts_for_relay(sta->t.usta.s.ryErrUsta.errPid);*/
+			ftmod_ss7_enable_grp_mtp3Link(sta->t.usta.s.ryUpUsta.id);
+
+			break;
+		/******************************************************************/
+		default:
+			break;
+		/******************************************************************/
+		} /* switch (g_ftdm_sngss7_data.cfg.relay[sta->t.usta.s.ryUpUsta.id].type) */
+	} /* intial up? */
+
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+ftdm_status_t handle_relay_disconnect_on_error(RyMngmt *sta)
+{
+
+	/* check which procId is in error, if it is 1, disable the ckts */
+	if (sta->t.usta.s.ryErrUsta.errPid == 1 ) {
+		disable_all_ckts_for_relay();
+
+		disble_all_mtp2_sigs_for_relay();
+	}
+
+	/* check if the channel is a server, means we just lost a MGW */
+	if (g_ftdm_sngss7_data.cfg.relay[sta->t.usta.s.ryErrUsta.errPid].type == LRY_CT_TCP_SERVER) {
+		block_all_ckts_for_relay(sta->t.usta.s.ryErrUsta.errPid);
+
+		disable_all_sigs_for_relay(sta->t.usta.s.ryErrUsta.errPid);
+	}
+
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+ftdm_status_t handle_relay_disconnect_on_down(RyMngmt *sta)
+{
+
+	/* check if the channel is a server, means we just lost a MGW */
+	if (g_ftdm_sngss7_data.cfg.relay[sta->t.usta.s.ryUpUsta.id].type == LRY_CT_TCP_SERVER) {
+		block_all_ckts_for_relay(sta->t.usta.s.ryUpUsta.id);
+
+		disable_all_sigs_for_relay(sta->t.usta.s.ryUpUsta.id);
+	}
+
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+ftdm_status_t disable_all_ckts_for_relay(void)
+{
+	sngss7_chan_data_t	*sngss7_info = NULL;
+	ftdm_channel_t		*ftdmchan = NULL;
+	int					x;	
+
+	SS7_INFO("Disabling all ckts becuase of Relay loss\n");
+
+	x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
+	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+	/**********************************************************************/
+		/* make sure this is voice channel */
+		if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
+	
+			/* get the ftdmchan and ss7_chan_data from the circuit */
+			if (extract_chan_data(g_ftdm_sngss7_data.cfg.isupCkt[x].id, &sngss7_info, &ftdmchan)) {
+				SS7_ERROR("Failed to extract channel data for circuit = %d!\n", g_ftdm_sngss7_data.cfg.isupCkt[x].id);
+				x++;
+				continue;
+			}
+
+			/* throw the relay_down flag */
+			sngss7_set_ckt_flag(sngss7_info, FLAG_RELAY_DOWN);
+
+			/* throw the channel infId status flags to PAUSED ... they will be executed next process cycle */
+			sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_RESUME);
+			sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_PAUSED);
+		} /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) */
+
+		/* move along */
+		x++;
+	/**********************************************************************/
+	} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */
+
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+ftdm_status_t enable_all_ckts_for_relay(void)
+{
+	sngss7_chan_data_t	*sngss7_info = NULL;
+	sng_isup_inf_t		*sngIntf = NULL;
+	ftdm_channel_t		*ftdmchan = NULL;
+	int					x;
+
+	SS7_INFO("Enabling all ckts becuase of Relay connection\n");
+
+	x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
+	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+	/**********************************************************************/
+		/* make sure this is voice channel */
+		if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
+	
+			/* get the ftdmchan and ss7_chan_data from the circuit */
+			if (extract_chan_data(g_ftdm_sngss7_data.cfg.isupCkt[x].id, &sngss7_info, &ftdmchan)) {
+				SS7_ERROR("Failed to extract channel data for circuit = %d!\n", g_ftdm_sngss7_data.cfg.isupCkt[x].id);
+				x++;
+				continue;
+			}
+
+			/* bring the relay_down flag down */
+			sngss7_clear_ckt_flag(sngss7_info, FLAG_RELAY_DOWN);
+
+			sngIntf = &g_ftdm_sngss7_data.cfg.isupIntf[g_ftdm_sngss7_data.cfg.isupCkt[x].infId];
+
+			/* check if the interface is paused or resumed */
+			if (sngss7_test_flag(sngIntf, SNGSS7_PAUSED)) {
+				/* don't bring the channel resume flag up...the interface is down */
+				SS7_DEBUG_CHAN(ftdmchan, "ISUP interface (%d) set to paused, not resuming channel\n", sngIntf->id);
+			} else {
+				SS7_DEBUG_CHAN(ftdmchan, "ISUP interface (%d) set to resume, resuming channel\n", sngIntf->id);
+				/* throw the channel infId status flags to PAUSED ... they will be executed next process cycle */
+				sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_RESUME);
+				sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_PAUSED);
+			}
+		} /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) */
+
+		/* move along */
+		x++;
+	/**********************************************************************/
+	} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */
+
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+ftdm_status_t reconfig_all_ckts_for_relay(void)
+{
+#if 1
+	int x;
+	int ret;
+
+	x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
+	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+		if ( g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
+	
+			ret = ftmod_ss7_isup_ckt_config(x);
+			if (ret) {
+				SS7_CRITICAL("ISUP CKT %d configuration FAILED (%d)!\n", x, ret);
+				return 1;
+			} else {
+				SS7_INFO("ISUP CKT %d configuration DONE!\n", x);
+			}
+
+		} /* if ( g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) */
+
+		/* set the SNGSS7_CONFIGURED flag */
+		g_ftdm_sngss7_data.cfg.isupCkt[x].flags |= SNGSS7_CONFIGURED;
+		
+		x++;
+	} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */
+#endif
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+ftdm_status_t block_all_ckts_for_relay(uint32_t procId)
+{
+	int x;
+
+	SS7_INFO("BLOcking all ckts on ProcID = %d\n", procId);
+
+	/* we just lost connection to this procId, send out a block for all these circuits */
+	x = (procId * 1000) + 1;
+	while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+	/**************************************************************************/
+		if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
+			/* send out a BLO */
+			sng_cc_sta_request (1,
+								0,
+								0,
+								g_ftdm_sngss7_data.cfg.isupCkt[x].id,
+								0, 
+								SIT_STA_CIRBLOREQ, 
+								NULL);
+
+		} /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) */
+
+		/* move along */
+		x++;
+	/**************************************************************************/
+	} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */
+
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+ftdm_status_t disable_all_sigs_for_relay(uint32_t procId)
+{
+	SS7_INFO("Disalbing all sig links on ProcID = %d\n", procId);
+
+	ftmod_ss7_disable_grp_mtp3Link(procId);
+	
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+ftdm_status_t disble_all_mtp2_sigs_for_relay(void)
+{
+	/* check if there is a local mtp2 link*/
+	if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2)) {
+		SS7_INFO("Disalbing all mtp2 sig links on local system\n");
+
+		ftmod_ss7_disable_grp_mtp2Link(1);
+	}
+
+	return FTDM_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/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c
index 1235238..2f507a2 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c
@@ -42,12 +42,43 @@
 /******************************************************************************/
 
 /* PROTOTYPES *****************************************************************/
-int ftmod_ss7_mtplink_sta(uint32_t id, SnMngmt *cfm);
+int ftmod_ss7_mtp1link_sta(uint32_t id, L1Mngmt *cfm);
+int ftmod_ss7_mtp2link_sta(uint32_t id, SdMngmt *cfm);
+int ftmod_ss7_mtp3link_sta(uint32_t id, SnMngmt *cfm);
 int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm);
+int ftmod_ss7_isup_intf_sta(uint32_t id, uint8_t *status);
+int ftmod_ss7_relay_status(uint32_t id, RyMngmt *cfm);
 /******************************************************************************/
 
 /* FUNCTIONS ******************************************************************/
-int ftmod_ss7_mtplink_sta(uint32_t id, SnMngmt *cfm)
+int ftmod_ss7_mtp1link_sta(uint32_t id, L1Mngmt *cfm)
+{
+
+	return 1;
+}
+
+/******************************************************************************/
+int ftmod_ss7_mtp2link_sta(uint32_t id, SdMngmt *cfm)
+{
+	SdMngmt	sta;
+	Pst		pst;
+
+	memset(&sta, 0x0, sizeof(sta));
+
+	/* initalize the post structure */
+	smPstInit(&pst);
+
+	/* insert the destination Entity */
+	pst.dstEnt = ENTSD;
+
+	sta.hdr.elmId.elmnt 		= STDLSAP;
+	sta.hdr.elmId.elmntInst1	= g_ftdm_sngss7_data.cfg.mtp2Link[id].id;
+
+	return(sng_sta_mtp2(&pst, &sta, cfm));
+}
+
+/******************************************************************************/
+int ftmod_ss7_mtp3link_sta(uint32_t id, SnMngmt *cfm)
 {
 	SnMngmt	sta;
 	Pst		pst;
@@ -60,8 +91,13 @@ int ftmod_ss7_mtplink_sta(uint32_t id, SnMngmt *cfm)
 	/* insert the destination Entity */
 	pst.dstEnt = ENTSN;
 
+	/* check the for the correct ProcId and make sure it goes to the right system */
+	if (g_ftdm_sngss7_data.cfg.procId != 1) {
+		pst.dstProcId = 1;
+	}
+
 	sta.hdr.elmId.elmnt 		= STDLSAP;
-	sta.hdr.elmId.elmntInst1	= g_ftdm_sngss7_data.cfg.mtpLink[id].id;
+	sta.hdr.elmId.elmntInst1	= g_ftdm_sngss7_data.cfg.mtp3Link[id].id;
 
 	return(sng_sta_mtp3(&pst, &sta, cfm));
 }
@@ -80,13 +116,77 @@ int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm)
 	/* insert the destination Entity */
 	pst.dstEnt = ENTSN;
 
+	/* check the for the correct ProcId and make sure it goes to the right system */
+	if (g_ftdm_sngss7_data.cfg.procId != 1) {
+		pst.dstProcId = 1;
+	}
+
 	sta.hdr.elmId.elmnt 		= STLNKSET;
 	sta.hdr.elmId.elmntInst1	= g_ftdm_sngss7_data.cfg.mtpLinkSet[id].id;
 	sta.hdr.elmId.elmntInst2	= g_ftdm_sngss7_data.cfg.mtpLinkSet[id].links[0];
 
 	return(sng_sta_mtp3(&pst, &sta, cfm));
 }
+
+/******************************************************************************/
+int ftmod_ss7_isup_intf_sta(uint32_t id, uint8_t *status)
+{
+	SiMngmt	sta;
+	SiMngmt cfm;
+	Pst		pst;
+	int		ret;
+
+	memset(&sta, 0x0, sizeof(sta));
+
+	/* initalize the post structure */
+	smPstInit(&pst);
+
+	/* insert the destination Entity */
+	pst.dstEnt = ENTSI;
+
+	/* check the for the correct ProcId and make sure it goes to the right system */
+	if (g_ftdm_sngss7_data.cfg.procId != 1) {
+		pst.dstProcId = 1;
+	}
+
+	/* request the status of an inftId */
+	sta.hdr.entId.ent			= ENTSI;
+	sta.hdr.entId.inst			= S_INST;
+	sta.hdr.msgType				= TSSTA;
+	sta.hdr.elmId.elmnt 		= SI_STINTF;
+
+	sta.t.ssta.elmntId.intfId = id;
+
+	ret = sng_sta_isup(&pst, &sta, &cfm);
+
+	*status = cfm.t.ssta.cfm.s.intf.state;
+
+	return(ret);
+}
+
 /******************************************************************************/
+int ftmod_ss7_relay_status(uint32_t id, RyMngmt *cfm)
+{
+	RyMngmt	sta;
+	Pst		pst;
+
+	memset(&sta, 0x0, sizeof(sta));
+
+	/* initalize the post structure */
+	smPstInit(&pst);
+
+	/* insert the destination Entity */
+	pst.dstEnt = ENTRY;
+
+	sta.hdr.entId.ent			= ENTRY;
+	sta.hdr.entId.inst			= S_INST;
+	sta.hdr.msgType				= TSSTA;
+	sta.hdr.elmId.elmnt 		= STCHSTA;
+	sta.hdr.elmId.elmntInst1	= id;
+
+
+	return(sng_sta_relay(&pst, &sta, cfm));
+}
 
 /******************************************************************************/
 /* For Emacs:
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c
index 23617c9..683caf2 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c
@@ -75,6 +75,14 @@ ftdm_status_t clear_tx_grs_data(sngss7_chan_data_t *sngss7_info);
 
 ftdm_status_t encode_subAddrIE_nsap(const char *subAddr, char *subAddrIE, int type);
 ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int type);
+
+int find_mtp2_error_type_in_map(const char *err_type);
+int find_link_type_in_map(const char *linkType);
+int find_switch_type_in_map(const char *switchType);
+int find_ssf_type_in_map(const char *ssfType);
+int find_cic_cntrl_in_map(const char *cntrlType);
+
+ftdm_status_t check_status_of_all_isup_intf(void);
 /******************************************************************************/
 
 /* FUNCTIONS ******************************************************************/
@@ -432,7 +440,7 @@ int check_cics_in_range(sngss7_chan_data_t *sngss7_info)
 			}
 
 			/* check if the channel still has the reset flag done is up */
-			if (!sngss7_test_flag(tmp_sngss7_info, FLAG_GRP_RESET_RX_DN)) {
+			if (!sngss7_test_ckt_flag(tmp_sngss7_info, FLAG_GRP_RESET_RX_DN)) {
 				SS7_DEBUG_CHAN(tmp_ftdmchan, "[CIC:%d] Still processing reset...\n", tmp_sngss7_info->circuit->cic);
 				return 0;
 			}
@@ -475,19 +483,19 @@ ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_in
 int check_for_reset(sngss7_chan_data_t *sngss7_info)
 {
 
-	if (sngss7_test_flag(sngss7_info,FLAG_RESET_RX)) {
+	if (sngss7_test_ckt_flag(sngss7_info,FLAG_RESET_RX)) {
 		return 1;
 	}
 	
-	if (sngss7_test_flag(sngss7_info,FLAG_RESET_TX)) {
+	if (sngss7_test_ckt_flag(sngss7_info,FLAG_RESET_TX)) {
 		return 1;
 	}
 	
-	if (sngss7_test_flag(sngss7_info,FLAG_GRP_RESET_RX)) {
+	if (sngss7_test_ckt_flag(sngss7_info,FLAG_GRP_RESET_RX)) {
 		return 1;
 	}
 	
-	if (sngss7_test_flag(sngss7_info,FLAG_GRP_RESET_TX)) {
+	if (sngss7_test_ckt_flag(sngss7_info,FLAG_GRP_RESET_TX)) {
 		return 1;
 	}
 
@@ -498,11 +506,13 @@ int check_for_reset(sngss7_chan_data_t *sngss7_info)
 /******************************************************************************/
 unsigned long get_unique_id(void)
 {
+	int	procId = sng_get_procId(); 
 
-	if (sngss7_id < 420000000) {
+	/* id values are between (procId * 1,000,000) and ((procId + 1) * 1,000,000) */ 
+	if (sngss7_id < ((procId + 1) * 1000000) ) {
 		sngss7_id++;
 	} else {
-		sngss7_id = 1;
+		sngss7_id = procId * 1000000;
 	}
 
 	return(sngss7_id);
@@ -525,7 +535,7 @@ ftdm_status_t check_if_rx_grs_started(ftdm_span_t *ftdmspan)
 		}
 
 		/* check if the GRP_RESET_RX flag is already up */
-		if (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX)) {
+		if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX)) {
 			/* we have already processed this channel...move along */
 			continue;
 		}
@@ -543,7 +553,7 @@ ftdm_status_t check_if_rx_grs_started(ftdm_span_t *ftdmspan)
 				(g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_grs.circuit].cic + sngss7_span->rx_grs.range));
 
 		/* flag the channel as having received a reset */
-		sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX);
+		sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX);
 
 		switch (ftdmchan->state) {
 		/**************************************************************************/
@@ -598,10 +608,10 @@ ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan)
 		/* check if there is a state change pending on the channel */
 		if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
 			/* check the state to the GRP_RESET_RX_DN flag */
-			if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) {
+			if (!sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) {
 				/* this channel is still resetting...do nothing */
 					goto GRS_UNLOCK_ALL;
-			} /* if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) */
+			} /* if (!sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) */
 		} else {
 			/* state change pending */
 			goto GRS_UNLOCK_ALL;
@@ -625,16 +635,16 @@ ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan)
 		}
 
 		/* throw the GRP reset flag complete flag */
-		sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT);
+		sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT);
 
 		/* move the channel to the down state */
 		ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
 
 		/* update the status map if the ckt is in blocked state */
-		if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) ||
-			(sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) ||
-			(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) ||
-			(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) {
+		if ((sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) ||
+			(sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) ||
+			(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) ||
+			(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) {
 		
 			sngss7_span->rx_grs.status[byte] = (sngss7_span->rx_grs.status[byte] | (1 << bit));
 		} /* if blocked */
@@ -679,7 +689,7 @@ ftdm_status_t check_if_rx_gra_started(ftdm_span_t *ftdmspan)
 		}
 
 		/* check if the channel is already procoessing the GRA */
-		if (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) {
+		if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) {
 			/* move along */
 			continue;
 		}
@@ -701,7 +711,7 @@ ftdm_status_t check_if_rx_gra_started(ftdm_span_t *ftdmspan)
 		case FTDM_CHANNEL_STATE_RESTART:
 			
 			/* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */
-			sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
+			sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
 
 			/* go to DOWN */
 			ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
@@ -720,7 +730,7 @@ ftdm_status_t check_if_rx_gra_started(ftdm_span_t *ftdmspan)
 		case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
 			
 			/* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */
-			sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
+			sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
 
 			break;
 		/**********************************************************************/
@@ -775,7 +785,7 @@ ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan)
 		sigev.channel = ftdmchan;
 
 		/* if we have the PAUSED flag and the sig status is still UP */
-		if ((sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED)) &&
+		if ((sngss7_test_ckt_flag(sngss7_info, FLAG_INFID_PAUSED)) &&
 			(ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP))) {
 
 			/* clear up any pending state changes */
@@ -790,7 +800,7 @@ ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan)
 
 		/* if the RESUME flag is up go to SUSPENDED to process the flag */
 		/* after doing this the flag will be cleared */
-		if (sngss7_test_flag(sngss7_info, FLAG_INFID_RESUME)) {
+		if (sngss7_test_ckt_flag(sngss7_info, FLAG_INFID_RESUME)) {
 
 			/* clear up any pending state changes */
 			while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
@@ -839,7 +849,7 @@ ftdm_status_t process_span_ucic(ftdm_span_t *ftdmspan)
 		}
 
 		/* throw the ckt block flag */
-		sngss7_set_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK);
+		sngss7_set_ckt_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK);
 
 		/* set the channel to suspended state */
 		ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
@@ -858,9 +868,9 @@ ftdm_status_t process_span_ucic(ftdm_span_t *ftdmspan)
 ftdm_status_t clear_rx_grs_flags(sngss7_chan_data_t *sngss7_info)
 {
 	/* clear all the flags related to an incoming GRS */
-	sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_RX);
-	sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_RX_DN);
-	sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT);
+	sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX);
+	sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_DN);
+	sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT);
 
 	return FTDM_SUCCESS;
 }
@@ -892,10 +902,10 @@ ftdm_status_t clear_rx_gra_data(sngss7_chan_data_t *sngss7_info)
 ftdm_status_t clear_tx_grs_flags(sngss7_chan_data_t *sngss7_info)
 {
 	/* clear all the flags related to an outgoing GRS */
-	sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_BASE);
-	sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_TX);
-	sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_SENT);
-	sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
+	sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_RESET_BASE);
+	sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX);
+	sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_RESET_SENT);
+	sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
 
 	return FTDM_SUCCESS;
 }
@@ -918,7 +928,7 @@ ftdm_status_t clear_tx_grs_data(sngss7_chan_data_t *sngss7_info)
 ftdm_status_t clear_rx_rsc_flags(sngss7_chan_data_t *sngss7_info)
 {
 	/* clear all the flags related to an incoming RSC */
-	sngss7_clear_flag(sngss7_info, FLAG_RESET_RX);
+	sngss7_clear_ckt_flag(sngss7_info, FLAG_RESET_RX);
 
 	return FTDM_SUCCESS;
 }
@@ -927,9 +937,9 @@ ftdm_status_t clear_rx_rsc_flags(sngss7_chan_data_t *sngss7_info)
 ftdm_status_t clear_tx_rsc_flags(sngss7_chan_data_t *sngss7_info)
 {
 	/* clear all the flags related to an outgoing RSC */
-	sngss7_clear_flag(sngss7_info, FLAG_RESET_TX);
-	sngss7_clear_flag(sngss7_info, FLAG_RESET_SENT);
-	sngss7_clear_flag(sngss7_info, FLAG_RESET_TX_RSP);
+	sngss7_clear_ckt_flag(sngss7_info, FLAG_RESET_TX);
+	sngss7_clear_ckt_flag(sngss7_info, FLAG_RESET_SENT);
+	sngss7_clear_ckt_flag(sngss7_info, FLAG_RESET_TX_RSP);
 
 	return FTDM_SUCCESS;
 }
@@ -1148,6 +1158,197 @@ ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int typ
 }
 
 /******************************************************************************/
+int find_mtp2_error_type_in_map(const char *err_type)
+{
+	int i = 0;
+
+	while (sng_mtp2_error_type_map[i].init == 1) {
+		/* check if string matches the sng_type name */ 
+		if (!strcasecmp(err_type, sng_mtp2_error_type_map[i].sng_type)) {
+			/* we've found a match break from the loop */
+			break;
+		} else {
+			/* move on to the next on */
+			i++;
+		}
+	} /* while (sng_mtp2_error_type_map[i].init == 1) */
+
+	/* check how we exited the loop */
+	if (sng_mtp2_error_type_map[i].init == 0) {
+		return -1;
+	} else {
+		return i;
+	} /* if (sng_mtp2_error_type_map[i].init == 0) */
+}
+
+/******************************************************************************/
+int find_link_type_in_map(const char *linkType)
+{
+	int i = 0;
+
+	while (sng_link_type_map[i].init == 1) {
+		/* check if string matches the sng_type name */ 
+		if (!strcasecmp(linkType, sng_link_type_map[i].sng_type)) {
+			/* we've found a match break from the loop */
+			break;
+		} else {
+			/* move on to the next on */
+			i++;
+		}
+	} /* while (sng_link_type_map[i].init == 1) */
+
+	/* check how we exited the loop */
+	if (sng_link_type_map[i].init == 0) {
+		return -1;
+	} else {
+		return i;
+	} /* if (sng_link_type_map[i].init == 0) */
+}
+
+/******************************************************************************/
+int find_switch_type_in_map(const char *switchType)
+{
+	int i = 0;
+
+	while (sng_switch_type_map[i].init == 1) {
+		/* check if string matches the sng_type name */ 
+		if (!strcasecmp(switchType, sng_switch_type_map[i].sng_type)) {
+			/* we've found a match break from the loop */
+			break;
+		} else {
+			/* move on to the next on */
+			i++;
+		}
+	} /* while (sng_switch_type_map[i].init == 1) */
+
+	/* check how we exited the loop */
+	if (sng_switch_type_map[i].init == 0) {
+		return -1;
+	} else {
+		return i;
+	} /* if (sng_switch_type_map[i].init == 0) */
+}
+
+/******************************************************************************/
+int find_ssf_type_in_map(const char *ssfType)
+{
+	int i = 0;
+
+	while (sng_ssf_type_map[i].init == 1) {
+		/* check if string matches the sng_type name */ 
+		if (!strcasecmp(ssfType, sng_ssf_type_map[i].sng_type)) {
+			/* we've found a match break from the loop */
+			break;
+		} else {
+			/* move on to the next on */
+			i++;
+		}
+	} /* while (sng_ssf_type_map[i].init == 1) */
+
+	/* check how we exited the loop */
+	if (sng_ssf_type_map[i].init == 0) {
+		return -1;
+	} else {
+		return i;
+	} /* if (sng_ssf_type_map[i].init == 0) */
+}
+
+/******************************************************************************/
+int find_cic_cntrl_in_map(const char *cntrlType)
+{
+	int i = 0;
+
+	while (sng_cic_cntrl_type_map[i].init == 1) {
+		/* check if string matches the sng_type name */ 
+		if (!strcasecmp(cntrlType, sng_cic_cntrl_type_map[i].sng_type)) {
+			/* we've found a match break from the loop */
+			break;
+		} else {
+			/* move on to the next on */
+			i++;
+		}
+	} /* while (sng_cic_cntrl_type_map[i].init == 1) */
+
+	/* check how we exited the loop */
+	if (sng_cic_cntrl_type_map[i].init == 0) {
+		return -1;
+	} else {
+		return i;
+	} /* if (sng_cic_cntrl_type_map[i].init == 0) */
+}
+
+/******************************************************************************/
+ftdm_status_t check_status_of_all_isup_intf(void)
+{
+	sng_isup_inf_t		*sngss7_intf = NULL;
+	uint8_t				status = 0xff;
+	int					x;
+
+	/* go through all the isupIntfs and ask the stack to give their current state */
+	x = 1;
+	for (x = 1; x < (MAX_ISUP_INFS + 1); x++) {
+	/**************************************************************************/
+
+		if (g_ftdm_sngss7_data.cfg.isupIntf[x].id == 0) continue;
+
+		sngss7_intf = &g_ftdm_sngss7_data.cfg.isupIntf[x];
+
+		if (ftmod_ss7_isup_intf_sta(sngss7_intf->id, &status)) {
+			SS7_ERROR("Failed to get status of ISUP intf %d\n", sngss7_intf->id);
+			continue;
+		}
+
+		switch (status){
+		/**********************************************************************/
+		case (SI_INTF_AVAIL):
+			SS7_DEBUG("State of ISUP intf %d = AVAIL\n", sngss7_intf->id); 
+
+			/* check the current state for interface that we know */
+			if (sngss7_test_flag(sngss7_intf, SNGSS7_PAUSED)) {
+				/* we thing the intf is paused...put into resume */ 
+				sngss7_clear_flag(sngss7_intf, SNGSS7_PAUSED);
+			} else {
+				/* nothing to since we already know that interface is active */
+			}
+			break;
+		/**********************************************************************/
+		case (SI_INTF_UNAVAIL):
+			SS7_DEBUG("State of ISUP intf %d = UNAVAIL\n", sngss7_intf->id); 
+			/* check the current state for interface that we know */
+			if (sngss7_test_flag(sngss7_intf, SNGSS7_PAUSED)) {
+				/* nothing to since we already know that interface is active */ 
+			} else {
+				/* put the interface into pause */
+				sngss7_set_flag(sngss7_intf, SNGSS7_PAUSED);
+			}
+			break;
+		/**********************************************************************/
+		case (SI_INTF_CONG1):
+			SS7_DEBUG("State of ISUP intf %d = Congestion 1\n", sngss7_intf->id);
+			break;
+		/**********************************************************************/
+		case (SI_INTF_CONG2):
+			SS7_DEBUG("State of ISUP intf %d = Congestion 2\n", sngss7_intf->id);
+			break;
+		/**********************************************************************/
+		case (SI_INTF_CONG3):
+			SS7_DEBUG("State of ISUP intf %d = Congestion 3\n", sngss7_intf->id);
+			break;
+		/**********************************************************************/
+		default:
+			/* should do something here to handle the possiblity of an unknown case */
+			SS7_ERROR("Unknown ISUP intf Status code (%d) for Intf = %d\n", status, sngss7_intf->id);
+			break;
+		/**********************************************************************/
+		} /* switch (status) */
+
+	/**************************************************************************/
+	} /* for (x = 1; x < MAX_ISUP_INFS + 1); i++) */
+
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
 /* For Emacs:
  * Local Variables:
  * mode:c
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c
index 75b32d6..c2d493f 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c
@@ -61,7 +61,7 @@ void handle_isup_t35(void *userdata)
     SS7_ERROR("[Call-Control] Timer 35 expired on CIC = %d\n", sngss7_info->circuit->cic);
 
     /* set the flag to indicate this hangup is started from the local side */
-    sngss7_set_flag(sngss7_info, FLAG_LOCAL_REL);
+    sngss7_set_ckt_flag(sngss7_info, FLAG_LOCAL_REL);
 
     /* hang up on timer expiry */
     ftdmchan->caller_data.hangup_cause = 28;
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
index d4fd1ca..277951c 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
@@ -39,6 +39,60 @@
 /******************************************************************************/
 
 /* GLOBALS ********************************************************************/
+sng_ssf_type_t sng_ssf_type_map[] =
+{
+	{ 1, "nat"   , SSF_NAT   },
+	{ 1, "int"   , SSF_INTL  },
+	{ 1, "spare" , SSF_SPARE },
+	{ 1, "res"   , SSF_RES   },
+	{ 0, "", 0 },
+};
+
+sng_switch_type_t sng_switch_type_map[] =
+{
+	{ 1, "itu88"  , LSI_SW_ITU     , LSI_SW_ITU     },
+	{ 1, "itu92"  , LSI_SW_ITU     , LSI_SW_ITU     },
+	{ 1, "itu97"  , LSI_SW_ITU97   , LSI_SW_ITU97   },
+	{ 1, "itu00"  , LSI_SW_ITU2000 , LSI_SW_ITU2000 },
+	{ 1, "ansi88" , LSI_SW_ANS88   , LSI_SW_ANS88   },
+	{ 1, "ansi92" , LSI_SW_ANS92   , LSI_SW_ANS92   },
+	{ 1, "ansi95" , LSI_SW_ANS92   , LSI_SW_ANS92   },
+	{ 1, "etsiv2" , LSI_SW_ETSI    , LSI_SW_ETSI    },
+	{ 1, "etsiv3" , LSI_SW_ETSIV3  , LSI_SW_ETSIV3  },
+	{ 1, "india"  , LSI_SW_INDIA   , LSI_SW_INDIA   },
+	{ 1, "uk"     , LSI_SW_UK      , LSI_SW_UK      },
+	{ 1, "russia" , LSI_SW_RUSSIA  , LSI_SW_RUSSIA  },
+	{ 0, "", 0, 0 },
+};
+
+sng_link_type_t sng_link_type_map[] =
+{
+	{ 1, "itu88"  , LSD_SW_ITU88 , LSN_SW_ITU   },
+	{ 1, "itu92"  , LSD_SW_ITU92 , LSN_SW_ITU   },
+	{ 1, "etsi"   , LSD_SW_ITU92 , LSN_SW_ITU   },
+	{ 1, "ansi88" , LSD_SW_ANSI88, LSN_SW_ANS   },
+	{ 1, "ansi92" , LSD_SW_ANSI92, LSN_SW_ANS   },
+	{ 1, "ansi96" , LSD_SW_ANSI92, LSN_SW_ANS96 },
+	{ 0, "", 0, 0 },
+};
+
+sng_mtp2_error_type_t sng_mtp2_error_type_map[] =
+{
+	{ 1, "basic", SD_ERR_NRM },
+	{ 1, "pcr"  , SD_ERR_CYC },
+	{ 0, "", 0 },
+};
+
+sng_cic_cntrl_type_t sng_cic_cntrl_type_map[] =
+{
+	{ 1, "bothway"     , BOTHWAY     },
+	{ 1, "incoming"    , INCOMING    },
+	{ 1, "outgoing"    , OUTGOING    },
+	{ 1, "controlling" , CONTROLLING },
+	{ 1, "controlled"  , CONTROLLED  },
+	{ 0, "", 0 },
+};
+
 typedef struct sng_timeslot
 {
 	int	 channel;
@@ -47,13 +101,28 @@ typedef struct sng_timeslot
 	int	 hole;
 }sng_timeslot_t;
 
-typedef struct sng_isupCkt
+typedef struct sng_span
 {
+	char			name[MAX_NAME_LEN];
 	ftdm_span_t		*span;
+	uint32_t		ccSpanId;
+} sng_span_t;
+
+typedef struct sng_ccSpan
+{
+	char			name[MAX_NAME_LEN];
+	uint32_t		options;
+	uint32_t		id;
+	uint32_t		procId;
+	uint32_t		isupInf;
 	uint32_t		cicbase;
-	uint32_t		typeCntrl;
 	char			ch_map[MAX_CIC_MAP_LENGTH];
-	uint32_t		isupInf;
+	uint32_t		typeCntrl;
+	uint32_t		switchType;
+	uint32_t		ssf;
+	uint32_t		clg_nadi;
+	uint32_t		cld_nadi;
+	uint32_t		min_digits;
 	uint32_t		t3;
 	uint32_t		t12;
 	uint32_t		t13;
@@ -61,8 +130,9 @@ typedef struct sng_isupCkt
 	uint32_t		t15;
 	uint32_t		t16;
 	uint32_t		t17;
+	uint32_t		t35;
 	uint32_t		tval;
-} sng_isupCkt_t;
+} sng_ccSpan_t;
 
 int cmbLinkSetId;
 /******************************************************************************/
@@ -72,9 +142,22 @@ int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *spa
 
 static int ftmod_ss7_parse_sng_isup(ftdm_conf_node_t *sng_isup);
 
+static int ftmod_ss7_parse_sng_gen(ftdm_conf_node_t *sng_gen);
+
+static int ftmod_ss7_parse_sng_relay(ftdm_conf_node_t *sng_relay);
+static int ftmod_ss7_parse_relay_channel(ftdm_conf_node_t *relay_chan);
+
+static int ftmod_ss7_parse_mtp1_links(ftdm_conf_node_t *mtp1_links);
+static int ftmod_ss7_parse_mtp1_link(ftdm_conf_node_t *mtp1_link);
+
+static int ftmod_ss7_parse_mtp2_links(ftdm_conf_node_t *mtp2_links);
+static int ftmod_ss7_parse_mtp2_link(ftdm_conf_node_t *mtp2_link);
+
+static int ftmod_ss7_parse_mtp3_links(ftdm_conf_node_t *mtp3_links);
+static int ftmod_ss7_parse_mtp3_link(ftdm_conf_node_t *mtp3_link);
+
 static int ftmod_ss7_parse_mtp_linksets(ftdm_conf_node_t *mtp_linksets);
 static int ftmod_ss7_parse_mtp_linkset(ftdm_conf_node_t *mtp_linkset);
-static int ftmod_ss7_parse_mtp_link(ftdm_conf_node_t *mtp_link, sng_mtp_link_t *mtpLink);
 
 static int ftmod_ss7_parse_mtp_routes(ftdm_conf_node_t *mtp_routes);
 static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route);
@@ -82,19 +165,22 @@ static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route);
 static int ftmod_ss7_parse_isup_interfaces(ftdm_conf_node_t *isup_interfaces);
 static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface);
 
-static int ftmod_ss7_fill_in_mtpLink(sng_mtp_link_t *mtpLink);
+static int ftmod_ss7_parse_cc_spans(ftdm_conf_node_t *cc_spans);
+static int ftmod_ss7_parse_cc_span(ftdm_conf_node_t *cc_span);
 
+static int ftmod_ss7_fill_in_relay_channel(sng_relay_t *relay_channel);
+static int ftmod_ss7_fill_in_mtp1_link(sng_mtp1_link_t *mtp1Link);
+static int ftmod_ss7_fill_in_mtp2_link(sng_mtp2_link_t *mtp1Link);
+static int ftmod_ss7_fill_in_mtp3_link(sng_mtp3_link_t *mtp1Link);
 static int ftmod_ss7_fill_in_mtpLinkSet(sng_link_set_t *mtpLinkSet);
-
 static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route);
 static int ftmod_ss7_fill_in_nsap(sng_route_t *mtp3_route);
-
 static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup);
 static int ftmod_ss7_fill_in_isap(sng_isap_t *sng_isap);
-
+static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan);
 static int ftmod_ss7_fill_in_self_route(int spc, int linkType, int switchType, int ssf);
+static int ftmod_ss7_fill_in_circuits(sng_span_t *sngSpan);
 
-static int ftmod_ss7_fill_in_circuits(sng_isupCkt_t *isupCkt);
 static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot);
 
 /******************************************************************************/
@@ -103,18 +189,17 @@ static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot);
 int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *span)
 {
 	int					i = 0;
-	int					x = 0;
 	const char			*var = NULL;
 	const char			*val = NULL;
 	ftdm_conf_node_t	*ptr = NULL;
 	sng_route_t			self_route;
-	sng_isupCkt_t		isupCkt;
+	sng_span_t			sngSpan;
 
 	/* clean out the isup ckt */
-	memset(&isupCkt, 0x0, sizeof(sng_isupCkt_t));
+	memset(&sngSpan, 0x0, sizeof(sngSpan));
 
 	/* clean out the self route */
-	memset(&self_route, 0x0, sizeof(sng_route_t));
+	memset(&self_route, 0x0, sizeof(self_route));
 
 	var = ftdm_parameters[i].var;
 	val = ftdm_parameters[i].val;
@@ -136,92 +221,23 @@ int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *spa
 
 	i++;
 	while (ftdm_parameters[i].var != NULL) {
+	/**************************************************************************/
 
 		var = ftdm_parameters[i].var;
 		val = ftdm_parameters[i].val;
 
-		if (!strcasecmp(var, "ch_map")) {
-		/**********************************************************************/
-			strncpy(isupCkt.ch_map, val, MAX_CIC_MAP_LENGTH-1);
-			SS7_DEBUG("\tFound channel map \"%s\"\n", isupCkt.ch_map);
-		/**********************************************************************/
-		} else if (!strcasecmp(var, "typeCntrl")) {
-			if (!strcasecmp(val, "bothway")) {
-				isupCkt.typeCntrl = BOTHWAY;
-				SS7_DEBUG("\tFound control type \"bothway\"\n");
-			} else if (!strcasecmp(val, "incoming")) {
-				isupCkt.typeCntrl = INCOMING;
-				SS7_DEBUG("\tFound control type \"incoming\"\n");
-			} else if (!strcasecmp(val, "outgoing")) {
-				isupCkt.typeCntrl = OUTGOING;
-				SS7_DEBUG("\tFound control type \"outgoing\"\n");
-			} else if (!strcasecmp(val, "controlled")) {
-				isupCkt.typeCntrl = CONTROLLED;
-				SS7_DEBUG("\tFound control type \"controlled\"\n");
-			} else if (!strcasecmp(val, "controlling")) {
-				isupCkt.typeCntrl = CONTROLLING;
-				SS7_DEBUG("\tFound control type \"controlling\"\n");
-			} else {
-				SS7_ERROR("Found invalid circuit control type \"%s\"!", val);
-				goto ftmod_ss7_parse_xml_error;
-			}
-		/**********************************************************************/
-		} else if (!strcasecmp(var, "cicbase")) {
-			isupCkt.cicbase = atoi(val);
-			SS7_DEBUG("\tFound cicbase = %d\n", isupCkt.cicbase);
+		if (!strcasecmp(var, "dialplan")) {
 		/**********************************************************************/
-		} else if (!strcasecmp(var, "dialplan")) {
 			/* do i give a shit about this??? */
 		/**********************************************************************/
 		} else if (!strcasecmp(var, "context")) {
-			/* do i give a shit about this??? */
-		/**********************************************************************/
-		} else if (!strcasecmp(var, "isup_interface")) {
-			/* go through all the existing interfaces and see if we find a match */
-			x = 1;
-			while (g_ftdm_sngss7_data.cfg.isupIntf[x].id != 0) {
-				if (!strcasecmp(g_ftdm_sngss7_data.cfg.isupIntf[x].name, val)) {
-					/* we have a match so break out of this loop */
-					break;
-				}
-				/* move on to the next one */
-				x++;
-			}
-
-			isupCkt.isupInf = x;
-			SS7_DEBUG("\tFound isup_interface = %s\n",g_ftdm_sngss7_data.cfg.isupIntf[x].name);
-		/**********************************************************************/
-		} else if (!strcasecmp(var, "isup.t3")) {
-			isupCkt.t3 = atoi(val);
-			SS7_DEBUG("\tFound isup t3 = \"%d\"\n", isupCkt.t3);
-		/**********************************************************************/
-		} else if (!strcasecmp(var, "isup.t12")) {
-			isupCkt.t12 = atoi(val);
-			SS7_DEBUG("\tFound isup t12 = \"%d\"\n", isupCkt.t12);
-		/**********************************************************************/
-		} else if (!strcasecmp(var, "isup.t13")) {
-			isupCkt.t13 = atoi(val);
-			SS7_DEBUG("\tFound isup t13 = \"%d\"\n", isupCkt.t13);
 		/**********************************************************************/
-		} else if (!strcasecmp(var, "isup.t14")) {
-			isupCkt.t14 = atoi(val);
-			SS7_DEBUG("\tFound isup t14 = \"%d\"\n", isupCkt.t14);
-		/**********************************************************************/
-		} else if (!strcasecmp(var, "isup.t15")) {
-			isupCkt.t15 = atoi(val);
-			SS7_DEBUG("\tFound isup t15 = \"%d\"\n", isupCkt.t15);
-		/**********************************************************************/
-		} else if (!strcasecmp(var, "isup.t16")) {
-			isupCkt.t16 = atoi(val);
-			SS7_DEBUG("\tFound isup t16 = \"%d\"\n", isupCkt.t16);
+			/* do i give a shit about this??? */
 		/**********************************************************************/
-		} else if (!strcasecmp(var, "isup.t17")) {
-			isupCkt.t17 = atoi(val);
-			SS7_DEBUG("\tFound isup t17 = \"%d\"\n", isupCkt.t17);
+		} else if (!strcasecmp(var, "ccSpanId")) {
 		/**********************************************************************/
-		} else if (!strcasecmp(var, "isup.tval")) {
-			isupCkt.tval = atoi(val);
-			SS7_DEBUG("\tFound isup tval = \"%d\"\n", isupCkt.tval);
+			sngSpan.ccSpanId = atoi(val);
+			SS7_DEBUG("Found an ccSpanId  = %d\n",sngSpan.ccSpanId);
 		/**********************************************************************/
 		} else {
 			SS7_ERROR("Unknown parameter found =\"%s\"...ignoring it!\n", var);
@@ -231,24 +247,11 @@ int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *spa
 		i++;
 	} /* while (ftdm_parameters[i].var != NULL) */
 
-	/* setup the self mtp3 route */
-	i = g_ftdm_sngss7_data.cfg.isupIntf[x].mtpRouteId;
-
-	if(ftmod_ss7_fill_in_self_route(g_ftdm_sngss7_data.cfg.isupIntf[x].spc,
-									g_ftdm_sngss7_data.cfg.mtpRoute[i].linkType,
-									g_ftdm_sngss7_data.cfg.mtpRoute[i].switchType,
-									g_ftdm_sngss7_data.cfg.mtpRoute[i].ssf)) {
-
-		SS7_ERROR("Failed to fill in self route structure!\n");
-		goto ftmod_ss7_parse_xml_error;
-
-	}
-
 	/* fill the pointer to span into isupCkt */
-	isupCkt.span = span;
+	sngSpan.span = span;
 
 	/* setup the circuits structure */
-	if(ftmod_ss7_fill_in_circuits(&isupCkt)) {
+	if(ftmod_ss7_fill_in_circuits(&sngSpan)) {
 		SS7_ERROR("Failed to fill in circuits structure!\n");
 		goto ftmod_ss7_parse_xml_error;
 	}
@@ -262,9 +265,15 @@ ftmod_ss7_parse_xml_error:
 /******************************************************************************/
 static int ftmod_ss7_parse_sng_isup(ftdm_conf_node_t *sng_isup)
 {
+	ftdm_conf_node_t	*gen_config = NULL;
+	ftdm_conf_node_t	*relay_channels = NULL;
+	ftdm_conf_node_t	*mtp1_links = NULL;
+	ftdm_conf_node_t	*mtp2_links = NULL;
+	ftdm_conf_node_t	*mtp3_links = NULL;
 	ftdm_conf_node_t	*mtp_linksets = NULL;
 	ftdm_conf_node_t	*mtp_routes = NULL;
 	ftdm_conf_node_t	*isup_interfaces = NULL;
+	ftdm_conf_node_t	*cc_spans = NULL;
 	ftdm_conf_node_t	*tmp_node = NULL;
 
 	/* confirm that we are looking at sng_isup */
@@ -275,51 +284,145 @@ static int ftmod_ss7_parse_sng_isup(ftdm_conf_node_t *sng_isup)
 		SS7_DEBUG("Parsing \"sng_isup\"...\n");
 	}
 
-	/* extract the 3 main sections of the sng_isup block */
+	/* extract the main sections of the sng_isup block */
 	tmp_node = sng_isup->child;
-	while (tmp_node != NULL) {
 
-		if (!strcasecmp(tmp_node->name, "mtp_linksets")) {
+	while (tmp_node != NULL) {
+	/**************************************************************************/
+		/* check the type of structure */
+ 		if (!strcasecmp(tmp_node->name, "sng_gen")) {
+		/**********************************************************************/
+			if (gen_config == NULL) {
+				gen_config = tmp_node;
+				SS7_DEBUG("Found a \"sng_gen\" section!\n");
+			} else {
+				SS7_ERROR("Found a second \"sng_gen\" section\n!");
+				return FTDM_FAIL;
+			}
+		/**********************************************************************/
+		} else if (!strcasecmp(tmp_node->name, "sng_relay")) {
+		/**********************************************************************/
+			if (relay_channels == NULL) {
+				relay_channels = tmp_node;
+				SS7_DEBUG("Found a \"sng_relay\" section!\n");
+			} else {
+				SS7_ERROR("Found a second \"sng_relay\" section\n!");
+				return FTDM_FAIL;
+			}
+		/**********************************************************************/
+		}else if (!strcasecmp(tmp_node->name, "mtp1_links")) {
+		/**********************************************************************/
+			if (mtp1_links == NULL) {
+				mtp1_links = tmp_node;
+				SS7_DEBUG("Found a \"mtp1_links\" section!\n");
+			} else {
+				SS7_ERROR("Found a second \"mtp1_links\" section!\n");
+				return FTDM_FAIL;
+			}
+		/**********************************************************************/
+		} else if (!strcasecmp(tmp_node->name, "mtp2_links")) {
+		/**********************************************************************/
+			if (mtp2_links == NULL) {
+				mtp2_links = tmp_node;
+				SS7_DEBUG("Found a \"mtp2_links\" section!\n");
+			} else {
+				SS7_ERROR("Found a second \"mtp2_links\" section!\n");
+				return FTDM_FAIL;
+			}
+		/**********************************************************************/
+		} else if (!strcasecmp(tmp_node->name, "mtp3_links")) {
+		/**********************************************************************/
+			if (mtp3_links == NULL) {
+				mtp3_links = tmp_node;
+				SS7_DEBUG("Found a \"mtp3_links\" section!\n");
+			} else {
+				SS7_ERROR("Found a second \"mtp3_links\" section!\n");
+				return FTDM_FAIL;
+			}
+		/**********************************************************************/
+		} else if (!strcasecmp(tmp_node->name, "mtp_linksets")) {
+		/**********************************************************************/
 			if (mtp_linksets == NULL) {
 				mtp_linksets = tmp_node;
-				SS7_DEBUG("\tFound a \"mtp_linksets section!\n");
+				SS7_DEBUG("Found a \"mtp_linksets\" section!\n");
 			} else {
-				SS7_ERROR("\tFound a second \"mtp_linksets\" section!\n");
+				SS7_ERROR("Found a second \"mtp_linksets\" section!\n");
 				return FTDM_FAIL;
 			}
+		/**********************************************************************/
 		} else if (!strcasecmp(tmp_node->name, "mtp_routes")) {
+		/**********************************************************************/
 			if (mtp_routes == NULL) {
 				mtp_routes = tmp_node;
-				SS7_DEBUG("\tFound a \"mtp_routes\" section!\n");
+				SS7_DEBUG("Found a \"mtp_routes\" section!\n");
 			} else {
-				SS7_ERROR("\tFound a second \"mtp_routes\" section!\n");
+				SS7_ERROR("Found a second \"mtp_routes\" section!\n");
 				return FTDM_FAIL;
 			}
+		/**********************************************************************/
 		} else if (!strcasecmp(tmp_node->name, "isup_interfaces")) {
+		/**********************************************************************/
 			if (isup_interfaces == NULL) {
 				isup_interfaces = tmp_node;
-				SS7_DEBUG("\tFound a \"isup_interfaces\" section!\n");
+				SS7_DEBUG("Found a \"isup_interfaces\" section!\n");
+			} else {
+				SS7_ERROR("Found a second \"isup_interfaces\" section\n!");
+				return FTDM_FAIL;
+			}
+		/**********************************************************************/
+		} else if (!strcasecmp(tmp_node->name, "cc_spans")) {
+		/**********************************************************************/
+			if (cc_spans == NULL) {
+				cc_spans = tmp_node;
+				SS7_DEBUG("Found a \"cc_spans\" section!\n");
 			} else {
-				SS7_ERROR("\tFound a second \"isup_interfaces\" section\n!");
+				SS7_ERROR("Found a second \"cc_spans\" section\n!");
 				return FTDM_FAIL;
 			}
+		/**********************************************************************/
 		} else {
+		/**********************************************************************/
 			SS7_ERROR("\tFound an unknown section \"%s\"!\n", tmp_node->name);
 			return FTDM_FAIL;
-		}
+		/**********************************************************************/
+		} 
 
 		/* go to the next sibling */
 		tmp_node = tmp_node->next;
-
 	} /* while (tmp_node != NULL) */
 
 	/* now try to parse the sections */
+	if (ftmod_ss7_parse_sng_gen(gen_config)) {
+		SS7_ERROR("Failed to parse \"gen_config\"!\n");
+		return FTDM_FAIL;
+	}
+
+	if (ftmod_ss7_parse_sng_relay(relay_channels)) {
+		SS7_ERROR("Failed to parse \"relay_channels\"!\n");
+		return FTDM_FAIL;
+	}
+
+	if (ftmod_ss7_parse_mtp1_links(mtp1_links)) {
+		SS7_ERROR("Failed to parse \"mtp1_links\"!\n");
+		return FTDM_FAIL;
+	}
+
+	if (ftmod_ss7_parse_mtp2_links(mtp2_links)) {
+		SS7_ERROR("Failed to parse \"mtp2_links\"!\n");
+		return FTDM_FAIL;
+	}
+
+	if (ftmod_ss7_parse_mtp3_links(mtp3_links)) {
+		SS7_ERROR("Failed to parse \"mtp3_links\"!\n");
+		return FTDM_FAIL;
+	}
+
 	if (ftmod_ss7_parse_mtp_linksets(mtp_linksets)) {
 		SS7_ERROR("Failed to parse \"mtp_linksets\"!\n");
 		return FTDM_FAIL;
 	}
 
-	if (ftmod_ss7_parse_mtp_routes(mtp_routes)) {
+	if (ftmod_ss7_parse_mtp_routes(mtp_routes)) {	
 		SS7_ERROR("Failed to parse \"mtp_routes\"!\n");
 		return FTDM_FAIL;
 	}
@@ -329,35 +432,190 @@ static int ftmod_ss7_parse_sng_isup(ftdm_conf_node_t *sng_isup)
 		return FTDM_FAIL;
 	}
 
+	if (ftmod_ss7_parse_cc_spans(cc_spans)) {
+		SS7_ERROR("Failed to parse \"cc_spans\"!\n");
+		return FTDM_FAIL;
+	}
+
 	return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
-static int ftmod_ss7_parse_mtp_linksets(ftdm_conf_node_t *mtp_linksets)
+static int ftmod_ss7_parse_sng_gen(ftdm_conf_node_t *sng_gen)
 {
-	ftdm_conf_node_t	*mtp_linkset = NULL;
+	ftdm_conf_parameter_t	*parm = sng_gen->parameters;
+	int						num_parms = sng_gen->n_parameters;
+	int						i = 0;
 
-	/* confirm that we are looking at mtp_linksets */
-	if (strcasecmp(mtp_linksets->name, "mtp_linksets")) {
-		SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_linksets\"!\n",mtp_linksets->name);
+	/* extract all the information from the parameters */
+	for (i = 0; i < num_parms; i++) {
+	/**************************************************************************/
+
+		if (!strcasecmp(parm->var, "procId")) {
+		/**********************************************************************/
+			g_ftdm_sngss7_data.cfg.procId = atoi(parm->val);
+			SS7_DEBUG("Found a procId = %d\n", g_ftdm_sngss7_data.cfg.procId);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "license")) {
+		/**********************************************************************/
+			strcpy(g_ftdm_sngss7_data.cfg.license, parm->val);
+			strcpy(g_ftdm_sngss7_data.cfg.signature, parm->val);
+			strcat(g_ftdm_sngss7_data.cfg.signature, ".sig");
+			SS7_DEBUG("Found license file = %s\n", g_ftdm_sngss7_data.cfg.license);
+			SS7_DEBUG("Found signature file = %s\n", g_ftdm_sngss7_data.cfg.signature);	
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "spc")) {
+		/**********************************************************************/
+			g_ftdm_sngss7_data.cfg.spc = atoi(parm->val);
+			SS7_DEBUG("Found SPC = %d\n", g_ftdm_sngss7_data.cfg.spc);
+		/**********************************************************************/
+		} else {
+		/**********************************************************************/
+			SS7_ERROR("Found an invalid parameter \"%s\"!\n", parm->val);
+			return FTDM_FAIL;
+		/**********************************************************************/
+		}
+
+		/* move to the next parmeter */
+		parm = parm + 1;
+	} /* for (i = 0; i < num_parms; i++) */
+
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+static int ftmod_ss7_parse_sng_relay(ftdm_conf_node_t *sng_relay)
+{
+	ftdm_conf_node_t	*relay_chan = NULL;
+
+	/* confirm that we are looking at sng_relay */
+	if (strcasecmp(sng_relay->name, "sng_relay")) {
+		SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"sng_relay\"!\n",sng_relay->name);
 		return FTDM_FAIL;
 	}  else {
-		SS7_DEBUG("Parsing \"mtp_linksets\"...\n");
+		SS7_DEBUG("Parsing \"sng_relay\"...\n");
+	}
+
+	relay_chan = sng_relay->child;
+
+	if (relay_chan != NULL) {
+		while (relay_chan != NULL) {
+			/* try to the parse relay_channel */
+			if (ftmod_ss7_parse_relay_channel(relay_chan)) {
+				SS7_ERROR("Failed to parse \"relay_channels\"!\n");
+				return FTDM_FAIL;
+			}
+
+			/* move on to the next linkset */
+			relay_chan = relay_chan->next;
+		} /* while (relay_chan != NULL) */
+	} /* if (relay_chan != NULL) */
+
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+static int ftmod_ss7_parse_relay_channel(ftdm_conf_node_t *relay_chan)
+{
+	sng_relay_t				tmp_chan;
+	ftdm_conf_parameter_t	*parm = relay_chan->parameters;
+	int						num_parms = relay_chan->n_parameters;
+	int						i = 0;
+
+	/* confirm that we are looking at relay_channel */
+	if (strcasecmp(relay_chan->name, "relay_channel")) {
+		SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"relay_channel\"!\n",relay_chan->name);
+		return FTDM_FAIL;
+	} else {
+		SS7_DEBUG("Parsing \"relay_channel\"...\n");
+	}
+
+	/* initalize the tmp_chan structure */
+	memset(&tmp_chan, 0x0, sizeof(tmp_chan));
+
+	/* extract all the information from the parameters */
+	for (i = 0; i < num_parms; i++) {
+	/**************************************************************************/
+
+		if (!strcasecmp(parm->var, "name")) {
+		/**********************************************************************/
+			strcpy((char *)tmp_chan.name, parm->val);
+			SS7_DEBUG("Found an relay_channel named = %s\n", tmp_chan.name);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "type")) {
+		/**********************************************************************/
+			if (!strcasecmp(parm->val, "listen")) {
+				tmp_chan.type = LRY_CT_TCP_LISTEN;
+				SS7_DEBUG("Found a type = LISTEN\n");
+			} else if (!strcasecmp(parm->val, "server")) {
+				tmp_chan.type = LRY_CT_TCP_SERVER;
+				SS7_DEBUG("Found a type = SERVER\n");
+			} else if (!strcasecmp(parm->val, "client")) {
+				tmp_chan.type = LRY_CT_TCP_CLIENT;
+				SS7_DEBUG("Found a type = CLIENT\n");
+			} else {
+				SS7_ERROR("Found an invalid \"type\" = %s\n", parm->var);
+				return FTDM_FAIL;
+			}
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "hostname")) {
+		/**********************************************************************/
+			strcpy((char *)tmp_chan.hostname, parm->val);
+			SS7_DEBUG("Found a hostname = %s\n", tmp_chan.hostname);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "port")) {
+		/**********************************************************************/
+			tmp_chan.port = atoi(parm->val);
+			SS7_DEBUG("Found a port = %d\n", tmp_chan.port);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "procId")) {
+		/**********************************************************************/
+			tmp_chan.procId = atoi(parm->val);
+			SS7_DEBUG("Found a procId = %d\n", tmp_chan.procId);
+		/**********************************************************************/
+		} else {
+		/**********************************************************************/
+			SS7_ERROR("Found an invalid parameter \"%s\"!\n", parm->val);
+			return FTDM_FAIL;
+		/**********************************************************************/
+		}
+
+		/* move to the next parmeter */
+		parm = parm + 1;
+	} /* for (i = 0; i < num_parms; i++) */
+
+	/* store the channel in the global structure */
+	ftmod_ss7_fill_in_relay_channel(&tmp_chan);
+
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+static int ftmod_ss7_parse_mtp1_links(ftdm_conf_node_t *mtp1_links)
+{
+	ftdm_conf_node_t	*mtp1_link = NULL;
+
+	/* confirm that we are looking at mtp1_links */
+	if (strcasecmp(mtp1_links->name, "mtp1_links")) {
+		SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp1_links\"!\n",mtp1_links->name);
+		return FTDM_FAIL;
+	}  else {
+		SS7_DEBUG("Parsing \"mtp1_links\"...\n");
 	}
 
 	/* extract the mtp_links */
-	mtp_linkset = mtp_linksets->child;
+	mtp1_link = mtp1_links->child;
 
-	/* run through all of the mtp_linksets found  */
-	while (mtp_linkset != NULL) {
-		/* try to the parse mtp_linkset */
-		if (ftmod_ss7_parse_mtp_linkset(mtp_linkset)) {
-			SS7_ERROR("Failed to parse \"mtp_linkset\"!\n");
+	/* run through all of the links found  */
+	while (mtp1_link != NULL) {
+		/* try to the parse mtp_link */
+		if (ftmod_ss7_parse_mtp1_link(mtp1_link)) {
+			SS7_ERROR("Failed to parse \"mtp1_link\"!\n");
 			return FTDM_FAIL;
 		}
 
-		/* move on to the next linkset */
-		mtp_linkset = mtp_linkset->next;
+		/* move on to the next link */
+		mtp1_link = mtp1_link->next;
 
 	} /* while (mtp_linkset != NULL) */
 
@@ -365,413 +623,611 @@ static int ftmod_ss7_parse_mtp_linksets(ftdm_conf_node_t *mtp_linksets)
 }
 
 /******************************************************************************/
-static int ftmod_ss7_parse_mtp_linkset(ftdm_conf_node_t *mtp_linkset)
+static int ftmod_ss7_parse_mtp1_link(ftdm_conf_node_t *mtp1_link)
 {
-	ftdm_conf_parameter_t	*parm = mtp_linkset->parameters;
-	int						num_parms = mtp_linkset->n_parameters;
-	ftdm_conf_node_t		*mtp_link = NULL;
-	sng_mtp_link_t			mtpLink[MAX_MTP_LINKS+1];
-	sng_link_set_t			mtpLinkSet;
-	int						count;
-	int						i;
+	sng_mtp1_link_t		 	mtp1Link;
+	ftdm_conf_parameter_t	*parm = mtp1_link->parameters;
+	int					 	num_parms = mtp1_link->n_parameters;
+	int					 	i;
 
-	/* initialize the mtp_link structures */
-	for (i = 0; i < (MAX_MTP_LINKS  + 1); i++) {
-		memset(&mtpLink[i], 0x0, sizeof(mtpLink[i]));
-	}
-	memset(&mtpLinkSet, 0x0, sizeof(mtpLinkSet));
+	/* initalize the mtp1Link structure */
+	memset(&mtp1Link, 0x0, sizeof(mtp1Link));
 
-	/* confirm that we are looking at mtp_linkset */
-	if (strcasecmp(mtp_linkset->name, "mtp_linkset")) {
-		SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_linkset\"!\n",mtp_linkset->name);
+	/* confirm that we are looking at an mtp_link */
+	if (strcasecmp(mtp1_link->name, "mtp1_link")) {
+		SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp1_link\"!\n",mtp1_link->name);
 		return FTDM_FAIL;
 	} else {
-		SS7_DEBUG("Parsing \"mtp_linkset\"...\n");
+		SS7_DEBUG("Parsing \"mtp1_link\"...\n");
 	}
 
-	/* extract all the information from the parameters */
 	for (i = 0; i < num_parms; i++) {
-		/**********************************************************************/
+	/**************************************************************************/
+
 		if (!strcasecmp(parm->var, "name")) {
-			strncpy((char *)mtpLinkSet.name, parm->val, MAX_NAME_LEN-1);
-			SS7_DEBUG("\tFound an \"mtp_linkset\" named = %s\n", mtpLinkSet.name);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "apc")) {
-			mtpLinkSet.apc = atoi(parm->val);
-			SS7_DEBUG("\tFound mtpLinkSet->apc = %d\n", mtpLinkSet.apc);
+			strcpy((char *)mtp1Link.name, parm->val);
+			SS7_DEBUG("Found an mtp1_link named = %s\n", mtp1Link.name);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "minActive")) {
-			mtpLinkSet.minActive = atoi(parm->val);
-			SS7_DEBUG("\tFound mtpLinkSet->minActive = %d\n", mtpLinkSet.minActive);
+		} else if (!strcasecmp(parm->var, "id")) {
+		/**********************************************************************/
+			mtp1Link.id = atoi(parm->val);
+			SS7_DEBUG("Found an mtp1_link id = %d\n", mtp1Link.id);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "span")) {
+		/**********************************************************************/
+			mtp1Link.span = atoi(parm->val);
+			SS7_DEBUG("Found an mtp1_link span = %d\n", mtp1Link.span);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "chan")) {
+		/**********************************************************************/
+			mtp1Link.chan = atoi(parm->val);
+			SS7_DEBUG("Found an mtp1_link chan = %d\n", mtp1Link.chan);
 		/**********************************************************************/
 		} else {
+		/**********************************************************************/
 			SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val);
 			return FTDM_FAIL;
+		/**********************************************************************/
 		}
 
 		/* move to the next parmeter */
 		parm = parm + 1;
 
+	/**************************************************************************/
 	} /* for (i = 0; i < num_parms; i++) */
 
-	/* grab the first mtp-link (which sits below the mtp_links section) */
-	mtp_link = mtp_linkset->child->child;
+	/* store the link in global structure */
+	ftmod_ss7_fill_in_mtp1_link(&mtp1Link);
+
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+static int ftmod_ss7_parse_mtp2_links(ftdm_conf_node_t *mtp2_links)
+{
+	ftdm_conf_node_t	*mtp2_link = NULL;
+
+	/* confirm that we are looking at mtp2_links */
+	if (strcasecmp(mtp2_links->name, "mtp2_links")) {
+		SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp2_links\"!\n",mtp2_links->name);
+		return FTDM_FAIL;
+	}  else {
+		SS7_DEBUG("Parsing \"mtp2_links\"...\n");
+	}
 
-	/* initalize the link counter */
-	count = 0;
+	/* extract the mtp_links */
+	mtp2_link = mtp2_links->child;
 
-	/* run through all of the mtp_links found  */
-	while (mtp_link != NULL) {
+	/* run through all of the links found  */
+	while (mtp2_link != NULL) {
 		/* try to the parse mtp_linkset */
-		if (ftmod_ss7_parse_mtp_link(mtp_link, &mtpLink[count] )) {
-			SS7_ERROR("Failed to parse \"mtp_link\"!\n");
+		if (ftmod_ss7_parse_mtp2_link(mtp2_link)) {
+			SS7_ERROR("Failed to parse \"mtp2_link\"!\n");
 			return FTDM_FAIL;
 		}
 
-		/* incremenet the link counter */
-		count++;
-
 		/* move on to the next link */
-		mtp_link = mtp_link->next;
+		mtp2_link = mtp2_link->next;
+
+	} /* while (mtp_linkset != NULL) */
+
+	return FTDM_SUCCESS;
+}
 
-	} /* while (mtp_link != NULL) */
+/******************************************************************************/
+static int ftmod_ss7_parse_mtp2_link(ftdm_conf_node_t *mtp2_link)
+{
+	sng_mtp2_link_t		 	mtp2Link;
+	ftdm_conf_parameter_t	*parm = mtp2_link->parameters;
+	int					 	num_parms = mtp2_link->n_parameters;
+	int					 	i;
+	int						ret;
+
+	/* initalize the mtp1Link structure */
+	memset(&mtp2Link, 0x0, sizeof(mtp2Link));
 
-	/* confirm we have the right number of links */
-	if (count < 1 || count > 15 ) {
-		SS7_ERROR("Invalid number of mtp_links found (%d)\n", count);
+	/* confirm that we are looking at an mtp2_link */
+	if (strcasecmp(mtp2_link->name, "mtp2_link")) {
+		SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp2_link\"!\n",mtp2_link->name);
 		return FTDM_FAIL;
+	} else {
+		SS7_DEBUG("Parsing \"mtp2_link\"...\n");
 	}
 
-	/* now we need to see if this linkset exists already or not and grab an Id */
-	i = 1;
-	while (g_ftdm_sngss7_data.cfg.mtpLinkSet[i].id != 0) {
-		if (!strcasecmp((const char *)g_ftdm_sngss7_data.cfg.mtpLinkSet[i].name, (const char *)mtpLinkSet.name)) {
-			/* we've found the linkset...so it has already been configured */
-			break;
+	for (i = 0; i < num_parms; i++) {
+	/**************************************************************************/
+
+		if (!strcasecmp(parm->var, "name")) {
+		/**********************************************************************/
+			strcpy((char *)mtp2Link.name, parm->val);
+			SS7_DEBUG("Found an mtp2_link named = %s\n", mtp2Link.name);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "id")) {
+		/**********************************************************************/
+			mtp2Link.id = atoi(parm->val);
+			SS7_DEBUG("Found an mtp2_link id = %d\n", mtp2Link.id);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "mtp1Id")) {
+		/**********************************************************************/
+			mtp2Link.mtp1Id = atoi(parm->val);
+			SS7_DEBUG("Found an mtp2_link mtp1Id = %d\n", mtp2Link.mtp1Id);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "errorType")) {
+		/**********************************************************************/
+			ret = find_mtp2_error_type_in_map(parm->val);
+			if (ret == -1) {
+				SS7_ERROR("Found an invalid mtp2_link errorType = %s\n", parm->var);
+				return FTDM_FAIL;
+			} else {
+				mtp2Link.errorType = sng_mtp2_error_type_map[ret].tril_type;
+				SS7_DEBUG("Found an mtp2_link errorType = %s\n", sng_mtp2_error_type_map[ret].sng_type);
+			}
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "lssuLength")) {
+		/**********************************************************************/
+			mtp2Link.lssuLength = atoi(parm->val);
+			SS7_DEBUG("Found an mtp2_link lssuLength = %d\n", mtp2Link.lssuLength);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "linkType")) {
+		/**********************************************************************/
+			ret = find_link_type_in_map(parm->val);
+			if (ret == -1) {
+				SS7_ERROR("Found an invalid mtp2_link linkType = %s\n", parm->var);
+				return FTDM_FAIL;
+			} else {
+				mtp2Link.linkType = sng_link_type_map[ret].tril_mtp2_type;
+				SS7_DEBUG("Found an mtp2_link linkType = %s\n", sng_link_type_map[ret].sng_type);
+			}
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "t1")) {
+		/**********************************************************************/
+			mtp2Link.t1 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp2 t1 = \"%d\"\n",mtp2Link.t1);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "t2")) {
+		/**********************************************************************/
+			mtp2Link.t2 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp2 t2 = \"%d\"\n",mtp2Link.t2);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "t3")) {
+		/**********************************************************************/
+			mtp2Link.t3 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp2 t3 = \"%d\"\n",mtp2Link.t3);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "t4n")) {
+		/**********************************************************************/
+			mtp2Link.t4n = atoi(parm->val);
+			SS7_DEBUG("Found an mtp2 t4n = \"%d\"\n",mtp2Link.t4n);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "t4e")) {
+		/**********************************************************************/
+			mtp2Link.t4e = atoi(parm->val);
+			SS7_DEBUG("Found an mtp2 t4e = \"%d\"\n",mtp2Link.t4e);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "t5")) {
+		/**********************************************************************/
+			mtp2Link.t5 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp2 t5 = \"%d\"\n",mtp2Link.t5);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "t6")) {
+		/**********************************************************************/
+			mtp2Link.t6 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp2 t6 = \"%d\"\n",mtp2Link.t6);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "t7")) {
+		/**********************************************************************/
+			mtp2Link.t7 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp2 t7 = \"%d\"\n",mtp2Link.t7);
+		/**********************************************************************/
+		} else {
+		/**********************************************************************/
+			SS7_ERROR("Found an invalid parameter \"%s\"!\n", parm->val);
+			return FTDM_FAIL;
+		/**********************************************************************/
 		}
-		i++;
-		/* add in error check to make sure we don't go out-of-bounds */
-	}
 
-	/* if the id value is 0 that means we didn't find the linkset */
-	if (g_ftdm_sngss7_data.cfg.mtpLinkSet[i].id  == 0) {
-		mtpLinkSet.id = i;
-		SS7_DEBUG("found new mtpLinkSet, id is = %d\n", mtpLinkSet.id);
-	} else {
-		mtpLinkSet.id = i;
-		SS7_DEBUG("found existing mtpLinkSet, id is = %d\n", mtpLinkSet.id);
-	}
+		/* move to the next parmeter */
+		parm = parm + 1;
 
-	/* we now have all the information to fill in the Libsng_ss7 structures */
-	i = 0;
-	count = 0;
-	while (mtpLink[i].mtp1.span != 0 ){
+	/**************************************************************************/
+	} /* for (i = 0; i < num_parms; i++) */
 
-		/* have to grab a couple of values from the linkset */
-		mtpLink[i].mtp3.apc			= mtpLinkSet.apc;
-		mtpLink[i].mtp3.linkSetId	= mtpLinkSet.id;
+	/* store the link in global structure */
+	ftmod_ss7_fill_in_mtp2_link(&mtp2Link);
 
-		ftmod_ss7_fill_in_mtpLink(&mtpLink[i]);
+	return FTDM_SUCCESS;
+}
 
-		/* increment the links counter */
-		count++;
+/******************************************************************************/
+static int ftmod_ss7_parse_mtp3_links(ftdm_conf_node_t *mtp3_links)
+{
+	ftdm_conf_node_t	*mtp3_link = NULL;
 
-		/* increment the index value */
-		i++;
+	/* confirm that we are looking at mtp3_links */
+	if (strcasecmp(mtp3_links->name, "mtp3_links")) {
+		SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp3_links\"!\n",mtp3_links->name);
+		return FTDM_FAIL;
+	}  else {
+		SS7_DEBUG("Parsing \"mtp3_links\"...\n");
 	}
 
-	mtpLinkSet.linkType		= mtpLink[0].mtp3.linkType;
-	mtpLinkSet.switchType	= mtpLink[0].mtp3.switchType;
-	mtpLinkSet.ssf			= mtpLink[0].mtp3.ssf;
+	/* extract the mtp_links */
+	mtp3_link = mtp3_links->child;
 
-	ftmod_ss7_fill_in_mtpLinkSet(&mtpLinkSet);
+	/* run through all of the links found  */
+	while (mtp3_link != NULL) {
+		/* try to the parse mtp_linkset */
+		if (ftmod_ss7_parse_mtp3_link(mtp3_link)) {
+			SS7_ERROR("Failed to parse \"mtp3_link\"!\n");
+			return FTDM_FAIL;
+		}
+
+		/* move on to the next link */
+		mtp3_link = mtp3_link->next;
+
+	} /* while (mtp_linkset != NULL) */
 
 	return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
-static int ftmod_ss7_parse_mtp_link(ftdm_conf_node_t *mtp_link, sng_mtp_link_t *mtpLink)
+static int ftmod_ss7_parse_mtp3_link(ftdm_conf_node_t *mtp3_link)
 {
-	ftdm_conf_parameter_t	*parm = mtp_link->parameters;
-	int					 	num_parms = mtp_link->n_parameters;
+	sng_mtp3_link_t		 	mtp3Link;
+	ftdm_conf_parameter_t	*parm = mtp3_link->parameters;
+	int					 	num_parms = mtp3_link->n_parameters;
 	int					 	i;
-	
+	int						ret;
+
+	/* initalize the mtp3Link structure */
+	memset(&mtp3Link, 0x0, sizeof(mtp3Link));
+
 	/* confirm that we are looking at an mtp_link */
-	if (strcasecmp(mtp_link->name, "mtp_link")) {
-		SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_link\"!\n",mtp_link->name);
+	if (strcasecmp(mtp3_link->name, "mtp3_link")) {
+		SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp3_link\"!\n",mtp3_link->name);
 		return FTDM_FAIL;
 	} else {
-		SS7_DEBUG("Parsing \"mtp_link\"...\n");
+		SS7_DEBUG("Parsing \"mtp3_link\"...\n");
 	}
-	
+
 	for (i = 0; i < num_parms; i++) {
-		/* try to match the parameter to what we expect */
-		/**********************************************************************/
+	/**************************************************************************/
 		if (!strcasecmp(parm->var, "name")) {
-			strncpy((char *)mtpLink->name, parm->val, MAX_NAME_LEN-1);
-			SS7_DEBUG("\tFound an \"mtp_link\" named = %s\n", mtpLink->name);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "span")) {
-			mtpLink->mtp1.span = atoi(parm->val);
-			SS7_DEBUG("\tFound mtpLink->span = %d\n", mtpLink->mtp1.span);
+			strcpy((char *)mtp3Link.name, parm->val);
+			SS7_DEBUG("Found an mtp3_link named = %s\n", mtp3Link.name);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "chan")) {
-			mtpLink->mtp1.chan = atoi(parm->val);
-			SS7_DEBUG("\tFound mtpLink->chan = %d\n", mtpLink->mtp1.chan);
+		} else if (!strcasecmp(parm->var, "id")) {
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "errorType")) {
-			if (!strcasecmp(parm->val, "basic")) {
-				mtpLink->mtp2.errorType = SD_ERR_NRM;
-			} else if (!strcasecmp(parm->val, "pcr")) {
-				mtpLink->mtp2.errorType = SD_ERR_CYC;
-			} else {
-				SS7_ERROR("\tFound an invalid \"errorType\" = %s\n", parm->var);
-				return FTDM_FAIL;
-			}
-			SS7_DEBUG("\tFound mtpLink->errorType=%s\n", parm->val);
+			mtp3Link.id = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3_link id = %d\n", mtp3Link.id);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "lssuLength")) {
-			mtpLink->mtp2.lssuLength = atoi(parm->val);
-			if ((mtpLink->mtp2.lssuLength != 1) && (mtpLink->mtp2.lssuLength != 2)) {
-				SS7_ERROR("\tFound an invalid \"lssuLength\" = %d\n", mtpLink->mtp2.lssuLength);
-				return FTDM_FAIL;
-			} else {
-				SS7_DEBUG("\tFound mtpLink->lssuLength=%d\n", mtpLink->mtp2.lssuLength);
-			}
+		} else if (!strcasecmp(parm->var, "mtp2Id")) {
+		/**********************************************************************/
+			mtp3Link.mtp2Id = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3_link mtp2Id = %d\n", mtp3Link.mtp2Id);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "mtp2ProcId")) {
+		/**********************************************************************/
+			mtp3Link.mtp2ProcId = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3_link mtp2ProcId = %d\n", mtp3Link.mtp2ProcId);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "priority")) {
-			mtpLink->mtp3.priority = atoi(parm->val);
-			if ((mtpLink->mtp3.priority == 0) || (mtpLink->mtp3.priority == 1) || 
-				(mtpLink->mtp3.priority == 2) || (mtpLink->mtp3.priority == 3)) {
-				SS7_DEBUG("\tFound mtpLink->priority = %d\n",mtpLink->mtp3.priority);
-			} else {
-				SS7_ERROR("\tFound an invalid \"priority\"=%d\n",mtpLink->mtp3.priority);
-				return FTDM_FAIL;
-			} 
+		/**********************************************************************/
+			mtp3Link.priority = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 Link priority = %d\n",mtp3Link.priority); 
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "linkType")) {
-			if (!strcasecmp(parm->val, "itu92")) {
-				mtpLink->mtp2.linkType = LSD_SW_ITU92;
-				mtpLink->mtp3.linkType = LSN_SW_ITU;
-				SS7_DEBUG("\tFound mtpLink->linkType = \"ITU92\"\n");
-			} else if (!strcasecmp(parm->val, "itu88")) {
-				mtpLink->mtp2.linkType = LSD_SW_ITU88;
-				mtpLink->mtp3.linkType = LSN_SW_ITU;
-				SS7_DEBUG("\tFound mtpLink->linkType = \"ITU88\"\n");
-			} else if (!strcasecmp(parm->val, "ansi96")) {
-				mtpLink->mtp2.linkType = LSD_SW_ANSI92;
-				mtpLink->mtp3.linkType = LSN_SW_ANS96;
-				SS7_DEBUG("\tFound mtpLink->linkType = \"ANSI96\"\n");
-			} else if (!strcasecmp(parm->val, "ansi92")) {
-				mtpLink->mtp2.linkType = LSD_SW_ANSI92;
-				mtpLink->mtp3.linkType = LSN_SW_ANS;
-				SS7_DEBUG("\tFound mtpLink->linkType = \"ANSI92\"\n");
-			} else if (!strcasecmp(parm->val, "ansi88")) {
-				mtpLink->mtp2.linkType = LSD_SW_ANSI88;
-				mtpLink->mtp3.linkType = LSN_SW_ANS;
-				SS7_DEBUG("\tFound mtpLink->linkType = \"ANSI88\"\n");
-			} else if (!strcasecmp(parm->val, "etsi")) {
-				mtpLink->mtp2.linkType = LSD_SW_ITU92;
-				mtpLink->mtp3.linkType = LSN_SW_ITU;
-				SS7_DEBUG("\tFound mtpLink->linkType = \"ETSI\"\n");
-			} else {
-				SS7_ERROR("\tFound an invalid linktype of \"%s\"!\n", parm->val);
+		/**********************************************************************/
+			ret = find_link_type_in_map(parm->val);
+			if (ret == -1) {
+				SS7_ERROR("Found an invalid mtp3_link linkType = %s\n", parm->var);
 				return FTDM_FAIL;
+			} else {
+				mtp3Link.linkType = sng_link_type_map[ret].tril_mtp3_type;
+				SS7_DEBUG("Found an mtp3_link linkType = %s\n", sng_link_type_map[ret].sng_type);
 			}
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "switchType")) {
-			if (!strcasecmp(parm->val, "itu97")) {
-				mtpLink->mtp3.switchType = LSI_SW_ITU97;
-				SS7_DEBUG("\tFound mtpLink->switchType = \"ITU97\"\n");
-			} else if (!strcasecmp(parm->val, "itu88")) {
-				mtpLink->mtp3.switchType = LSI_SW_ITU;
-				SS7_DEBUG("\tFound mtpLink->switchType = \"ITU88\"\n");
-			} else if (!strcasecmp(parm->val, "itu92")) {
-				mtpLink->mtp3.switchType = LSI_SW_ITU;
-				SS7_DEBUG("\tFound mtpLink->switchType = \"ITU92\"\n");
-			} else if (!strcasecmp(parm->val, "itu00")) {
-				mtpLink->mtp3.switchType = LSI_SW_ITU2000;
-				SS7_DEBUG("\tFound mtpLink->switchType = \"ITU00\"\n");
-			} else if (!strcasecmp(parm->val, "ETSIV2")) {
-				mtpLink->mtp3.switchType = LSI_SW_ETSI;
-				SS7_DEBUG("\tFound mtpLink->switchType = \"ETSIV2\"\n");
-			} else if (!strcasecmp(parm->val, "ETSIV3")) {
-				mtpLink->mtp3.switchType = LSI_SW_ETSIV3;
-				SS7_DEBUG("\tFound mtpLink->switchType = \"ETSIV3\"\n");
-			} else if (!strcasecmp(parm->val, "UK")) {
-				mtpLink->mtp3.switchType = LSI_SW_UK;
-				SS7_DEBUG("\tFound mtpLink->switchType = \"UK\"\n");
-			} else if (!strcasecmp(parm->val, "RUSSIA")) {
-				mtpLink->mtp3.switchType = LSI_SW_RUSSIA;
-				SS7_DEBUG("\tFound mtpLink->switchType = \"RUSSIA\"\n");
-			} else if (!strcasecmp(parm->val, "INDIA")) {
-				mtpLink->mtp3.switchType = LSI_SW_INDIA;
-				SS7_DEBUG("\tFound mtpLink->switchType = \"INDIA\"\n");
-			} else if (!strcasecmp(parm->val, "ansi88")) {
-				mtpLink->mtp3.switchType = LSI_SW_ANS88;
-				SS7_DEBUG("\tFound mtpLink->switchType = \"ANSI88\"\n");
-			} else if (!strcasecmp(parm->val, "ansi92")) {
-				mtpLink->mtp3.switchType = LSI_SW_ANS92;
-				SS7_DEBUG("\tFound mtpLink->switchType = \"ANSI92\"\n");
-			} else if (!strcasecmp(parm->val, "ansi95")) {
-				mtpLink->mtp3.switchType = LSI_SW_ANS95;
-				SS7_DEBUG("\tFound mtpLink->switchType = \"ANSI95\"\n");
-			} else {
-				SS7_ERROR("\tFound an invalid linktype of \"%s\"!\n", parm->val);
+		/**********************************************************************/
+			ret = find_switch_type_in_map(parm->val);
+			if (ret == -1) {
+				SS7_ERROR("Found an invalid mtp3_link switchType = %s\n", parm->var);
 				return FTDM_FAIL;
+			} else {
+				mtp3Link.switchType = sng_switch_type_map[ret].tril_mtp3_type;
+				SS7_DEBUG("Found an mtp3_link switchType = %s\n", sng_switch_type_map[ret].sng_type);
 			}
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "ssf")) {
-			if (!strcasecmp(parm->val, "nat")) {
-				mtpLink->mtp3.ssf = SSF_NAT;
-			} else if (!strcasecmp(parm->val, "int")) {
-				mtpLink->mtp3.ssf = SSF_INTL;
-			} else if (!strcasecmp(parm->val, "spare")) {
-				mtpLink->mtp3.ssf = SSF_SPARE;
-			} else if (!strcasecmp(parm->val, "res")) {
-				mtpLink->mtp3.ssf = SSF_RES;
-			} else {
-				SS7_ERROR("\tFound an invalid ssf of \"%s\"!\n", parm->val);
+		/**********************************************************************/
+			ret = find_ssf_type_in_map(parm->val);
+			if (ret == -1) {
+				SS7_ERROR("Found an invalid mtp3_link ssf = %s\n", parm->var);
 				return FTDM_FAIL;
+			} else {
+				mtp3Link.ssf = sng_ssf_type_map[ret].tril_type;
+				SS7_DEBUG("Found an mtp3_link ssf = %s\n", sng_ssf_type_map[ret].sng_type);
 			}
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "slc")) {
-			mtpLink->mtp3.slc = atoi(parm->val);
-			SS7_DEBUG("\tFound mtpLink->slc = \"%d\"\n",mtpLink->mtp3.slc);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp2.t1")) {
-			mtpLink->mtp2.t1 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp2 t1 = \"%d\"\n",mtpLink->mtp2.t1);
+			mtp3Link.slc = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 Link slc = %d\n",mtp3Link.slc);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "linkset")) {
+		/**********************************************************************/
+			mtp3Link.linkSetId = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 Link linkset = %d\n",mtp3Link.linkSetId);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "t1")) {
+		/**********************************************************************/
+			mtp3Link.t1 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 t1 = %d\n",mtp3Link.t1);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "t2")) {
+		/**********************************************************************/
+			mtp3Link.t2 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 t2 = %d\n",mtp3Link.t2);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "t3")) {
+		/**********************************************************************/
+			mtp3Link.t3 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 t3 = %d\n",mtp3Link.t3);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "t4")) {
+		/**********************************************************************/
+			mtp3Link.t4 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 t4 = %d\n",mtp3Link.t4);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "t5")) {
+		/**********************************************************************/
+			mtp3Link.t5 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 t5 = %d\n",mtp3Link.t5);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp2.t2")) {
-			mtpLink->mtp2.t2 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp2 t2 = \"%d\"\n",mtpLink->mtp2.t2);
+		} else if (!strcasecmp(parm->var, "t7")) {
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp2.t3")) {
-			mtpLink->mtp2.t3 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp2 t3 = \"%d\"\n",mtpLink->mtp2.t3);
+			mtp3Link.t7 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 t7 = %d\n",mtp3Link.t7);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp2.t4n")) {
-			mtpLink->mtp2.t4n = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp2 t4n = \"%d\"\n",mtpLink->mtp2.t4n);
+		} else if (!strcasecmp(parm->var, "t12")) {
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp2.t4e")) {
-			mtpLink->mtp2.t4e = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp2 t4e = \"%d\"\n",mtpLink->mtp2.t4e);
+			mtp3Link.t12 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 t12 = %d\n",mtp3Link.t12);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp2.t5")) {
-			mtpLink->mtp2.t5 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp2 t5 = \"%d\"\n",mtpLink->mtp2.t5);
+		} else if (!strcasecmp(parm->var, "t13")) {
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp2.t6")) {
-			mtpLink->mtp2.t6 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp2 t6 = \"%d\"\n",mtpLink->mtp2.t6);
+			mtp3Link.t13 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 t13 = %d\n",mtp3Link.t13);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp2.t7")) {
-			mtpLink->mtp2.t7 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp2 t7 = \"%d\"\n",mtpLink->mtp2.t7);
+		} else if (!strcasecmp(parm->var, "t14")) {
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.t1")) {
-			mtpLink->mtp3.t1 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t1 = \"%d\"\n",mtpLink->mtp3.t1);
+			mtp3Link.t14 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 t14 = %d\n",mtp3Link.t14);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.t2")) {
-			mtpLink->mtp3.t2 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t2 = \"%d\"\n",mtpLink->mtp3.t2);
+		} else if (!strcasecmp(parm->var, "t17")) {
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.t3")) {
-			mtpLink->mtp3.t3 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t3 = \"%d\"\n",mtpLink->mtp3.t3);
+			mtp3Link.t17 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 t17 = %d\n",mtp3Link.t17);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.t4")) {
-			mtpLink->mtp3.t4 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t4 = \"%d\"\n",mtpLink->mtp3.t4);
+		} else if (!strcasecmp(parm->var, "t22")) {
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.t5")) {
-			mtpLink->mtp3.t5 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t5 = \"%d\"\n",mtpLink->mtp3.t5);
+			mtp3Link.t22 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 t22 = %d\n",mtp3Link.t22);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.t7")) {
-			mtpLink->mtp3.t7 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t7 = \"%d\"\n",mtpLink->mtp3.t7);
+		} else if (!strcasecmp(parm->var, "t23")) {
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.t12")) {
-			mtpLink->mtp3.t12 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t12 = \"%d\"\n",mtpLink->mtp3.t12);
+			mtp3Link.t23 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 t23 = %d\n",mtp3Link.t23);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.t13")) {
-			mtpLink->mtp3.t13 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t13 = \"%d\"\n",mtpLink->mtp3.t13);
+		} else if (!strcasecmp(parm->var, "t24")) {
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.t14")) {
-			mtpLink->mtp3.t14 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t14 = \"%d\"\n",mtpLink->mtp3.t14);
+			mtp3Link.t24 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 t24 = %d\n",mtp3Link.t24);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.t17")) {
-			mtpLink->mtp3.t17 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t17 = \"%d\"\n",mtpLink->mtp3.t17);
+		} else if (!strcasecmp(parm->var, "t31")) {
+			mtp3Link.t31 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 t31 = %d\n",mtp3Link.t31);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.t22")) {
-			mtpLink->mtp3.t22 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t22 = \"%d\"\n",mtpLink->mtp3.t22);
+		} else if (!strcasecmp(parm->var, "t32")) {
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.t23")) {
-			mtpLink->mtp3.t23 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t23 = \"%d\"\n",mtpLink->mtp3.t23);
+			mtp3Link.t32 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 t32 = %d\n",mtp3Link.t32);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.t24")) {
-			mtpLink->mtp3.t24 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t24 = \"%d\"\n",mtpLink->mtp3.t24);
+		} else if (!strcasecmp(parm->var, "t33")) {
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.t31")) {
-			mtpLink->mtp3.t31 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t31 = \"%d\"\n",mtpLink->mtp3.t31);
+			mtp3Link.t33 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 t33 = %d\n",mtp3Link.t33);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.t32")) {
-			mtpLink->mtp3.t32 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t32 = \"%d\"\n",mtpLink->mtp3.t32);
+		} else if (!strcasecmp(parm->var, "t34")) {
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.t33")) {
-			mtpLink->mtp3.t33 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t33 = \"%d\"\n",mtpLink->mtp3.t33);
+			mtp3Link.t34 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 t34 = %d\n",mtp3Link.t34);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.t34")) {
-			mtpLink->mtp3.t34 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t34 = \"%d\"\n",mtpLink->mtp3.t34);
+		} else if (!strcasecmp(parm->var, "t35")) {
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.t35")) {
-			mtpLink->mtp3.t35 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t35 = \"%d\"\n",mtpLink->mtp3.t35);
+			mtp3Link.t35 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 t35 = %d\n",mtp3Link.t35);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.t36")) {
-			mtpLink->mtp3.t36 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t36 = \"%d\"\n",mtpLink->mtp3.t36);
+		} else if (!strcasecmp(parm->var, "t36")) {
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.t37")) {
-			mtpLink->mtp3.t37 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t37 = \"%d\"\n",mtpLink->mtp3.t37);
+			mtp3Link.t36 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 t36 = %d\n",mtp3Link.t36);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.tcraft")) {
-			mtpLink->mtp3.tcraft = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 tcraft = \"%d\"\n",mtpLink->mtp3.tcraft);
+		} else if (!strcasecmp(parm->var, "t37")) {
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.tflc")) {
-			mtpLink->mtp3.tflc = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 tflc = \"%d\"\n",mtpLink->mtp3.tflc);
+			mtp3Link.t37 = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 t37 = %d\n",mtp3Link.t37);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp3.tbnd")) {
-			mtpLink->mtp3.tbnd = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 tbnd = \"%d\"\n",mtpLink->mtp3.tbnd);
+		} else if (!strcasecmp(parm->var, "tcraft")) {
+		/**********************************************************************/
+			mtp3Link.tcraft = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 tcraft = %d\n",mtp3Link.tcraft);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "tflc")) {
+		/**********************************************************************/
+			mtp3Link.tflc = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 tflc = %d\n",mtp3Link.tflc);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "tbnd")) {
+		/**********************************************************************/
+			mtp3Link.tbnd = atoi(parm->val);
+			SS7_DEBUG("Found an mtp3 tbnd = %d\n",mtp3Link.tbnd);
 		/**********************************************************************/
 		} else {
-			SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val);
+		/**********************************************************************/
+			SS7_ERROR("Found an invalid parameter %s!\n", parm->val);
 			return FTDM_FAIL;
+		/**********************************************************************/
 		}
-	
-		/* move to the next parameter */
+
+		/* move to the next parmeter */
 		parm = parm + 1;
+
+	/**************************************************************************/
+	} /* for (i = 0; i < num_parms; i++) */
+
+	/* store the link in global structure */
+	ftmod_ss7_fill_in_mtp3_link(&mtp3Link);
+
+	/* move the linktype, switchtype and ssf to the linkset */
+	if (g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].linkType == 0) {
+		g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].linkType = mtp3Link.linkType;
+	} else if (g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].linkType != mtp3Link.linkType) {
+		SS7_ERROR("Trying to add an MTP3 Link to a Linkset with a different linkType: mtp3.id=%d, mtp3.name=%s, mtp3.linktype=%d, linkset.id=%d, linkset.linktype=%d\n",
+					mtp3Link.id, mtp3Link.name, mtp3Link.linkType,
+					g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].id, g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].linkType);
+		return FTDM_FAIL;
+	} else {
+		/* should print that all is ok...*/
 	}
-	
+
+	if (g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].switchType == 0) {
+		g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].switchType = mtp3Link.switchType;
+	} else if (g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].switchType != mtp3Link.switchType) {
+		SS7_ERROR("Trying to add an MTP3 Link to a Linkset with a different switchType: mtp3.id=%d, mtp3.name=%s, mtp3.switchtype=%d, linkset.id=%d, linkset.switchtype=%d\n",
+					mtp3Link.id, mtp3Link.name, mtp3Link.switchType,
+					g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].id, g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].switchType);
+		return FTDM_FAIL;
+	} else {
+		/* should print that all is ok...*/
+	}
+
+	if (g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].ssf == 0) {
+		g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].ssf = mtp3Link.ssf;
+	} else if (g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].ssf != mtp3Link.ssf) {
+		SS7_ERROR("Trying to add an MTP3 Link to a Linkset with a different ssf: mtp3.id=%d, mtp3.name=%s, mtp3.ssf=%d, linkset.id=%d, linkset.ssf=%d\n",
+					mtp3Link.id, mtp3Link.name, mtp3Link.ssf,
+					g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].id, g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3Link.linkSetId].ssf);
+		return FTDM_FAIL;
+	} else {
+		/* should print that all is ok...*/
+	}
+
+
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+static int ftmod_ss7_parse_mtp_linksets(ftdm_conf_node_t *mtp_linksets)
+{
+	ftdm_conf_node_t	*mtp_linkset = NULL;
+
+	/* confirm that we are looking at mtp_linksets */
+	if (strcasecmp(mtp_linksets->name, "mtp_linksets")) {
+		SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_linksets\"!\n",mtp_linksets->name);
+		return FTDM_FAIL;
+	}  else {
+		SS7_DEBUG("Parsing \"mtp_linksets\"...\n");
+	}
+
+	/* extract the mtp_links */
+	mtp_linkset = mtp_linksets->child;
+
+	/* run through all of the mtp_linksets found  */
+	while (mtp_linkset != NULL) {
+		/* try to the parse mtp_linkset */
+		if (ftmod_ss7_parse_mtp_linkset(mtp_linkset)) {
+			SS7_ERROR("Failed to parse \"mtp_linkset\"!\n");
+			return FTDM_FAIL;
+		}
+
+		/* move on to the next linkset */
+		mtp_linkset = mtp_linkset->next;
+
+	} /* while (mtp_linkset != NULL) */
+
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+static int ftmod_ss7_parse_mtp_linkset(ftdm_conf_node_t *mtp_linkset)
+{
+	sng_link_set_t	 		mtpLinkSet;
+	ftdm_conf_parameter_t	*parm = mtp_linkset->parameters;
+	int					 	num_parms = mtp_linkset->n_parameters;
+	int					 	i;
+
+	/* initalize the mtpLinkSet structure */
+	memset(&mtpLinkSet, 0x0, sizeof(mtpLinkSet));
+
+	/* confirm that we are looking at mtp_linkset */
+	if (strcasecmp(mtp_linkset->name, "mtp_linkset")) {
+		SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_linkset\"!\n",mtp_linkset->name);
+		return FTDM_FAIL;
+	} else {
+		SS7_DEBUG("Parsing \"mtp_linkset\"...\n");
+	}
+
+	/* extract all the information from the parameters */
+	for (i = 0; i < num_parms; i++) {
+	/**************************************************************************/
+
+		if (!strcasecmp(parm->var, "name")) {
+		/**********************************************************************/
+			strcpy((char *)mtpLinkSet.name, parm->val);
+			SS7_DEBUG("Found an mtpLinkSet named = %s\n", mtpLinkSet.name);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "id")) {
+		/**********************************************************************/
+			mtpLinkSet.id = atoi(parm->val);
+			SS7_DEBUG("Found mtpLinkSet id = %d\n", mtpLinkSet.id);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "apc")) {
+		/**********************************************************************/
+			mtpLinkSet.apc = atoi(parm->val);
+			SS7_DEBUG("Found mtpLinkSet apc = %d\n", mtpLinkSet.apc);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "minActive")) {
+		/**********************************************************************/
+			mtpLinkSet.minActive = atoi(parm->val);
+			SS7_DEBUG("Found mtpLinkSet minActive = %d\n", mtpLinkSet.minActive);
+		/**********************************************************************/
+		} else {
+		/**********************************************************************/
+			SS7_ERROR("Found an invalid parameter \"%s\"!\n", parm->val);
+			return FTDM_FAIL;
+		/**********************************************************************/
+		}
+
+		/* move to the next parmeter */
+		parm = parm + 1;
+	/**************************************************************************/
+	} /* for (i = 0; i < num_parms; i++) */
+
+	ftmod_ss7_fill_in_mtpLinkSet(&mtpLinkSet);
+
+	/* go through all the mtp3 links and fill in the apc */
+	i = 1;
+	while (g_ftdm_sngss7_data.cfg.mtp3Link[i].id != 0) {
+		if (g_ftdm_sngss7_data.cfg.mtp3Link[i].linkSetId == mtpLinkSet.id) {
+			g_ftdm_sngss7_data.cfg.mtp3Link[i].apc = mtpLinkSet.apc;
+		}
+
+		i++;
+	}
+
 	return FTDM_SUCCESS;
 }
 
@@ -813,6 +1269,7 @@ static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route)
 	int					 	num_parms = mtp_route->n_parameters;
 	int					 	i;
 
+	/* initalize the mtpRoute structure */
 	memset(&mtpRoute, 0x0, sizeof(mtpRoute));
 
 	/* confirm that we are looking at an mtp_link */
@@ -824,119 +1281,120 @@ static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route)
 	}
 
 	for (i = 0; i < num_parms; i++) {
+	/**************************************************************************/
+
 		/* try to match the parameter to what we expect */
-		/**********************************************************************/
 		if (!strcasecmp(parm->var, "name")) {
-			strncpy((char *)mtpRoute.name, parm->val, MAX_NAME_LEN-1);
-			SS7_DEBUG("\tFound an \"mtp_route\" named = %s\n", mtpRoute.name);
+		/**********************************************************************/
+			strcpy((char *)mtpRoute.name, parm->val);
+			SS7_DEBUG("Found an mtpRoute named = %s\n", mtpRoute.name);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "id")) {
+		/**********************************************************************/
+			mtpRoute.id = atoi(parm->val);
+			SS7_DEBUG("Found an mtpRoute id = %d\n", mtpRoute.id);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "dpc")) {
+		/**********************************************************************/
 			mtpRoute.dpc = atoi(parm->val);
-			SS7_DEBUG("\tFound mtpRoute->dpc = %d\n", mtpRoute.dpc);
-		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp_linkset")) {
-
-			/* find the linkset by it's name */
-			int x = 1;
-			while (g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) {
-				/* check if the name matches */
-				if (!strcasecmp((char *)g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name, parm->val)) {
-
-					/* now, harvest the required infomormation from the global structure */
-					mtpRoute.linkType		= g_ftdm_sngss7_data.cfg.mtpLinkSet[x].linkType;
-					mtpRoute.switchType		= g_ftdm_sngss7_data.cfg.mtpLinkSet[x].switchType;
-					mtpRoute.ssf			= g_ftdm_sngss7_data.cfg.mtpLinkSet[x].ssf;
-					mtpRoute.linkSetId		= g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id;
-					cmbLinkSetId++;
-					mtpRoute.cmbLinkSetId	= cmbLinkSetId;
-
-					/* update the linkset with the new cmbLinkSet value */
-					g_ftdm_sngss7_data.cfg.mtpLinkSet[x].numLinks++;
-					g_ftdm_sngss7_data.cfg.mtpLinkSet[x].links[g_ftdm_sngss7_data.cfg.mtpLinkSet[x].numLinks-1] = mtpRoute.cmbLinkSetId;
-					break;
-				}
-				x++;
-			}
-
-			/* check why we exited the wile loop ... and react accordingly */
-			if (mtpRoute.cmbLinkSetId == 0) {
-				SS7_ERROR("\tFailed to find the linkset = \"%s\"!\n", parm->val);
-				return FTDM_FAIL;
-			} else {
-				SS7_DEBUG("\tFound mtp3_route->linkset = %s\n", parm->val);
-			}
+			SS7_DEBUG("Found an mtpRoute dpc = %d\n", mtpRoute.dpc);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "linksetId")) {
+		/**********************************************************************/
+			mtpRoute.linkSetId = atoi(parm->val);
+			SS7_DEBUG("Found an mtpRoute linkset = %s\n", parm->val);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isSTP")) {
+		/**********************************************************************/
 			if (!strcasecmp(parm->val, "no")) {
 				mtpRoute.isSTP = 0;
-				SS7_DEBUG("\tFound mtpRoute->isSTP = no\n");
+				SS7_DEBUG("Found an mtpRoute isSTP = no\n");
 			} else if (!strcasecmp(parm->val, "yes")) {
 				mtpRoute.isSTP = 1;
-				SS7_DEBUG("\tFound mtpRoute->isSTP = yes\n");
+				SS7_DEBUG("Found an mtpRoute isSTP = yes\n");
 			} else {
-				SS7_ERROR("\tFound an invalid parameter for isSTP \"%s\"!\n", parm->val);
+				SS7_ERROR("Found an invalid parameter for isSTP %s!\n", parm->val);
 			   return FTDM_FAIL;
 			}
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "mtp3.t6")) {
+		/**********************************************************************/
 			mtpRoute.t6 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t6 = \"%d\"\n",mtpRoute.t6);
+			SS7_DEBUG("Found an mtp3 t6 = %d\n",mtpRoute.t6);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "mtp3.t8")) {
+		/**********************************************************************/
 			mtpRoute.t8 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t8 = \"%d\"\n",mtpRoute.t8);
+			SS7_DEBUG("Found an mtp3 t8 = %d\n",mtpRoute.t8);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "mtp3.t10")) {
+		/**********************************************************************/
 			mtpRoute.t10 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t10 = \"%d\"\n",mtpRoute.t10);
+			SS7_DEBUG("Found an mtp3 t10 = %d\n",mtpRoute.t10);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "mtp3.t11")) {
+		/**********************************************************************/
 			mtpRoute.t11 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t11 = \"%d\"\n",mtpRoute.t11);
+			SS7_DEBUG("Found an mtp3 t11 = %d\n",mtpRoute.t11);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "mtp3.t15")) {
+		/**********************************************************************/
 			mtpRoute.t15 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t15 = \"%d\"\n",mtpRoute.t15);
+			SS7_DEBUG("Found an mtp3 t15 = %d\n",mtpRoute.t15);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "mtp3.t16")) {
+		/**********************************************************************/
 			mtpRoute.t16 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t16 = \"%d\"\n",mtpRoute.t16);
+			SS7_DEBUG("Found an mtp3 t16 = %d\n",mtpRoute.t16);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "mtp3.t18")) {
+		/**********************************************************************/
 			mtpRoute.t18 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t18 = \"%d\"\n",mtpRoute.t18);
+			SS7_DEBUG("Found an mtp3 t18 = %d\n",mtpRoute.t18);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "mtp3.t19")) {
+		/**********************************************************************/
 			mtpRoute.t19 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t19 = \"%d\"\n",mtpRoute.t19);
+			SS7_DEBUG("Found an mtp3 t19 = %d\n",mtpRoute.t19);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "mtp3.t21")) {
+		/**********************************************************************/
 			mtpRoute.t21 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t21 = \"%d\"\n",mtpRoute.t21);
+			SS7_DEBUG("Found an mtp3 t21 = %d\n",mtpRoute.t21);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "mtp3.t25")) {
+		/**********************************************************************/
 			mtpRoute.t25 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t25 = \"%d\"\n",mtpRoute.t25);
+			SS7_DEBUG("Found an mtp3 t25 = %d\n",mtpRoute.t25);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "mtp3.t26")) {
+		/**********************************************************************/
 			mtpRoute.t26 = atoi(parm->val);
-			SS7_DEBUG("\tFound mtp3 t26 = \"%d\"\n",mtpRoute.t26);
+			SS7_DEBUG("Found an mtp3 t26 = %d\n",mtpRoute.t26);
 		/**********************************************************************/
 		} else {
-			SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val);
+		/**********************************************************************/
+			SS7_ERROR("Found an invalid parameter \"%s\"!\n", parm->val);
 			return FTDM_FAIL;
-
+		/**********************************************************************/
 		}
 
 		/* move to the next parameter */
 		parm = parm + 1;
 	}
 
-	ftmod_ss7_fill_in_nsap(&mtpRoute);
+	/* pull up the linktype, switchtype, and SSF from the linkset */
+	mtpRoute.linkType = g_ftdm_sngss7_data.cfg.mtpLinkSet[mtpRoute.linkSetId].linkType;
+	mtpRoute.switchType = g_ftdm_sngss7_data.cfg.mtpLinkSet[mtpRoute.linkSetId].switchType;
+	mtpRoute.ssf = g_ftdm_sngss7_data.cfg.mtpLinkSet[mtpRoute.linkSetId].ssf;
 
-	ftmod_ss7_fill_in_mtp3_route(&mtpRoute);
+	/* fill in the rest of the values in the mtpRoute struct  */
+	mtpRoute.nwId = mtpRoute.id;
+	mtpRoute.cmbLinkSetId = mtpRoute.id;
 
+	ftmod_ss7_fill_in_mtp3_route(&mtpRoute);
 
+	ftmod_ss7_fill_in_nsap(&mtpRoute);
 
 	return FTDM_SUCCESS;
 }
@@ -979,10 +1437,9 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
 	ftdm_conf_parameter_t	*parm = isup_interface->parameters;
 	int						num_parms = isup_interface->n_parameters;
 	int						i;
-	int						linkSetId;
-	int						flag_cld_nadi = 0;
-	int						flag_clg_nadi = 0;
+	int						ret;
 
+	/* initalize the isup intf and isap structure */
 	memset(&sng_isup, 0x0, sizeof(sng_isup));
 	memset(&sng_isap, 0x0, sizeof(sng_isap));
 
@@ -996,56 +1453,30 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
 
 
 	for (i = 0; i < num_parms; i++) {
+	/**************************************************************************/
+
 		/* try to match the parameter to what we expect */
-		/**********************************************************************/
 		if (!strcasecmp(parm->var, "name")) {
-			strncpy((char *)sng_isup.name, parm->val, MAX_NAME_LEN-1);
-			SS7_DEBUG("\tFound an \"isup_interface\" named = %s\n", sng_isup.name);
+		/**********************************************************************/
+			strcpy((char *)sng_isup.name, parm->val);
+			SS7_DEBUG("Found an isup_interface named = %s\n", sng_isup.name);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "id")) {
+		/**********************************************************************/
+			sng_isup.id = atoi(parm->val);
+			SS7_DEBUG("Found an isup id = %d\n", sng_isup.id);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "spc")) {
+		/**********************************************************************/
 			sng_isup.spc = atoi(parm->val);
 			g_ftdm_sngss7_data.cfg.spc = sng_isup.spc;
-			SS7_DEBUG("\tFound SPC = %d\n", sng_isup.spc);
-		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "mtp_route")) {
-			/* find the route by it's name */
-			int x = 1;
-
-			while (g_ftdm_sngss7_data.cfg.mtpRoute[x].id != 0) {
-
-				/* check if the name matches */
-				if (!strcasecmp((char *)g_ftdm_sngss7_data.cfg.mtpRoute[x].name, parm->val)) {
-					/* now, harvest the required information from the global structure */
-					sng_isup.mtpRouteId		= g_ftdm_sngss7_data.cfg.mtpRoute[x].id;
-					sng_isup.dpc			= g_ftdm_sngss7_data.cfg.mtpRoute[x].dpc;
-					sng_isup.switchType	 	= g_ftdm_sngss7_data.cfg.mtpRoute[x].switchType;
-					sng_isap.switchType		= g_ftdm_sngss7_data.cfg.mtpRoute[x].switchType;
-
-					/* find the NSAP corresponding to this switchType and SSF */
-					int z = 1;
-					while (g_ftdm_sngss7_data.cfg.nsap[z].id != 0) {
-						if ((g_ftdm_sngss7_data.cfg.nsap[z].linkType == g_ftdm_sngss7_data.cfg.mtpRoute[x].linkType) &&
-							(g_ftdm_sngss7_data.cfg.nsap[z].switchType == g_ftdm_sngss7_data.cfg.mtpRoute[x].switchType) &&
-							(g_ftdm_sngss7_data.cfg.nsap[z].ssf == g_ftdm_sngss7_data.cfg.mtpRoute[x].ssf)) {
-								sng_isup.nwId 	= g_ftdm_sngss7_data.cfg.nsap[z].nwId;
-							/* we have a match so break out of this loop */
-							break;
-						}
-						/* move on to the next one */
-						z++;
-					}
-					break;
-				}
-				x++;
-			} /* while (g_ftdm_sngss7_data.cfg.mtpRoute[x].id != 0) */
-
-			/* check why we exited the while loop ... and react accordingly */
-			if (sng_isup.mtpRouteId == 0) {
-				SS7_ERROR("\tFailed to find the MTP3 Route = \"%s\"!\n", parm->val);
-				return FTDM_FAIL;
-			} else {
-				SS7_DEBUG("\tFound MTP3 Route = %s\n", parm->val);
-			}
+			SS7_DEBUG("Found an isup SPC = %d\n", sng_isup.spc);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "mtprouteId")) {
+		/**********************************************************************/
+			sng_isup.mtpRouteId=atoi(parm->val);
+
+			SS7_DEBUG("Found an isup mptRouteId = %d\n", sng_isup.mtpRouteId);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "min_digits")) {
 			sng_isup.min_digits = atoi(parm->val);
@@ -1053,300 +1484,544 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
 			SS7_DEBUG("\tFound min_digits = %d\n", sng_isup.min_digits);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "ssf")) {
-			if (!strcasecmp(parm->val, "nat")) {
-				sng_isup.ssf = SSF_NAT;
-				sng_isap.ssf = SSF_NAT;
-			} else if (!strcasecmp(parm->val, "int")) {
-				sng_isup.ssf = SSF_INTL;
-				sng_isap.ssf = SSF_INTL;
-			} else if (!strcasecmp(parm->val, "spare")) {
-				sng_isup.ssf = SSF_SPARE;
-				sng_isap.ssf = SSF_SPARE;
-			} else if (!strcasecmp(parm->val, "res")) {
-				sng_isup.ssf = SSF_RES;
-				sng_isap.ssf = SSF_RES;
-			} else {
-				SS7_ERROR("\tFound an invalid ssf of \"%s\"!\n", parm->val);
+		/**********************************************************************/
+			ret = find_ssf_type_in_map(parm->val);
+			if (ret == -1) {
+				SS7_ERROR("Found an invalid isup ssf = %s\n", parm->var);
 				return FTDM_FAIL;
+			} else {
+				sng_isup.ssf = sng_ssf_type_map[ret].tril_type;
+				sng_isap.ssf = sng_ssf_type_map[ret].tril_type;
+				SS7_DEBUG("Found an isup ssf = %s\n", sng_ssf_type_map[ret].sng_type);
 			}
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "license")) {
-		/**********************************************************************/
-			strncpy(g_ftdm_sngss7_data.cfg.license, parm->val, MAX_PATH-1);
-			strncpy(g_ftdm_sngss7_data.cfg.signature, parm->val, MAX_PATH-1);
-			strcat(g_ftdm_sngss7_data.cfg.signature, ".sig");
-			SS7_DEBUG("\tFound license file = %s\n", g_ftdm_sngss7_data.cfg.license);
-			SS7_DEBUG("\tFound signature file = %s\n", g_ftdm_sngss7_data.cfg.signature);	
-		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t1")) {
+		/**********************************************************************/
 			sng_isap.t1 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t1 = \"%d\"\n",sng_isap.t1);
+			SS7_DEBUG("Found isup t1 = %d\n",sng_isap.t1);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t2")) {
+		/**********************************************************************/
 			sng_isap.t2 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t2 = \"%d\"\n",sng_isap.t2);
+			SS7_DEBUG("Found isup t2 = %d\n",sng_isap.t2);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t4")) {
+		/**********************************************************************/
 			sng_isup.t4 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t4 = \"%d\"\n",sng_isup.t4);
+			SS7_DEBUG("Found isup t4 = %d\n",sng_isup.t4);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t5")) {
+		/**********************************************************************/
 			sng_isap.t5 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t5 = \"%d\"\n",sng_isap.t5);
+			SS7_DEBUG("Found isup t5 = %d\n",sng_isap.t5);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t6")) {
+		/**********************************************************************/
 			sng_isap.t6 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t6 = \"%d\"\n",sng_isap.t6);
+			SS7_DEBUG("Found isup t6 = %d\n",sng_isap.t6);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t7")) {
+		/**********************************************************************/
 			sng_isap.t7 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t7 = \"%d\"\n",sng_isap.t7);
+			SS7_DEBUG("Found isup t7 = %d\n",sng_isap.t7);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t8")) {
+		/**********************************************************************/
 			sng_isap.t8 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t8 = \"%d\"\n",sng_isap.t8);
+			SS7_DEBUG("Found isup t8 = %d\n",sng_isap.t8);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t9")) {
+		/**********************************************************************/
 			sng_isap.t9 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t9 = \"%d\"\n",sng_isap.t9);
+			SS7_DEBUG("Found isup t9 = %d\n",sng_isap.t9);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t10")) {
+		/**********************************************************************/
 			sng_isup.t10 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t10 = \"%d\"\n",sng_isup.t10);
+			SS7_DEBUG("Found isup t10 = %d\n",sng_isup.t10);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t11")) {
+		/**********************************************************************/
 			sng_isup.t11 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t11 = \"%d\"\n",sng_isup.t11);
+			SS7_DEBUG("Found isup t11 = %d\n",sng_isup.t11);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t18")) {
+		/**********************************************************************/
 			sng_isup.t18 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t18 = \"%d\"\n",sng_isup.t18);
+			SS7_DEBUG("Found isup t18 = %d\n",sng_isup.t18);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t19")) {
+		/**********************************************************************/
 			sng_isup.t19 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t19 = \"%d\"\n",sng_isup.t19);
+			SS7_DEBUG("Found isup t19 = %d\n",sng_isup.t19);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t20")) {
+		/**********************************************************************/
 			sng_isup.t20 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t20 = \"%d\"\n",sng_isup.t20);
+			SS7_DEBUG("Found isup t20 = %d\n",sng_isup.t20);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t21")) {
+		/**********************************************************************/
 			sng_isup.t21 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t21 = \"%d\"\n",sng_isup.t21);
+			SS7_DEBUG("Found isup t21 = %d\n",sng_isup.t21);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t22")) {
+		/**********************************************************************/
 			sng_isup.t22 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t22 = \"%d\"\n",sng_isup.t22);
+			SS7_DEBUG("Found isup t22 = %d\n",sng_isup.t22);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t23")) {
+		/**********************************************************************/
 			sng_isup.t23 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t23 = \"%d\"\n",sng_isup.t23);
+			SS7_DEBUG("Found isup t23 = %d\n",sng_isup.t23);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t24")) {
+		/**********************************************************************/
 			sng_isup.t24 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t24 = \"%d\"\n",sng_isup.t24);
+			SS7_DEBUG("Found isup t24 = %d\n",sng_isup.t24);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t25")) {
+		/**********************************************************************/
 			sng_isup.t25 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t25 = \"%d\"\n",sng_isup.t25);
+			SS7_DEBUG("Found isup t25 = %d\n",sng_isup.t25);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t26")) {
+		/**********************************************************************/
 			sng_isup.t26 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t26 = \"%d\"\n",sng_isup.t26);
+			SS7_DEBUG("Found isup t26 = %d\n",sng_isup.t26);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t28")) {
+		/**********************************************************************/
 			sng_isup.t28 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t28 = \"%d\"\n",sng_isup.t28);
+			SS7_DEBUG("Found isup t28 = %d\n",sng_isup.t28);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t29")) {
+		/**********************************************************************/
 			sng_isup.t29 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t29 = \"%d\"\n",sng_isup.t29);
+			SS7_DEBUG("Found isup t29 = %d\n",sng_isup.t29);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t30")) {
+		/**********************************************************************/
 			sng_isup.t30 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t30 = \"%d\"\n",sng_isup.t30);
+			SS7_DEBUG("Found isup t30 = %d\n",sng_isup.t30);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t31")) {
+		/**********************************************************************/
 			sng_isap.t31 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t31 = \"%d\"\n",sng_isap.t31);
+			SS7_DEBUG("Found isup t31 = %d\n",sng_isap.t31);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t32")) {
+		/**********************************************************************/
 			sng_isup.t32 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t32 = \"%d\"\n",sng_isup.t32);
+			SS7_DEBUG("Found isup t32 = %d\n",sng_isup.t32);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t33")) {
+		/**********************************************************************/
 			sng_isap.t33 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t33 = \"%d\"\n",sng_isap.t33);
+			SS7_DEBUG("Found isup t33 = %d\n",sng_isap.t33);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t34")) {
-			sng_isap.t34 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t34 = \"%d\"\n",sng_isap.t34);
 		/**********************************************************************/
-		} else if (!strcasecmp(parm->var, "isup.t35")) {
-			sng_isup.t35 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t35 = \"%d\"\n",sng_isup.t35);
+			sng_isap.t34 = atoi(parm->val);
+			SS7_DEBUG("Found isup t34 = %d\n",sng_isap.t34);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t36")) {
+		/**********************************************************************/
 			sng_isap.t36 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t36 = \"%d\"\n",sng_isap.t36);
+			SS7_DEBUG("Found isup t36 = %d\n",sng_isap.t36);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t37")) {
+		/**********************************************************************/
 			sng_isup.t37 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t37 = \"%d\"\n",sng_isup.t37);
+			SS7_DEBUG("Found isup t37 = %d\n",sng_isup.t37);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t38")) {
+		/**********************************************************************/
 			sng_isup.t38 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t38 = \"%d\"\n",sng_isup.t38);
+			SS7_DEBUG("Found isup t38 = %d\n",sng_isup.t38);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.t39")) {
+		/**********************************************************************/
 			sng_isup.t39 = atoi(parm->val);
-			SS7_DEBUG("\tFound isup t39 = \"%d\"\n",sng_isup.t39);
+			SS7_DEBUG("Found isup t39 = %d\n",sng_isup.t39);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.tccr")) {
+		/**********************************************************************/
 			sng_isap.tccr = atoi(parm->val);
-			SS7_DEBUG("\tFound isup tccr = \"%d\"\n",sng_isap.tccr);
+			SS7_DEBUG("Found isup tccr = %d\n",sng_isap.tccr);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.tccrt")) {
+		/**********************************************************************/
 			sng_isap.tccrt = atoi(parm->val);
-			SS7_DEBUG("\tFound isup tccrt = \"%d\"\n",sng_isap.tccrt);
+			SS7_DEBUG("Found isup tccrt = %d\n",sng_isap.tccrt);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.tex")) {
+		/**********************************************************************/
 			sng_isap.tex = atoi(parm->val);
-			SS7_DEBUG("\tFound isup tex = \"%d\"\n",sng_isap.tex);
+			SS7_DEBUG("Found isup tex = %d\n",sng_isap.tex);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.tect")) {
+		/**********************************************************************/
 			sng_isap.tect = atoi(parm->val);
-			SS7_DEBUG("\tFound isup tect = \"%d\"\n",sng_isap.tect);
+			SS7_DEBUG("Found isup tect = %d\n",sng_isap.tect);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.tcrm")) {
+		/**********************************************************************/
 			sng_isap.tcrm = atoi(parm->val);
-			SS7_DEBUG("\tFound isup tcrm = \"%d\"\n",sng_isap.tcrm);
+			SS7_DEBUG("Found isup tcrm = %d\n",sng_isap.tcrm);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.tcra")) {
+		/**********************************************************************/
 			sng_isap.tcra = atoi(parm->val);
-			SS7_DEBUG("\tFound isup tcra = \"%d\"\n",sng_isap.tcra);
+			SS7_DEBUG("Found isup tcra = %d\n",sng_isap.tcra);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.tfgr")) {
+		/**********************************************************************/
 			sng_isup.tfgr = atoi(parm->val);
-			SS7_DEBUG("\tFound isup tfgr = \"%d\"\n",sng_isup.tfgr);
+			SS7_DEBUG("Found isup tfgr = %d\n",sng_isup.tfgr);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.trelrsp")) {
+		/**********************************************************************/
 			sng_isap.trelrsp = atoi(parm->val);
-			SS7_DEBUG("\tFound isup trelrsp = \"%d\"\n",sng_isap.trelrsp);
+			SS7_DEBUG("Found isup trelrsp = %d\n",sng_isap.trelrsp);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.tfnlrelrsp")) {
+		/**********************************************************************/
 			sng_isap.tfnlrelrsp = atoi(parm->val);
-			SS7_DEBUG("\tFound isup tfnlrelrsp = \"%d\"\n",sng_isap.tfnlrelrsp);
+			SS7_DEBUG("Found isup tfnlrelrsp = %d\n",sng_isap.tfnlrelrsp);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.tfnlrelrsp")) {
+		/**********************************************************************/
 			sng_isap.tfnlrelrsp = atoi(parm->val);
-			SS7_DEBUG("\tFound isup tfnlrelrsp = \"%d\"\n",sng_isap.tfnlrelrsp);
+			SS7_DEBUG("Found isup tfnlrelrsp = %d\n",sng_isap.tfnlrelrsp);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.tpause")) {
+		/**********************************************************************/
 			sng_isup.tpause = atoi(parm->val);
-			SS7_DEBUG("\tFound isup tpause = \"%d\"\n",sng_isup.tpause);
+			SS7_DEBUG("Found isup tpause = %d\n",sng_isup.tpause);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "isup.tstaenq")) {
+		/**********************************************************************/
 			sng_isup.tstaenq = atoi(parm->val);
-			SS7_DEBUG("\tFound isup tstaenq = \"%d\"\n",sng_isup.tstaenq);
+			SS7_DEBUG("Found isup tstaenq = %d\n",sng_isup.tstaenq);
+		/**********************************************************************/
+		} else {
+		/**********************************************************************/
+			SS7_ERROR("Found an invalid parameter %s!\n", parm->val);
+			return FTDM_FAIL;
+		/**********************************************************************/
+		}
+
+		/* move to the next parameter */
+		parm = parm + 1;
+	/**************************************************************************/
+	} /* for (i = 0; i < num_parms; i++) */
+
+	/* default the interface to paused state */
+	sngss7_set_flag(&sng_isup, SNGSS7_PAUSED);
+
+	/* trickle down the SPC to all sub entities */
+	int	linkSetId;
+
+	linkSetId = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].linkSetId;
+
+	i = 1;
+	while (g_ftdm_sngss7_data.cfg.mtp3Link[i].id != 0) {
+		if (g_ftdm_sngss7_data.cfg.mtp3Link[i].linkSetId == linkSetId) {
+			g_ftdm_sngss7_data.cfg.mtp3Link[i].spc = g_ftdm_sngss7_data.cfg.spc;
+		}
+
+		i++;
+	}
+
+	/* pull values from the lower levels */
+	sng_isup.dpc = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].dpc;
+	sng_isup.switchType = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].switchType;
+	sng_isup.nwId = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].nwId;
+
+	sng_isap.switchType = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].switchType;
+
+	ftmod_ss7_fill_in_isap(&sng_isap);
+
+	sng_isup.isap = sng_isap.id;
+
+	ftmod_ss7_fill_in_isup_interface(&sng_isup);
+
+	/* setup the self mtp3 route */
+	i = sng_isup.mtpRouteId;
+
+	if(ftmod_ss7_fill_in_self_route(sng_isup.spc,
+									g_ftdm_sngss7_data.cfg.mtpRoute[i].linkType,
+									g_ftdm_sngss7_data.cfg.mtpRoute[i].switchType,
+									g_ftdm_sngss7_data.cfg.mtpRoute[i].ssf)) {
+
+		SS7_ERROR("Failed to fill in self route structure!\n");
+		return FTDM_FAIL;
+
+	}
+
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+static int ftmod_ss7_parse_cc_spans(ftdm_conf_node_t *cc_spans)
+{
+	ftdm_conf_node_t	*cc_span = NULL;
+
+	/* confirm that we are looking at cc_spans */
+	if (strcasecmp(cc_spans->name, "cc_spans")) {
+		SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"cc_spans\"!\n",cc_spans->name);
+		return FTDM_FAIL;
+	} else {
+		SS7_DEBUG("Parsing \"cc_spans\"...\n");
+	}
+
+	/* extract the cc_spans */
+	cc_span = cc_spans->child;
+
+	while (cc_span != NULL) {
+		/* parse the found cc_span */
+		if (ftmod_ss7_parse_cc_span(cc_span)) {
+			SS7_ERROR("Failed to parse \"cc_span\"\n");
+			return FTDM_FAIL;
+		}
+
+		/* go to the next cc_span */
+		cc_span = cc_span->next;
+	}
+
+	return FTDM_SUCCESS;
+
+}
+
+/******************************************************************************/
+static int ftmod_ss7_parse_cc_span(ftdm_conf_node_t *cc_span)
+{
+	sng_ccSpan_t			sng_ccSpan;
+	ftdm_conf_parameter_t	*parm = cc_span->parameters;
+	int						num_parms = cc_span->n_parameters;
+	int						flag_clg_nadi = 0;
+	int						flag_cld_nadi = 0;
+	int						i;
+	int						ret;
+
+	/* initalize the ccSpan structure */
+	memset(&sng_ccSpan, 0x0, sizeof(sng_ccSpan));
+
+	/* confirm that we are looking at an mtp_link */
+	if (strcasecmp(cc_span->name, "cc_span")) {
+		SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"cc_span\"!\n",cc_span->name);
+		return FTDM_FAIL;
+	} else {
+		SS7_DEBUG("Parsing \"cc_span\"...\n");
+	}
+
+
+	for (i = 0; i < num_parms; i++) {
+	/**************************************************************************/
+
+		/* try to match the parameter to what we expect */
+		if (!strcasecmp(parm->var, "name")) {
+		/**********************************************************************/
+			strcpy((char *)sng_ccSpan.name, parm->val);
+			SS7_DEBUG("Found an ccSpan named = %s\n", sng_ccSpan.name);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "id")) {
+		/**********************************************************************/
+			sng_ccSpan.id = atoi(parm->val);
+			SS7_DEBUG("Found an ccSpan id = %d\n", sng_ccSpan.id);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "procid")) {
+		/**********************************************************************/
+			sng_ccSpan.procId = atoi(parm->val);
+			SS7_DEBUG("Found an ccSpan procId = %d\n", sng_ccSpan.procId);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "ch_map")) {
+		/**********************************************************************/
+			strcpy(sng_ccSpan.ch_map, parm->val);
+			SS7_DEBUG("Found channel map %s\n", sng_ccSpan.ch_map);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "typeCntrl")) {
+		/**********************************************************************/
+			ret = find_cic_cntrl_in_map(parm->val);
+			if (ret == -1) {
+				SS7_ERROR("Found an invalid ccSpan typeCntrl = %s\n", parm->var);
+				return FTDM_FAIL;
+			} else {
+				sng_ccSpan.typeCntrl = sng_cic_cntrl_type_map[ret].tril_type;
+				SS7_DEBUG("Found an ccSpan typeCntrl = %s\n", sng_cic_cntrl_type_map[ret].sng_type);
+			}
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "ssf")) {
+		/**********************************************************************/
+			ret = find_ssf_type_in_map(parm->val);
+			if (ret == -1) {
+				SS7_ERROR("Found an invalid ccSpan ssf = %s\n", parm->var);
+				return FTDM_FAIL;
+			} else {
+				sng_ccSpan.ssf = sng_ssf_type_map[ret].tril_type;
+				SS7_DEBUG("Found an ccSpan ssf = %s\n", sng_ssf_type_map[ret].sng_type);
+			}
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "switchType")) {
+		/**********************************************************************/
+			ret = find_switch_type_in_map(parm->val);
+			if (ret == -1) {
+				SS7_ERROR("Found an invalid ccSpan switchType = %s\n", parm->var);
+				return FTDM_FAIL;
+			} else {
+				sng_ccSpan.switchType = sng_switch_type_map[ret].tril_isup_type;
+				SS7_DEBUG("Found an ccSpan switchType = %s\n", sng_switch_type_map[ret].sng_type);
+			}
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "cicbase")) {
+		/**********************************************************************/
+			sng_ccSpan.cicbase = atoi(parm->val);
+			SS7_DEBUG("Found a cicbase = %d\n", sng_ccSpan.cicbase);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "isup_interface")) {
+		/**********************************************************************/
+			sng_ccSpan.isupInf = atoi(parm->val);
+			SS7_DEBUG("Found an isup_interface = %d\n",sng_ccSpan.isupInf);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "min_digits")) {
+		/**********************************************************************/
+			sng_ccSpan.min_digits = atoi(parm->val);
+			SS7_DEBUG("Found a min_digits = %d\n",sng_ccSpan.min_digits);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "clg_nadi")) {
 		/**********************************************************************/
 			/* throw the flag so that we know we got this optional parameter */
 			flag_clg_nadi = 1;
-			sng_isup.clg_nadi = atoi(parm->val);
-			SS7_DEBUG("\tFound default CLG_NADI value = %d\n", sng_isup.clg_nadi);
+			sng_ccSpan.clg_nadi = atoi(parm->val);
+			SS7_DEBUG("Found default CLG_NADI parm->value = %d\n", sng_ccSpan.clg_nadi);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "cld_nadi")) {
 		/**********************************************************************/
 			/* throw the flag so that we know we got this optional parameter */
 			flag_cld_nadi = 1;
-			sng_isup.cld_nadi = atoi(parm->val);
-			SS7_DEBUG("\tFound default CLD_NADI value = %d\n", sng_isup.cld_nadi);
+			sng_ccSpan.cld_nadi = atoi(parm->val);
+			SS7_DEBUG("Found default CLD_NADI parm->value = %d\n", sng_ccSpan.cld_nadi);
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "obci_bita")) {
 		/**********************************************************************/
 			if (*parm->val == '1') {
-				sngss7_set_options(&sng_isup, SNGSS7_ACM_OBCI_BITA);
-				SS7_DEBUG("\tFound Optional Backwards Indicator: Bit A (early media) enable option\n");
+				sngss7_set_options(&sng_ccSpan, SNGSS7_ACM_OBCI_BITA);
+				SS7_DEBUG("Found Optional Backwards Indicator: Bit A (early media) enable option\n");
 			} else if (*parm->val == '0') {
-				sngss7_clear_options(&sng_isup, SNGSS7_ACM_OBCI_BITA);
-				SS7_DEBUG("\tFound Optional Backwards Indicator: Bit A (early media) disable option\n");
+				sngss7_clear_options(&sng_ccSpan, SNGSS7_ACM_OBCI_BITA);
+				SS7_DEBUG("Found Optional Backwards Indicator: Bit A (early media) disable option\n");
 			} else {
-				SS7_DEBUG("\tInvalid value for \"obci_bita\" option\n");
+				SS7_DEBUG("Invalid parm->value for obci_bita option\n");
 			}
 		/**********************************************************************/
 		} else if (!strcasecmp(parm->var, "lpa_on_cot")) {
 		/**********************************************************************/
 			if (*parm->val == '1') {
-				sngss7_set_options(&sng_isup, SNGSS7_LPA_FOR_COT);
-				SS7_DEBUG("\tFound Tx LPA on COT enable option\n");
+				sngss7_set_options(&sng_ccSpan, SNGSS7_LPA_FOR_COT);
+				SS7_DEBUG("Found Tx LPA on COT enable option\n");
 			} else if (*parm->val == '0') {
-				sngss7_clear_options(&sng_isup, SNGSS7_LPA_FOR_COT);
-				SS7_DEBUG("\tFound Tx LPA on COT disable option\n");
+				sngss7_clear_options(&sng_ccSpan, SNGSS7_LPA_FOR_COT);
+				SS7_DEBUG("Found Tx LPA on COT disable option\n");
 			} else {
-				SS7_DEBUG("\tInvalid value for \"lpa_on_cot\" option\n");
+				SS7_DEBUG("Invalid parm->value for lpa_on_cot option\n");
 			}
 		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "isup.t3")) {
+		/**********************************************************************/
+			sng_ccSpan.t3 = atoi(parm->val);
+			SS7_DEBUG("Found isup t3 = %d\n", sng_ccSpan.t3);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "isup.t12")) {
+		/**********************************************************************/
+			sng_ccSpan.t12 = atoi(parm->val);
+			SS7_DEBUG("Found isup t12 = %d\n", sng_ccSpan.t12);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "isup.t13")) {
+		/**********************************************************************/
+			sng_ccSpan.t13 = atoi(parm->val);
+			SS7_DEBUG("Found isup t13 = %d\n", sng_ccSpan.t13);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "isup.t14")) {
+		/**********************************************************************/
+			sng_ccSpan.t14 = atoi(parm->val);
+			SS7_DEBUG("Found isup t14 = %d\n", sng_ccSpan.t14);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "isup.t15")) {
+		/**********************************************************************/
+			sng_ccSpan.t15 = atoi(parm->val);
+			SS7_DEBUG("Found isup t15 = %d\n", sng_ccSpan.t15);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "isup.t16")) {
+		/**********************************************************************/
+			sng_ccSpan.t16 = atoi(parm->val);
+			SS7_DEBUG("Found isup t16 = %d\n", sng_ccSpan.t16);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "isup.t17")) {
+		/**********************************************************************/
+			sng_ccSpan.t17 = atoi(parm->val);
+			SS7_DEBUG("Found isup t17 = %d\n", sng_ccSpan.t17);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "isup.t35")) {
+		/**********************************************************************/
+			sng_ccSpan.t35 = atoi(parm->val);
+			SS7_DEBUG("Found isup t35 = %d\n",sng_ccSpan.t35);
+		/**********************************************************************/
+		} else if (!strcasecmp(parm->var, "isup.tval")) {
+		/**********************************************************************/
+			sng_ccSpan.tval = atoi(parm->val);
+			SS7_DEBUG("Found isup tval = %d\n", sng_ccSpan.tval);
+		/**********************************************************************/
 		} else {
-			SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val);
+		/**********************************************************************/
+			SS7_ERROR("Found an invalid parameter %s!\n", parm->var);
 			return FTDM_FAIL;
-
+		/**********************************************************************/
 		}
 
 		/* move to the next parameter */
 		parm = parm + 1;
-	}
+	/**************************************************************************/
+	} /* for (i = 0; i < num_parms; i++) */
 
 	/* check if the user filled in a nadi value by looking at flag */
 	if (!flag_cld_nadi) {
 		/* default the nadi value to national */
-		sng_isup.cld_nadi = 0x03;
+		sng_ccSpan.cld_nadi = 0x03;
 	}
 
 	if (!flag_clg_nadi) {
 		/* default the nadi value to national */
-		sng_isup.clg_nadi = 0x03;
+		sng_ccSpan.clg_nadi = 0x03;
 	}
 
-	/* check if the user requested min_digits value */
-	if (sng_isup.min_digits == 0) {
-		/* default to 7 */
-		sng_isup.min_digits = 7;
-	}
-		
-
-	/* trickle down the SPC to all sub entities */
-	linkSetId = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].linkSetId;
+	/* add this span to our global listing */
+	ftmod_ss7_fill_in_ccSpan(&sng_ccSpan);
 
-	i = 1;
-	while (g_ftdm_sngss7_data.cfg.mtpLink[i].id != 0) {
-		if (g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.linkSetId == linkSetId) {
-			g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.spc = g_ftdm_sngss7_data.cfg.spc;
-		}
+	/* make sure the isup interface structure has something in it */
+	if (g_ftdm_sngss7_data.cfg.isupIntf[sng_ccSpan.isupInf].id == 0) {
+		/* fill in the id, so that we know it exists */
+		g_ftdm_sngss7_data.cfg.isupIntf[sng_ccSpan.isupInf].id = sng_ccSpan.isupInf;
 
-		i++;
+		/* default the status to PAUSED */
+		sngss7_set_flag(&g_ftdm_sngss7_data.cfg.isupIntf[sng_ccSpan.isupInf], SNGSS7_PAUSED);
 	}
 
-	ftmod_ss7_fill_in_isap(&sng_isap);
-
-	sng_isup.isap = sng_isap.id;
-
-	ftmod_ss7_fill_in_isup_interface(&sng_isup);
-
 	return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
-static int ftmod_ss7_fill_in_mtpLink(sng_mtp_link_t *mtpLink)
+static int ftmod_ss7_fill_in_relay_channel(sng_relay_t *relay_channel)
 {
 	int i;
 
-	/* go through all the existing links and see if we find a match */
+	/* go through all the existing channels and see if we find a match */
 	i = 1;
-	while (g_ftdm_sngss7_data.cfg.mtpLink[i].id != 0) {
-		if ((g_ftdm_sngss7_data.cfg.mtpLink[i].mtp1.span == mtpLink->mtp1.span) &&
-			(g_ftdm_sngss7_data.cfg.mtpLink[i].mtp1.chan == mtpLink->mtp1.chan)) {
+	while (g_ftdm_sngss7_data.cfg.relay[i].id != 0) {
+		if ((g_ftdm_sngss7_data.cfg.relay[i].type == relay_channel->type) &&
+			(g_ftdm_sngss7_data.cfg.relay[i].port == relay_channel->port) &&
+			(g_ftdm_sngss7_data.cfg.relay[i].procId == relay_channel->procId) &&
+			(!strcasecmp(g_ftdm_sngss7_data.cfg.relay[i].hostname, relay_channel->hostname))) {
 
 			/* we have a match so break out of this loop */
 			break;
@@ -1355,179 +2030,273 @@ static int ftmod_ss7_fill_in_mtpLink(sng_mtp_link_t *mtpLink)
 		i++;
 	}
 
-	/* if the id value is 0 that means we didn't find the link */
-	if (g_ftdm_sngss7_data.cfg.mtpLink[i].id  == 0) {
-		mtpLink->id = i;
-		SS7_DEBUG("found new mtpLink on span=%d, chan=%d, id = %d\n", 
-					mtpLink->mtp1.span, 
-					mtpLink->mtp1.chan, 
-					mtpLink->id);
+		/* if the id value is 0 that means we didn't find the relay channel */
+	if (g_ftdm_sngss7_data.cfg.relay[i].id  == 0) {
+		relay_channel->id = i;
+		SS7_DEBUG("found new relay channel on type:%d, hostname:%s, port:%d, procId:%d, id = %d\n",
+					relay_channel->type,
+					relay_channel->hostname,
+					relay_channel->port,
+					relay_channel->procId, 
+					relay_channel->id);
+		sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY);
 	} else {
-		mtpLink->id = i;
-		SS7_DEBUG("found existing mtpLink on span=%d, chan=%d, id = %d\n", 
-					mtpLink->mtp1.span, 
-					mtpLink->mtp1.chan, 
-					mtpLink->id);
+		relay_channel->id = i;
+		SS7_DEBUG("found existing relay channel on type:%d, hostname:%s, port:%d, procId:%d, id = %d\n",
+					relay_channel->type,
+					relay_channel->hostname,
+					relay_channel->port,
+					relay_channel->procId, 
+					relay_channel->id);
 	}
 
-	/* fill in the information */
-	strncpy((char *)g_ftdm_sngss7_data.cfg.mtpLink[i].name, (char *)mtpLink->name, MAX_NAME_LEN-1);
+	g_ftdm_sngss7_data.cfg.relay[i].id		= relay_channel->id;
+	g_ftdm_sngss7_data.cfg.relay[i].type	= relay_channel->type;
+	g_ftdm_sngss7_data.cfg.relay[i].port	= relay_channel->port;
+	g_ftdm_sngss7_data.cfg.relay[i].procId	= relay_channel->procId;
+	strcpy(g_ftdm_sngss7_data.cfg.relay[i].hostname, relay_channel->hostname);
+	strcpy(g_ftdm_sngss7_data.cfg.relay[i].name, relay_channel->name);
 
-	g_ftdm_sngss7_data.cfg.mtpLink[i].id				= mtpLink->id;
+	/* if this is THE listen channel grab the procId and use it */
+	if (relay_channel->type == LRY_CT_TCP_LISTEN) {
+		g_ftdm_sngss7_data.cfg.procId = relay_channel->procId;
+	}
 
-	g_ftdm_sngss7_data.cfg.mtpLink[i].mtp1.span 		= mtpLink->mtp1.span;
-	g_ftdm_sngss7_data.cfg.mtpLink[i].mtp1.chan 		= mtpLink->mtp1.chan;
+	return FTDM_SUCCESS;
+}
 
-	g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.linkType		= mtpLink->mtp2.linkType;
-	g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.errorType	= mtpLink->mtp2.errorType;
-	g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.lssuLength	= mtpLink->mtp2.lssuLength;
-	g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.mtp1Id		= mtpLink->id;
+/******************************************************************************/
+static int ftmod_ss7_fill_in_mtp1_link(sng_mtp1_link_t *mtp1Link)
+{
+	int i = mtp1Link->id;
 
-	g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.priority		= mtpLink->mtp3.priority;
-	g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.linkType		= mtpLink->mtp3.linkType;
-	g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.switchType	= mtpLink->mtp3.switchType;
-	g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.apc			= mtpLink->mtp3.apc;
-	g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.spc			= g_ftdm_sngss7_data.cfg.spc;
-	g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.ssf			= mtpLink->mtp3.ssf;
-	g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.slc			= mtpLink->mtp3.slc;
-	g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.linkSetId	= mtpLink->mtp3.linkSetId;
-	g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.mtp2Id		= mtpLink->id;
+	/* check if this id value has been used already */
+	if (g_ftdm_sngss7_data.cfg.mtp1Link[i].id == 0) {
+		SS7_DEBUG("Found new MTP1 Link: id=%d, name=%s\n", mtp1Link->id, mtp1Link->name);
+		sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP1);
+	} else {
+		SS7_DEBUG("Found an existing MTP1 Link: id=%d, name=%s (old name=%s)\n", 
+					mtp1Link->id, 
+					mtp1Link->name,
+					g_ftdm_sngss7_data.cfg.mtp1Link[i].name);
+	}
+
+	/* copy over the values */
+	strcpy((char *)g_ftdm_sngss7_data.cfg.mtp1Link[i].name, (char *)mtp1Link->name);
+
+	g_ftdm_sngss7_data.cfg.mtp1Link[i].id		= mtp1Link->id;
+	g_ftdm_sngss7_data.cfg.mtp1Link[i].span		= mtp1Link->span;
+	g_ftdm_sngss7_data.cfg.mtp1Link[i].chan		= mtp1Link->chan;
+
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+static int ftmod_ss7_fill_in_mtp2_link(sng_mtp2_link_t *mtp2Link)
+{
+	int i = mtp2Link->id;
+
+	/* check if this id value has been used already */
+	if (g_ftdm_sngss7_data.cfg.mtp2Link[i].id == 0) {
+		SS7_DEBUG("Found new MTP2 Link: id=%d, name=%s\n", mtp2Link->id, mtp2Link->name);
+		sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2);
+	} else {
+		SS7_DEBUG("Found an existing MTP2 Link: id=%d, name=%s (old name=%s)\n", 
+					mtp2Link->id, 
+					mtp2Link->name,
+					g_ftdm_sngss7_data.cfg.mtp2Link[i].name);
+	}
+
+	/* copy over the values */
+	strcpy((char *)g_ftdm_sngss7_data.cfg.mtp2Link[i].name, (char *)mtp2Link->name);
 
-	if ( mtpLink->mtp2.t1 != 0 ) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t1		= mtpLink->mtp2.t1;
+	g_ftdm_sngss7_data.cfg.mtp2Link[i].id			= mtp2Link->id;
+	g_ftdm_sngss7_data.cfg.mtp2Link[i].lssuLength	= mtp2Link->lssuLength;
+	g_ftdm_sngss7_data.cfg.mtp2Link[i].errorType	= mtp2Link->errorType;
+	g_ftdm_sngss7_data.cfg.mtp2Link[i].linkType		= mtp2Link->linkType;
+	g_ftdm_sngss7_data.cfg.mtp2Link[i].mtp1Id		= mtp2Link->mtp1Id;
+	g_ftdm_sngss7_data.cfg.mtp2Link[i].mtp1ProcId	= mtp2Link->mtp1ProcId;
+
+	if ( mtp2Link->t1 != 0 ) {
+		g_ftdm_sngss7_data.cfg.mtp2Link[i].t1		= mtp2Link->t1;
 	}else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t1		= 500;
+		g_ftdm_sngss7_data.cfg.mtp2Link[i].t1		= 500;
 	}
-	if ( mtpLink->mtp2.t2 != 0 ) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t2		= mtpLink->mtp2.t2;
+
+	if ( mtp2Link->t2 != 0 ) {
+		g_ftdm_sngss7_data.cfg.mtp2Link[i].t2		= mtp2Link->t2;
 	}else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t2		= 250;
+		g_ftdm_sngss7_data.cfg.mtp2Link[i].t2		= 250;
 	}
-	if ( mtpLink->mtp2.t3 != 0 ) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t3		= mtpLink->mtp2.t3;
+
+	if ( mtp2Link->t3 != 0 ) {
+		g_ftdm_sngss7_data.cfg.mtp2Link[i].t3		= mtp2Link->t3;
 	}else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t3		= 20;
+		g_ftdm_sngss7_data.cfg.mtp2Link[i].t3		= 20;
 	}
-	if ( mtpLink->mtp2.t4n != 0 ) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t4n		= mtpLink->mtp2.t4n;
+
+	if ( mtp2Link->t4n != 0 ) {
+		g_ftdm_sngss7_data.cfg.mtp2Link[i].t4n		= mtp2Link->t4n;
 	}else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t4n		= 80;
+		g_ftdm_sngss7_data.cfg.mtp2Link[i].t4n		= 80;
 	}
-	if ( mtpLink->mtp2.t4e != 0 ) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t4e		= mtpLink->mtp2.t4e;
+
+	if ( mtp2Link->t4e != 0 ) {
+		g_ftdm_sngss7_data.cfg.mtp2Link[i].t4e		= mtp2Link->t4e;
 	}else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t4e		= 5;
+		g_ftdm_sngss7_data.cfg.mtp2Link[i].t4e		= 5;
 	}
-	if ( mtpLink->mtp2.t5 != 0 ) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t5		= mtpLink->mtp2.t5;
+
+	if ( mtp2Link->t5 != 0 ) {
+		g_ftdm_sngss7_data.cfg.mtp2Link[i].t5		= mtp2Link->t5;
 	}else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t5		= 1;
+		g_ftdm_sngss7_data.cfg.mtp2Link[i].t5		= 1;
 	}
-	if ( mtpLink->mtp2.t6 != 0 ) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t6		= mtpLink->mtp2.t6;
+
+	if ( mtp2Link->t6 != 0 ) {
+		g_ftdm_sngss7_data.cfg.mtp2Link[i].t6		= mtp2Link->t6;
 	}else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t6		= 60;
+		g_ftdm_sngss7_data.cfg.mtp2Link[i].t6		= 60;
 	}
-	if ( mtpLink->mtp2.t7 != 0 ) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t7		= mtpLink->mtp2.t7;
+
+	if ( mtp2Link->t7 != 0 ) {
+		g_ftdm_sngss7_data.cfg.mtp2Link[i].t7		= mtp2Link->t7;
 	}else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t7		= 40;
+		g_ftdm_sngss7_data.cfg.mtp2Link[i].t7		= 40;
 	}
 
-	if (mtpLink->mtp3.t1 != 0) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t1		= mtpLink->mtp3.t1;
-	} else { 
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t1		= 8;
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+static int ftmod_ss7_fill_in_mtp3_link(sng_mtp3_link_t *mtp3Link)
+{
+	int i = mtp3Link->id;
+
+	/* check if this id value has been used already */
+	if (g_ftdm_sngss7_data.cfg.mtp3Link[i].id == 0) {
+		SS7_DEBUG("Found new MTP3 Link: id=%d, name=%s\n", mtp3Link->id, mtp3Link->name);
+		sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP3);
+	} else {
+		SS7_DEBUG("Found an existing MTP3 Link: id=%d, name=%s (old name=%s)\n", 
+					mtp3Link->id, 
+					mtp3Link->name,
+					g_ftdm_sngss7_data.cfg.mtp3Link[i].name);
+	}
+
+	/* copy over the values */
+	strcpy((char *)g_ftdm_sngss7_data.cfg.mtp3Link[i].name, (char *)mtp3Link->name);
+
+	g_ftdm_sngss7_data.cfg.mtp3Link[i].id			= mtp3Link->id;
+	g_ftdm_sngss7_data.cfg.mtp3Link[i].priority		= mtp3Link->priority;
+	g_ftdm_sngss7_data.cfg.mtp3Link[i].linkType		= mtp3Link->linkType;
+	g_ftdm_sngss7_data.cfg.mtp3Link[i].switchType	= mtp3Link->switchType;
+	g_ftdm_sngss7_data.cfg.mtp3Link[i].apc			= mtp3Link->apc;
+	g_ftdm_sngss7_data.cfg.mtp3Link[i].spc			= mtp3Link->spc;	/* unknown at this time */
+	g_ftdm_sngss7_data.cfg.mtp3Link[i].ssf			= mtp3Link->ssf;
+	g_ftdm_sngss7_data.cfg.mtp3Link[i].slc			= mtp3Link->slc;
+	g_ftdm_sngss7_data.cfg.mtp3Link[i].linkSetId	= mtp3Link->linkSetId;
+	g_ftdm_sngss7_data.cfg.mtp3Link[i].mtp2Id		= mtp3Link->mtp2Id;
+	g_ftdm_sngss7_data.cfg.mtp3Link[i].mtp2ProcId	= mtp3Link->mtp2ProcId;
+
+	if (mtp3Link->t1 != 0) {
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t1		= mtp3Link->t1;
+	} else {
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t1		= 8;
+	}
+	if (mtp3Link->t2 != 0) {
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t2		= mtp3Link->t2;
+	} else {
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t2		= 14;
 	}
-	if (mtpLink->mtp3.t2 != 0) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t2		= mtpLink->mtp3.t2;
+	if (mtp3Link->t3 != 0) {
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t3		= mtp3Link->t3;
 	} else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t2		= 14;
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t3		= 8;
 	}
-	if (mtpLink->mtp3.t3 != 0) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t3		= mtpLink->mtp3.t3;
+	if (mtp3Link->t4 != 0) {
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t4		= mtp3Link->t4;
 	} else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t3		= 8;
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t4		= 8;
 	}
-	if (mtpLink->mtp3.t4 != 0) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t4		= mtpLink->mtp3.t4;
+	if (mtp3Link->t5 != 0) {
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t5		= mtp3Link->t5;
 	} else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t4		= 8;
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t5		= 8;
 	}
-	if (mtpLink->mtp3.t5 != 0) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t5		= mtpLink->mtp3.t5;
+	if (mtp3Link->t7 != 0) {
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t7		= mtp3Link->t7;
 	} else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t5		= 8;
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t7		= 15;
 	}
-	if (mtpLink->mtp3.t7 != 0) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t7		= mtpLink->mtp3.t7;
+	if (mtp3Link->t12 != 0) {
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t12		= mtp3Link->t12;
 	} else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t7		= 15;
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t12		= 15;
 	}
-	if (mtpLink->mtp3.t12 != 0) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t12		= mtpLink->mtp3.t12;
+	if (mtp3Link->t13 != 0) {
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t13		= mtp3Link->t13;
 	} else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t12		= 15;
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t13		= 15;
 	}
-	if (mtpLink->mtp3.t13 != 0) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t13		= mtpLink->mtp3.t13;
+	if (mtp3Link->t14 != 0) {
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t14		= mtp3Link->t14;
 	} else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t13		= 15;
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t14		= 30;
 	}
-	if (mtpLink->mtp3.t14 != 0) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t14		= mtpLink->mtp3.t14;
+	if (mtp3Link->t17 != 0) {
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t17		= mtp3Link->t17;
 	} else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t14		= 30;
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t17		= 15;
 	}
-	if (mtpLink->mtp3.t17 != 0) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t17		= mtpLink->mtp3.t17;
+	if (mtp3Link->t22 != 0) {
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t22		= mtp3Link->t22;
 	} else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t17		= 15;
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t22		= 1800;
 	}
-	if (mtpLink->mtp3.t22 != 0) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t22		= mtpLink->mtp3.t22;
+	if (mtp3Link->t23 != 0) {
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t23		= mtp3Link->t23;
 	} else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t22		= 1800;
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t23		= 1800;
 	}
-	if (mtpLink->mtp3.t23 != 0) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t23		= mtpLink->mtp3.t23;
+	if (mtp3Link->t24 != 0) {
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t24		= mtp3Link->t24;
 	} else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t23		= 1800;
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t24		= 5;
 	}
-	if (mtpLink->mtp3.t24 != 0) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t24		= mtpLink->mtp3.t24;
+	if (mtp3Link->t31 != 0) {
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t31		= mtp3Link->t31;
 	} else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t24		= 5;
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t31		= 50;
 	}
-	if (mtpLink->mtp3.t31 != 0) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t31		= mtpLink->mtp3.t31;
+	if (mtp3Link->t32 != 0) {
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t32		= mtp3Link->t32;
 	} else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t31		= 50;
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t32		= 120;
 	}
-	if (mtpLink->mtp3.t32 != 0) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t32		= mtpLink->mtp3.t32;
+	if (mtp3Link->t33 != 0) {
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t33		= mtp3Link->t33;
 	} else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t32		= 120;
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t33		= 3000;
 	}
-	if (mtpLink->mtp3.t33 != 0) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t33		= mtpLink->mtp3.t33;
+	if (mtp3Link->t34 != 0) {
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t34		= mtp3Link->t34;
 	} else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t33		= 3000;
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].t34		= 600;
 	}
-	if (mtpLink->mtp3.t34 != 0) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t34		= mtpLink->mtp3.t34;
+	if (mtp3Link->tbnd != 0) {
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].tbnd		= mtp3Link->tbnd;
 	} else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t34		= 600;
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].tbnd		= 30000;
 	}
-	if (mtpLink->mtp3.tflc != 0) {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.tflc		= mtpLink->mtp3.tflc;
+	if (mtp3Link->tflc != 0) {
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].tflc		= mtp3Link->tflc;
 	} else {
-		g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.tflc		= 300;
+		g_ftdm_sngss7_data.cfg.mtp3Link[i].tflc		= 300;
 	}
-	return (mtpLink->id);
+	return FTDM_SUCCESS;
 }
 
-
 /******************************************************************************/
 static int ftmod_ss7_fill_in_mtpLinkSet(sng_link_set_t *mtpLinkSet)
 {
@@ -1537,9 +2306,6 @@ static int ftmod_ss7_fill_in_mtpLinkSet(sng_link_set_t *mtpLinkSet)
 
 	g_ftdm_sngss7_data.cfg.mtpLinkSet[i].id			= mtpLinkSet->id;
 	g_ftdm_sngss7_data.cfg.mtpLinkSet[i].apc		= mtpLinkSet->apc;
-	g_ftdm_sngss7_data.cfg.mtpLinkSet[i].linkType	= mtpLinkSet->linkType;
-	g_ftdm_sngss7_data.cfg.mtpLinkSet[i].switchType	= mtpLinkSet->switchType;
-	g_ftdm_sngss7_data.cfg.mtpLinkSet[i].ssf		= mtpLinkSet->ssf;
 
 	/* these values are filled in as we find routes and start allocating cmbLinkSetIds */
 	g_ftdm_sngss7_data.cfg.mtpLinkSet[i].minActive	= mtpLinkSet->minActive;
@@ -1550,28 +2316,25 @@ static int ftmod_ss7_fill_in_mtpLinkSet(sng_link_set_t *mtpLinkSet)
 /******************************************************************************/
 static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route)
 {
-	int i;
-
-	/* go through all the existing routes and see if we find a match */
-	i = 1;
-	while (g_ftdm_sngss7_data.cfg.mtpRoute[i].id != 0) {
-		if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpRoute[i].name, mtp3_route->name)) {
-			/* we have a match so break out of this loop */
-			break;
-		}
-		/* move on to the next one */
-		i++;
-	}
+	int i = mtp3_route->id;
 
+	/* check if this id value has been used already */
 	if (g_ftdm_sngss7_data.cfg.mtpRoute[i].id == 0) {
-		mtp3_route->id = i;
-		SS7_DEBUG("found new mtp3_route, id is = %d\n", mtp3_route->id);
+		SS7_DEBUG("Found new MTP3 Link: id=%d, name=%s\n", mtp3_route->id, mtp3_route->name);
 	} else {
-		mtp3_route->id = i;
-		SS7_DEBUG("found existing mtp3_route, id is = %d\n", mtp3_route->id);
+		SS7_DEBUG("Found an existing MTP3 Link: id=%d, name=%s (old name=%s)\n", 
+					mtp3_route->id, 
+					mtp3_route->name,
+					g_ftdm_sngss7_data.cfg.mtpRoute[i].name);
 	}
 
-	strncpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[i].name, (char *)mtp3_route->name, MAX_NAME_LEN-1);
+	/* fill in the cmbLinkSet in the linkset structure */
+	int tmp = g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3_route->linkSetId].numLinks;
+
+	g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3_route->linkSetId].links[tmp] = mtp3_route->cmbLinkSetId;
+	g_ftdm_sngss7_data.cfg.mtpLinkSet[mtp3_route->linkSetId].numLinks++;
+
+	strcpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[i].name, (char *)mtp3_route->name);
 
 	g_ftdm_sngss7_data.cfg.mtpRoute[i].id			= mtp3_route->id;
 	g_ftdm_sngss7_data.cfg.mtpRoute[i].dpc			= mtp3_route->dpc;
@@ -1662,11 +2425,9 @@ static int ftmod_ss7_fill_in_nsap(sng_route_t *mtp3_route)
 
 	if (g_ftdm_sngss7_data.cfg.nsap[i].id == 0) {
 		g_ftdm_sngss7_data.cfg.nsap[i].id = i;
-		 mtp3_route->nwId = i;
 		SS7_DEBUG("found new mtp3_isup interface, id is = %d\n", g_ftdm_sngss7_data.cfg.nsap[i].id);
 	} else {
 		g_ftdm_sngss7_data.cfg.nsap[i].id = i;
-		 mtp3_route->nwId = i;
 		SS7_DEBUG("found existing mtp3_isup interface, id is = %d\n", g_ftdm_sngss7_data.cfg.nsap[i].id);
 	}
 	
@@ -1683,26 +2444,17 @@ static int ftmod_ss7_fill_in_nsap(sng_route_t *mtp3_route)
 /******************************************************************************/
 static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup)
 {
-	int i;
-
-	/* go through all the existing interfaces and see if we find a match */
-	i = 1;
-	while (g_ftdm_sngss7_data.cfg.isupIntf[i].id != 0) {
-		if (!strcasecmp(g_ftdm_sngss7_data.cfg.isupIntf[i].name, sng_isup->name)) {
-
-			/* we have a match so break out of this loop */
-			break;
-		}
-		/* move on to the next one */
-		i++;
-	}
+	int i = sng_isup->id;
 
+	/* check if this id value has been used already */
 	if (g_ftdm_sngss7_data.cfg.isupIntf[i].id == 0) {
-		sng_isup->id = i;
-		SS7_DEBUG("found new isup interface, id is = %d\n", sng_isup->id);
+		SS7_DEBUG("Found new ISUP Interface: id=%d, name=%s\n", sng_isup->id, sng_isup->name);
+		sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_ISUP);
 	} else {
-		sng_isup->id = i;
-		SS7_DEBUG("found existing isup interface, id is = %d\n", sng_isup->id);
+		SS7_DEBUG("Found an existing ISUP Interface: id=%d, name=%s (old name=%s)\n", 
+					sng_isup->id, 
+					sng_isup->name,
+					g_ftdm_sngss7_data.cfg.isupIntf[i].name);
 	}
 
 	strncpy((char *)g_ftdm_sngss7_data.cfg.isupIntf[i].name, (char *)sng_isup->name, MAX_NAME_LEN-1);
@@ -1715,9 +2467,6 @@ static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup)
 	g_ftdm_sngss7_data.cfg.isupIntf[i].switchType	= sng_isup->switchType;
 	g_ftdm_sngss7_data.cfg.isupIntf[i].ssf			= sng_isup->ssf;
 	g_ftdm_sngss7_data.cfg.isupIntf[i].isap			= sng_isup->isap;
-	g_ftdm_sngss7_data.cfg.isupIntf[i].cld_nadi		= sng_isup->cld_nadi;
-	g_ftdm_sngss7_data.cfg.isupIntf[i].clg_nadi		= sng_isup->clg_nadi;
-	g_ftdm_sngss7_data.cfg.isupIntf[i].min_digits	= sng_isup->min_digits;
 	g_ftdm_sngss7_data.cfg.isupIntf[i].options		= sng_isup->options;
 	if (sng_isup->t4 != 0) {
 		g_ftdm_sngss7_data.cfg.isupIntf[i].t4		= sng_isup->t4;
@@ -1799,11 +2548,6 @@ static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup)
 	} else {
 		g_ftdm_sngss7_data.cfg.isupIntf[i].t32		= 30;
 	}
-	if (sng_isup->t35 != 0) {
-		g_ftdm_sngss7_data.cfg.isupIntf[i].t35		= sng_isup->t35;
-	} else {
-		g_ftdm_sngss7_data.cfg.isupIntf[i].t35		= 170;
-	}
 	if (sng_isup->t37 != 0) {
 		g_ftdm_sngss7_data.cfg.isupIntf[i].t37		= sng_isup->t37;
 	} else {
@@ -1857,10 +2601,10 @@ static int ftmod_ss7_fill_in_isap(sng_isap_t *sng_isap)
 
 	if (g_ftdm_sngss7_data.cfg.isap[i].id == 0) {
 		sng_isap->id = i;
-		SS7_DEBUG("found new isup to cc interface, id is = %d\n", g_ftdm_sngss7_data.cfg.isap[i].id);
+		SS7_DEBUG("found new isup to cc interface, id is = %d\n", sng_isap->id);
 	} else {
 		sng_isap->id = i;
-		SS7_DEBUG("found existing isup to cc interface, id is = %d\n", g_ftdm_sngss7_data.cfg.isap[i].id);
+		SS7_DEBUG("found existing isup to cc interface, id is = %d\n", sng_isap->id);
 	}
 
 	g_ftdm_sngss7_data.cfg.isap[i].id 			= sng_isap->id;
@@ -2013,226 +2757,213 @@ static int ftmod_ss7_fill_in_self_route(int spc, int linkType, int switchType, i
 }
 
 /******************************************************************************/
-static int ftmod_ss7_fill_in_circuits(sng_isupCkt_t *isupCkt)
+static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan)
 {
-	sngss7_chan_data_t	*ss7_info = NULL;
-	ftdm_channel_t		*ftdmchan = NULL;
 	sng_timeslot_t		timeslot;
-	int					count;
-	int					i;
+	sngss7_chan_data_t	*ss7_info = NULL;
 	int					x;
+	int					count = 1;
 
-	count = 1;
-
-	while (isupCkt->ch_map[0] != '\0') {
+	while (ccSpan->ch_map[0] != '\0') {
+	/**************************************************************************/
 
-		 /* pull out the next timeslot */
-		if (ftmod_ss7_next_timeslot(isupCkt->ch_map, &timeslot)) {
+		/* pull out the next timeslot */
+		if (ftmod_ss7_next_timeslot(ccSpan->ch_map, &timeslot)) {
 			SS7_ERROR("Failed to parse the channel map!\n");
 			return FTDM_FAIL;
 		}
 
-		if ((timeslot.siglink) || (timeslot.gap)) {
-			/* try to find the channel in the circuits structure*/
-			x = 1;
-			while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
-				if ((g_ftdm_sngss7_data.cfg.isupCkt[x].chan == count) &&
-					(g_ftdm_sngss7_data.cfg.isupCkt[x].span == isupCkt->span->channels[1]->physical_span_id)) {
-
-					SS7_DEVEL_DEBUG("Circuit for span=%d, chan=%d is already exists...id=%d\n",
-								isupCkt->span->channels[1]->physical_span_id,
-								count,
-								x);
-
-					/* we have a match so this circuit already exists in the structure */
-					break;
-				}
-				/* move to the next circuit */
-				x++;
-			} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */
-
-			/* check why we exited the while loop */
-			if (g_ftdm_sngss7_data.cfg.isupCkt[x].id == 0) {
-				SS7_DEVEL_DEBUG("Circuit for span=%d, chan=%d is new...id=%d\n",
-				isupCkt->span->channels[1]->physical_span_id,
-				count,
-				x);
-
-				/* prepare the global info sturcture */
-				ss7_info = ftdm_calloc(1, sizeof(sngss7_chan_data_t));
-				ss7_info->ftdmchan = NULL;
-				ss7_info->circuit = &g_ftdm_sngss7_data.cfg.isupCkt[x];
-
-				/* circuit is new so fill in the needed information */
-				g_ftdm_sngss7_data.cfg.isupCkt[x].id		  	= x;
-				g_ftdm_sngss7_data.cfg.isupCkt[x].span			= isupCkt->span->channels[1]->physical_span_id;
-				g_ftdm_sngss7_data.cfg.isupCkt[x].chan			= count;
-				if (timeslot.siglink) {
-					g_ftdm_sngss7_data.cfg.isupCkt[x].type		= SIG;
-				} else {
-					g_ftdm_sngss7_data.cfg.isupCkt[x].type		= HOLE;
-				}
-
-				if (timeslot.channel) {
-					g_ftdm_sngss7_data.cfg.isupCkt[x].cic		= isupCkt->cicbase;
-					isupCkt->cicbase++;
-				} else {
-					g_ftdm_sngss7_data.cfg.isupCkt[x].cic		= 0;
-				}
-				g_ftdm_sngss7_data.cfg.isupCkt[x].infId	   		= isupCkt->isupInf;
-				g_ftdm_sngss7_data.cfg.isupCkt[x].typeCntrl   	= isupCkt->typeCntrl;
-				g_ftdm_sngss7_data.cfg.isupCkt[x].ssf			= g_ftdm_sngss7_data.cfg.isupIntf[isupCkt->isupInf].ssf;
-				g_ftdm_sngss7_data.cfg.isupCkt[x].obj			= ss7_info;
-
-			} /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].id == 0) */
-
-			/* increment the span channel count */
-			count++;
-
-		} else { /* if ((timeslot.siglink) || (timeslot.gap)) */
-			/* find the ftdm the channel structure for this channel*/
-			i = 1;
-			while (isupCkt->span->channels[i] != NULL) {
-				if (isupCkt->span->channels[i]->physical_chan_id == timeslot.channel) {
-					break;
-				}
-				i++;
-			} /* while (span->channels[i] != NULL) */
-
-			if (isupCkt->span->channels[i] == NULL) {
-				/* we weren't able to find the channel in the ftdm channels */
-				SS7_ERROR("Unable to find the requested channel %d in the FreeTDM channels!\n", timeslot.channel);
-				return FTDM_FAIL;
-			} else {
-				ftdmchan = isupCkt->span->channels[i];
-			}
+		/* find the spot in master array for this circuit */
+		x = (ccSpan->procId * 1000) + count;
 
-			/* try to find a match for the physical span and chan */
-			x = 1;
-			while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
-				if ((g_ftdm_sngss7_data.cfg.isupCkt[x].chan == ftdmchan->physical_chan_id) && 
-					(g_ftdm_sngss7_data.cfg.isupCkt[x].span == ftdmchan->physical_span_id)) {
-
-					/* we have a match so this circuit already exists in the structure */
-					break;
-				}
-				/* move to the next circuit */
-				x++;
-			} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */
-
-			/* check why we exited the while loop */
-			if (g_ftdm_sngss7_data.cfg.isupCkt[x].id == 0) {
-				SS7_DEVEL_DEBUG("Circuit for span=%d, chan=%d is new...id=%d\n",
-				ftdmchan->physical_span_id,
-				ftdmchan->physical_chan_id,
-				x);
-
-				/* prepare the global info sturcture */
-				ss7_info = ftdm_calloc(1, sizeof(sngss7_chan_data_t));
-				ss7_info->ftdmchan = ftdmchan;
-				ss7_info->circuit = &g_ftdm_sngss7_data.cfg.isupCkt[x];
-				ftdmchan->call_data = ss7_info;
-
-				/* prepare the timer structures */
-				ss7_info->t35.sched			= ((sngss7_span_data_t *)isupCkt->span->signal_data)->sched;
-				ss7_info->t35.counter		= 1;
-				ss7_info->t35.beat			= g_ftdm_sngss7_data.cfg.isupIntf[isupCkt->isupInf].t35*100; /* beat is in ms, t35 is in 100ms */
-				ss7_info->t35.callback		= handle_isup_t35;
-				ss7_info->t35.sngss7_info	= ss7_info;
-
-				/* circuit is new so fill in the needed information */
-				g_ftdm_sngss7_data.cfg.isupCkt[x].id		= x;
-				g_ftdm_sngss7_data.cfg.isupCkt[x].span		= ftdmchan->physical_span_id;
-				g_ftdm_sngss7_data.cfg.isupCkt[x].chan		= ftdmchan->physical_chan_id;
-				g_ftdm_sngss7_data.cfg.isupCkt[x].type		= VOICE;
-				g_ftdm_sngss7_data.cfg.isupCkt[x].cic		= isupCkt->cicbase;
-				g_ftdm_sngss7_data.cfg.isupCkt[x].infId		= isupCkt->isupInf;
-				g_ftdm_sngss7_data.cfg.isupCkt[x].typeCntrl	= isupCkt->typeCntrl;
-				if (isupCkt->t3 == 0) {
-					g_ftdm_sngss7_data.cfg.isupCkt[x].t3	= 1200;
-				} else {
-					g_ftdm_sngss7_data.cfg.isupCkt[x].t3	= isupCkt->t3;
-				}
-				if (isupCkt->t12 == 0) {
-					g_ftdm_sngss7_data.cfg.isupCkt[x].t12	= 300;
-				} else {
-					g_ftdm_sngss7_data.cfg.isupCkt[x].t12	= isupCkt->t12;
-				}
-				if (isupCkt->t13 == 0) {
-					g_ftdm_sngss7_data.cfg.isupCkt[x].t13	= 3000;
-				} else {
-					g_ftdm_sngss7_data.cfg.isupCkt[x].t13	= isupCkt->t13;
-				}
-				if (isupCkt->t14 == 0) {
-					g_ftdm_sngss7_data.cfg.isupCkt[x].t14	= 300;
-				} else {
-					g_ftdm_sngss7_data.cfg.isupCkt[x].t14	= isupCkt->t14;
-				}
-				if (isupCkt->t15 == 0) {
-					g_ftdm_sngss7_data.cfg.isupCkt[x].t15	= 3000;
-				} else {
-					g_ftdm_sngss7_data.cfg.isupCkt[x].t15	= isupCkt->t15;
-				}
-				if (isupCkt->t16 == 0) {
-					g_ftdm_sngss7_data.cfg.isupCkt[x].t16	= 300;
-				} else {
-					g_ftdm_sngss7_data.cfg.isupCkt[x].t16	= isupCkt->t16;
-				}
-				if (isupCkt->t17 == 0) {
-					g_ftdm_sngss7_data.cfg.isupCkt[x].t17	= 3000;
-				} else {
-					g_ftdm_sngss7_data.cfg.isupCkt[x].t17	= isupCkt->t17;
-				}
-				if (isupCkt->tval == 0) {
-					g_ftdm_sngss7_data.cfg.isupCkt[x].tval	= 10;
-				} else {
-					g_ftdm_sngss7_data.cfg.isupCkt[x].tval	= isupCkt->tval;
-				}
-				g_ftdm_sngss7_data.cfg.isupCkt[x].obj		= ss7_info;
-				g_ftdm_sngss7_data.cfg.isupCkt[x].ssf		= g_ftdm_sngss7_data.cfg.isupIntf[isupCkt->isupInf].ssf;
-
-				/* increment the cicbase */
-				isupCkt->cicbase++;
-			} else { /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].id == 0) */
-				SS7_DEBUG("Circuit for span=%d, chan=%d is new...id=%d\n",
-									ftdmchan->physical_span_id,
-									ftdmchan->physical_chan_id,
-									x);
-
-				/* for now make sure ss7_info is set to null */
-				ss7_info = NULL;
-
-				/* KONRAD FIX ME -> confirm that it is the same circuit */
-			}  /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].id == 0) */
-
-			/* increment the span channel count */
-			count++;
-		} /* if ((timeslot.siglink) || (timeslot.gap)) */
-
-		if (ss7_info == NULL) {
-			SS7_ERROR("KONRAD -> circuit was not configured !\n");
-			return FTDM_FAIL;
+		/* check if this circuit has already been filled in */
+		if (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+			SS7_DEVEL_DEBUG("Filling in circuit that already exists...%d\n", x);
 		}
 
-		if (ss7_info->ftdmchan == NULL) {
-			SS7_INFO("Added span = %d, chan = %d, cic = %d, FTDM chan = %d, ISUP cirId = %d\n",
-						g_ftdm_sngss7_data.cfg.isupCkt[x].span,
-						g_ftdm_sngss7_data.cfg.isupCkt[x].chan,
-						g_ftdm_sngss7_data.cfg.isupCkt[x].cic,
-						0,
-						g_ftdm_sngss7_data.cfg.isupCkt[x].id);
+		/* prepare the global info sturcture */
+		ss7_info = ftdm_calloc(1, sizeof(sngss7_chan_data_t));
+		ss7_info->ftdmchan = NULL;
+		ss7_info->circuit = &g_ftdm_sngss7_data.cfg.isupCkt[x];
+
+		g_ftdm_sngss7_data.cfg.isupCkt[x].obj			= ss7_info;
+
+		/* fill in the rest of the global structure */
+		g_ftdm_sngss7_data.cfg.isupCkt[x].procId	  	= ccSpan->procId;
+		g_ftdm_sngss7_data.cfg.isupCkt[x].id		  	= x;
+		g_ftdm_sngss7_data.cfg.isupCkt[x].ccSpanId		= ccSpan->id;
+		g_ftdm_sngss7_data.cfg.isupCkt[x].span			= 0;
+		g_ftdm_sngss7_data.cfg.isupCkt[x].chan			= count;
+
+		if (timeslot.siglink) {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].type		= SIG;
+		} else if (timeslot.gap) {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].type		= HOLE;
 		} else {
-			SS7_INFO("Added span = %d, chan = %d, cic = %d, FTDM chan = %d, ISUP cirId = %d\n",
-						g_ftdm_sngss7_data.cfg.isupCkt[x].span,
-						g_ftdm_sngss7_data.cfg.isupCkt[x].chan,
-						g_ftdm_sngss7_data.cfg.isupCkt[x].cic,
-						ss7_info->ftdmchan->chan_id,
-						g_ftdm_sngss7_data.cfg.isupCkt[x].id);
+			g_ftdm_sngss7_data.cfg.isupCkt[x].type		= VOICE;
+			
+			/* throw the flag to indicate that we need to start call control */
+			sngss7_set_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC);
 		}
 
-	} /* while (ch_map[0] != '\0') */
+		if (timeslot.channel) {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].cic		= ccSpan->cicbase;
+			ccSpan->cicbase++;
+		} else {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].cic		= 0;
+		}
 
-	return 0;
+		g_ftdm_sngss7_data.cfg.isupCkt[x].infId	   		= ccSpan->isupInf;
+		g_ftdm_sngss7_data.cfg.isupCkt[x].typeCntrl   	= ccSpan->typeCntrl;
+		g_ftdm_sngss7_data.cfg.isupCkt[x].ssf			= ccSpan->ssf;
+		g_ftdm_sngss7_data.cfg.isupCkt[x].cld_nadi		= ccSpan->cld_nadi;
+		g_ftdm_sngss7_data.cfg.isupCkt[x].clg_nadi		= ccSpan->clg_nadi;
+		g_ftdm_sngss7_data.cfg.isupCkt[x].options		= ccSpan->options;
+		g_ftdm_sngss7_data.cfg.isupCkt[x].switchType	= ccSpan->switchType;
+		g_ftdm_sngss7_data.cfg.isupCkt[x].min_digits	= ccSpan->min_digits;
+
+		if (ccSpan->t3 == 0) {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].t3			= 1200;
+		} else {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].t3			= ccSpan->t3;
+		}
+		if (ccSpan->t12 == 0) {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].t12		= 300;
+		} else {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].t12		= ccSpan->t12;
+		}
+		if (ccSpan->t13 == 0) {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].t13		= 3000;
+		} else {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].t13		= ccSpan->t13;
+		}
+		if (ccSpan->t14 == 0) {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].t14		= 300;
+		} else {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].t14		= ccSpan->t14;
+		}
+		if (ccSpan->t15 == 0) {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].t15		= 3000;
+		} else {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].t15		= ccSpan->t15;
+		}
+		if (ccSpan->t16 == 0) {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].t16		= 300;
+		} else {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].t16		= ccSpan->t16;
+		}
+		if (ccSpan->t17 == 0) {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].t17		= 3000;
+		} else {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].t17		= ccSpan->t17;
+		}
+		if (ccSpan->t35 == 0) {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].t17		= 170;
+		} else {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].t17		= ccSpan->t35;
+		}
+		if (ccSpan->tval == 0) {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].tval		= 10;
+		} else {
+			g_ftdm_sngss7_data.cfg.isupCkt[x].tval		= ccSpan->tval;
+		}
+
+		SS7_INFO("Added procId=%d, spanId = %d, chan = %d, cic = %d, ISUP cirId = %d\n",
+					g_ftdm_sngss7_data.cfg.isupCkt[x].procId,
+					g_ftdm_sngss7_data.cfg.isupCkt[x].ccSpanId,
+					g_ftdm_sngss7_data.cfg.isupCkt[x].chan,
+					g_ftdm_sngss7_data.cfg.isupCkt[x].cic,
+					g_ftdm_sngss7_data.cfg.isupCkt[x].id);
+
+		/* increment the span channel count */
+		count++;
+
+	/**************************************************************************/
+	} /* while (ccSpan->ch_map[0] != '\0') */
+
+
+	return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+static int ftmod_ss7_fill_in_circuits(sng_span_t *sngSpan)
+{
+	ftdm_channel_t		*ftdmchan = NULL;
+	ftdm_span_t			*ftdmspan = sngSpan->span;
+	sng_isup_ckt_t		*isupCkt = NULL;
+	sngss7_chan_data_t	*ss7_info = NULL;
+	int					flag;
+	int					i;
+	int					x;
+
+	/* go through all the channels on ftdm span */
+	for (i = 1; i < (ftdmspan->chan_count+1); i++) {
+	/**************************************************************************/
+		
+		/* extract the ftdmchan pointer */
+		ftdmchan = ftdmspan->channels[i];
+
+		/* find the equivalent channel in the global structure */
+		x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
+		flag = 0;
+		while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+		/**********************************************************************/
+			/* pull out the circuit to make it easier to work with */
+			isupCkt = &g_ftdm_sngss7_data.cfg.isupCkt[x];
+
+			/* if the ccSpanId's match fill in the span value...this is for sigs
+			 * because they will never have a channel that matches since they 
+			 * have a ftdmchan at this time */
+			if (sngSpan->ccSpanId == isupCkt->ccSpanId) {
+				isupCkt->span = ftdmchan->physical_span_id;
+			}
+
+			/* check if the ccSpanId matches and the physical channel # match */
+			if ((sngSpan->ccSpanId == isupCkt->ccSpanId) &&
+				(ftdmchan->physical_chan_id == isupCkt->chan)) {
+
+				/* we've found the channel in the ckt structure...raise the flag */
+				flag = 1;
+
+				/* now get out of the loop */
+				break;
+			}
+
+			/* move to the next ckt */
+			x++;
+
+			/* check if we are outside of the range of possible indexes */
+			if (x == ((g_ftdm_sngss7_data.cfg.procId + 1) * 1000)) {
+				break;
+			}
+		/**********************************************************************/
+		} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */
+
+		/* check we found the ckt or not */
+		if (!flag) {
+			SS7_ERROR_CHAN(ftdmchan, "Failed to find this channel in the global ckts!%s\n","");
+			return FTDM_FAIL;
+		}
+
+		/* fill in the rest of the global sngss7_chan_data_t structure */
+		ss7_info = (sngss7_chan_data_t *)isupCkt->obj;
+		ss7_info->ftdmchan = ftdmchan;
+
+		/* attach the sngss7_chan_data_t to the freetdm channel structure */
+		ftdmchan->call_data = ss7_info;
+
+		/* prepare the timer structures */
+		ss7_info->t35.sched			= ((sngss7_span_data_t *)(ftdmspan->signal_data))->sched;
+		ss7_info->t35.counter		= 1;
+		ss7_info->t35.beat			= (isupCkt->t35) * 100; /* beat is in ms, t35 is in 100ms */
+		ss7_info->t35.callback		= handle_isup_t35;
+		ss7_info->t35.sngss7_info	= ss7_info;
+
+
+	/**************************************************************************/
+	} /* for (i == 1; i < ftdmspan->chan_count; i++) */
+
+	return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
committer: Leon de Rooij
comments: 
Merge branch 'master' of ssh://git.freeswitch.org/freeswitch
committer: David Yat Sin
comments: 
Merge branch 'master' of git://git.freeswitch.org/freeswitch
committer: cypromis
comments: 
Merge remote branch 'origin/master'
committer: Leon de Rooij
comments: 
Merge branch 'master' of ssh://git.freeswitch.org/freeswitch
committer: Moises Silva
comments: 
freetdm: add WIN32_LEAN_AND_MEAN fix

diff --git a/libs/freetdm/cyginstall.sh b/libs/freetdm/cyginstall.sh
old mode 100644
new mode 100755
diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h
index 7cf0934..ba16c7c 100644
--- a/libs/freetdm/src/include/private/ftdm_core.h
+++ b/libs/freetdm/src/include/private/ftdm_core.h
@@ -94,7 +94,10 @@
 			   !strcasecmp(expr, "active") ||	\
 			   atoi(expr))) ? 1 : 0
 
-
+#ifdef WIN32_LEAN_AND_MEAN
+#include <winsock2.h>
+#include <mmsystem.h>
+#endif
 
 #include <time.h>
 #ifndef __WINDOWS__
committer: Moises Silva
comments: 
freetdm: ftmod_r2 - check for io dump file errors on open

diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
index 0217a51..d86fb43 100644
--- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
+++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
@@ -729,16 +729,24 @@ static void dump_mf(openr2_chan_t *r2chan)
 		snprintf(dfile, sizeof(dfile), logname ? "%s.s%dc%d.input.alaw" : "%s/s%dc%d.input.alaw", 
 				logname ? logname : r2data->logdir, ftdmchan->span_id, ftdmchan->chan_id);
 		f = fopen(dfile, "wb");
-		ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO input in file %s\n", dfile);
-		ftdm_channel_command(ftdmchan, FTDM_COMMAND_DUMP_INPUT, f);
-		fclose(f);
+		if (f) {
+			ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO input in file %s\n", dfile);
+			ftdm_channel_command(ftdmchan, FTDM_COMMAND_DUMP_INPUT, f);
+			fclose(f);
+		} else {
+			ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Could not dump IO input in file %s, error: %s", dfile, strerror(errno));
+		}
 
 		snprintf(dfile, sizeof(dfile), logname ? "%s.s%dc%d.output.alaw" : "%s/s%dc%d.output.alaw", 
 				logname ? logname : r2data->logdir, ftdmchan->span_id, ftdmchan->chan_id);
 		f = fopen(dfile, "wb");
-		ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO output in file %s\n", dfile);
-		ftdm_channel_command(ftdmchan, FTDM_COMMAND_DUMP_OUTPUT, f);
-		fclose(f);
+		if (f) {
+			ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO output in file %s\n", dfile);
+			ftdm_channel_command(ftdmchan, FTDM_COMMAND_DUMP_OUTPUT, f);
+			fclose(f);
+		} else {
+			ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Could not dump IO output in file %s, error: %s", dfile, strerror(errno));
+		}
 	}
 }
 
committer: Moises Silva
comments: 
freetdm: fix ftdm error mapping to unix-style errors

diff --git a/libs/freetdm/src/include/ftdm_declare.h b/libs/freetdm/src/include/ftdm_declare.h
index 88a7693..b443f2d 100644
--- a/libs/freetdm/src/include/ftdm_declare.h
+++ b/libs/freetdm/src/include/ftdm_declare.h
@@ -178,18 +178,20 @@ typedef int ftdm_socket_t;
 /*! \brief FreeTDM APIs possible return codes */
 typedef enum {
 	FTDM_SUCCESS, /*!< Success */
-	FTDM_FAIL, /*!< Failure, generic error return code, use ftdm_channel_get_last_error or ftdm_span_get_last_error for details */
-	FTDM_MEMERR, /*!< Memory error, most likely allocation failure */
+	FTDM_FAIL, /*!< Failure, generic error return code when no more specific return code can be used */
+
+	FTDM_MEMERR, /*!< Allocation failure */
+	FTDM_ENOMEM = FTDM_MEMERR,
+
 	FTDM_TIMEOUT, /*!< Operation timed out (ie: polling on a device)*/
+	FTDM_ETIMEDOUT = FTDM_TIMEOUT,
+
 	FTDM_NOTIMPL, /*!< Operation not implemented */
+	FTDM_ENOSYS = FTDM_NOTIMPL, /*!< The function is not implemented */
+
 	FTDM_BREAK, /*!< Request the caller to perform a break (context-dependant, ie: stop getting DNIS/ANI) */
 
 	/*!< Any new return codes should try to mimc unix style error codes, no need to reinvent */
-	/* Remapping some of the codes that were before */
-	FTDM_ENOMEM = FTDM_MEMERR, /*!< Memory error */
-	FTDM_ETIMEDOUT = FTDM_TIMEOUT, /*!< Operation timedout */
-	FTDM_ENOSYS = FTDM_NOTIMPL, /*!< The function is not implemented */
-
 	FTDM_EINVAL, /*!< Invalid argument */
 	FTDM_ECANCELED, /*!< Operation cancelled */
 	FTDM_EBUSY, /*!< Device busy */
committer: Moises Silva
comments: 
freetdm: use the problem freetdm define to set wp alarms

diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
index 3b384cd..b3d1fe6 100644
--- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
+++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
@@ -1242,7 +1242,7 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms)
 			/* there is a bug in wanpipe where alarms were not properly set when they should be
 			 * on at application startup, until that is fixed we check the link status here too */
 			ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_LINK_STATUS, &sangoma_status);
-			ftdmchan->alarm_flags = sangoma_status == FTDM_HW_LINK_DISCONNECTED ? 1 : 0;
+			ftdmchan->alarm_flags = sangoma_status == FTDM_HW_LINK_DISCONNECTED ? FTDM_ALARM_RED : FTDM_ALARM_NONE;
 			ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Link status is %d\n", sangoma_status);
 		}
 	}
diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h
index aed4054..588dc31 100644
--- a/libs/freetdm/src/include/freetdm.h
+++ b/libs/freetdm/src/include/freetdm.h
@@ -838,11 +838,11 @@ typedef enum {
 /*! \brief FreeTDM supported hardware alarms. */
 typedef enum {
 	FTDM_ALARM_NONE    = 0,
-	FTDM_ALARM_RED     = (1 << 1),
-	FTDM_ALARM_YELLOW  = (1 << 2),
-	FTDM_ALARM_RAI     = (1 << 3),
-	FTDM_ALARM_BLUE    = (1 << 4),
-	FTDM_ALARM_AIS     = (1 << 5),
+	FTDM_ALARM_RED     = (1 << 0),
+	FTDM_ALARM_YELLOW  = (1 << 1),
+	FTDM_ALARM_RAI     = (1 << 2),
+	FTDM_ALARM_BLUE    = (1 << 3),
+	FTDM_ALARM_AIS     = (1 << 4),
 	FTDM_ALARM_GENERAL = (1 << 30)
 } ftdm_alarm_flag_t;
 
committer: Leon de Rooij
comments: 
enter

diff --git a/src/mod/languages/mod_lua/mod_lua_extra.c b/src/mod/languages/mod_lua/mod_lua_extra.c
index 38776f9..821cc60 100644
--- a/src/mod/languages/mod_lua/mod_lua_extra.c
+++ b/src/mod/languages/mod_lua/mod_lua_extra.c
@@ -1,6 +1,8 @@
 using namespace LUA;
 
-SWITCH_BEGIN_EXTERN_C void mod_lua_conjure_event(lua_State * L, switch_event_t *event, const char *name, int destroy_me)
+SWITCH_BEGIN_EXTERN_C
+
+void mod_lua_conjure_event(lua_State * L, switch_event_t *event, const char *name, int destroy_me)
 {
 	Event *result = new Event(event);
 	SWIG_NewPointerObj(L, result, SWIGTYPE_p_Event, destroy_me);
committer: Leon de Rooij
comments: 
enter

diff --git a/src/mod/languages/mod_lua/mod_lua_extra.h b/src/mod/languages/mod_lua/mod_lua_extra.h
index b96adc3..3fca994 100644
--- a/src/mod/languages/mod_lua/mod_lua_extra.h
+++ b/src/mod/languages/mod_lua/mod_lua_extra.h
@@ -1,6 +1,8 @@
 #ifndef MOD_LUA_EXTRA
 #define MOD_LUA_EXTRA
-SWITCH_BEGIN_EXTERN_C void mod_lua_conjure_event(lua_State * L, switch_event_t *event, const char *name, int destroy_me);
+SWITCH_BEGIN_EXTERN_C
+
+void mod_lua_conjure_event(lua_State * L, switch_event_t *event, const char *name, int destroy_me);
 void mod_lua_conjure_stream(lua_State * L, switch_stream_handle_t *stream, const char *name, int destroy_me);
 void mod_lua_conjure_session(lua_State * L, switch_core_session_t *session, const char *name, int destroy_me);
 
committer: cypromis
comments: 
antoher try at c options to make iksemel right on solaris

diff --git a/libs/iksemel/configure.ac b/libs/iksemel/configure.ac
index 49d8621..403725a 100644
--- a/libs/iksemel/configure.ac
+++ b/libs/iksemel/configure.ac
@@ -83,12 +83,12 @@ AC_ARG_ENABLE(64,
 
 if test "x${ax_cv_c_compiler_vendor}"  =  "xsun" ; then
     if test "${enable_64}" = "yes"; then
-        CFLAGS="$CFLAGS -xc99=all -mt -m64 -lgpg-error"
-        CXXFLAGS="$CXXFLAGS -xc99=all -mt -m64 -lgpg-error"
+        CFLAGS="$CFLAGS -mt -m64 -lgpg-error"
+        CXXFLAGS="$CXXFLAGS -mt -m64 -lgpg-error"
 	SUNFLAGS="-xc99=all -mt -m64 -lgpg-error"
     else 
-	CFLAGS="$CFLAGS -xc99=all -mt -lgpg-error"
-	CXXFLAGS="$CXXFLAGS -xc99=all -mt -lgpg-error"
+	CFLAGS="$CFLAGS  -mt -lgpg-error"
+	CXXFLAGS="$CXXFLAGS -mt -lgpg-error"
 	SUNFLAGS="-xc99=all -mt -lgpg-error"
     fi
 fi
committer: Moises Silva
comments: 
freetdm: do not enable ec on SIGEVENT_START

diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c
index b5f9fab..529a30f 100644
--- a/libs/freetdm/src/ftdm_io.c
+++ b/libs/freetdm/src/ftdm_io.c
@@ -5533,7 +5533,6 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
 			}
 			ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_CALL_STARTED);
 			ftdm_call_set_call_id(sigmsg->channel, &sigmsg->channel->caller_data);
-			ftdm_set_echocancel_call_begin(sigmsg->channel);
 			if (sigmsg->channel->dtmfdbg.requested) {
 				ftdm_channel_command(sigmsg->channel, FTDM_COMMAND_ENABLE_DEBUG_DTMF, NULL);
 			}
========================================================================

Summary of changes:
 .gitignore                                         |   69 +-
 Freeswitch.2010.sln                                |   24 +-
 build/getg729.sh.in                                |   34 +
 build/modules.conf.in                              |    2 +
 conf/autoload_configs/cdr_pg_csv.conf.xml          |   35 +-
 conf/autoload_configs/modules.conf.xml             |    1 +
 conf/autoload_configs/switch.conf.xml              |    4 +
 conf/jingle_profiles/client.xml                    |    2 +-
 configure.in                                       |    6 +
 fscomm/widgets/codecwidget.cpp                     |    2 +
 libs/esl/fs_cli.c                                  |   44 +-
 libs/freetdm/Makefile.am                           |    3 +-
 libs/freetdm/configure.ac                          |    2 +-
 libs/freetdm/mod_freetdm/mod_freetdm.c             |   73 +-
 libs/freetdm/src/ftdm_io.c                         |   57 +-
 libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c         |   20 +-
 .../ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c  |   13 +-
 .../ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c    |    2 +
 .../ftmod_sangoma_isdn_stack_cfg.c                 |   38 +-
 .../ftmod_sangoma_isdn_stack_hndl.c                |   17 +
 .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c      |  562 +++--
 .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c      |  448 +++-
 .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c    |  374 +++-
 .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c   |   94 +-
 .../ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c |   82 +-
 .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c   |  125 +-
 .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c     |  303 ++-
 .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h     |  335 ++-
 .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c      |   17 +-
 .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_relay.c    |  318 +++
 .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c      |  106 +-
 .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c  |  267 ++-
 .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c   |    2 +-
 .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c      | 2891 +++++++++++++-------
 .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c        |    2 +-
 libs/freetdm/src/include/freetdm.h                 |   10 +-
 libs/freetdm/src/include/ftdm_declare.h            |   16 +-
 libs/freetdm/src/include/private/ftdm_core.h       |    5 +-
 libs/iksemel/configure.ac                          |    8 +-
 libs/ilbc/src/iLBC_decode.c                        |    2 +
 libs/openzap/mod_openzap/mod_openzap.c             |   34 +-
 libs/portaudio/build/msvc/portaudio.2010.vcxproj   |  136 +-
 .../sofia/libsofia_sip_ua_static.2010.vcxproj      |    6 +
 src/include/private/switch_core_pvt.h              |    1 +
 src/include/switch_core.h                          |    8 +
 src/include/switch_cpp.h                           |    4 +
 src/include/switch_nat.h                           |    2 +-
 src/mod/Makefile.am                                |    5 +-
 src/mod/applications/mod_commands/mod_commands.c   |  200 ++-
 .../applications/mod_conference/mod_conference.c   |   46 +-
 src/mod/applications/mod_dptools/mod_dptools.c     |   27 +-
 src/mod/applications/mod_fsk/mod_fsk.c             |    4 +-
 src/mod/applications/mod_redis/mod_redis.c         |   10 +-
 src/mod/applications/mod_voicemail/mod_voicemail.c |   28 +-
 .../mod_tts_commandline/mod_tts_commandline.c      |   17 +-
 src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c          |   51 +-
 src/mod/codecs/mod_com_g729/Makefile.am            |   39 +
 src/mod/codecs/mod_opus/Makefile                   |   28 +
 src/mod/codecs/mod_opus/mod_opus.c                 |  200 ++
 .../mod_dialplan_asterisk/mod_dialplan_asterisk.c  |    6 +-
 src/mod/endpoints/mod_dingaling/mod_dingaling.c    |    4 +-
 src/mod/endpoints/mod_khomp/src/khomp_pvt.cpp      |    3 +-
 src/mod/endpoints/mod_loopback/mod_loopback.c      |   29 +-
 src/mod/endpoints/mod_portaudio/mod_portaudio.c    | 1046 +++++---
 src/mod/endpoints/mod_sofia/mod_sofia.c            |   13 +-
 src/mod/endpoints/mod_sofia/sofia.c                |   11 +-
 src/mod/endpoints/mod_sofia/sofia_glue.c           |   27 +-
 src/mod/endpoints/mod_sofia/sofia_presence.c       |   62 +-
 src/mod/endpoints/mod_sofia/sofia_reg.c            |   15 +-
 .../event_handlers/mod_cdr_pg_csv/mod_cdr_pg_csv.c |  396 ++--
 .../mod_event_socket/mod_event_socket.c            |    5 +-
 src/mod/formats/mod_file_string/mod_file_string.c  |    2 +-
 src/mod/languages/mod_lua/mod_lua_extra.c          |    4 +-
 src/mod/languages/mod_lua/mod_lua_extra.h          |    4 +-
 src/mod/languages/mod_lua/mod_lua_wrap.cpp         |   50 +
 src/mod/languages/mod_managed/freeswitch_wrap.cxx  |   24 +
 src/mod/languages/mod_managed/managed/swig.cs      |    8 +
 .../languages/mod_spidermonkey/mod_spidermonkey.c  |   13 +-
 src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c          |    6 +-
 src/switch_channel.c                               |   27 +-
 src/switch_console.c                               |   32 +-
 src/switch_core.c                                  |   49 +-
 src/switch_core_file.c                             |    2 +-
 src/switch_core_io.c                               |   13 +
 src/switch_core_session.c                          |   15 +
 src/switch_core_sqldb.c                            |  178 +-
 src/switch_cpp.cpp                                 |    7 +
 src/switch_event.c                                 |    7 +-
 src/switch_nat.c                                   |    7 +
 src/switch_rtp.c                                   |   11 +-
 src/switch_utils.c                                 |   10 +-
 src/switch_xml.c                                   |    3 +-
 src/switch_xml_config.c                            |    2 +-
 support-d/prereq.sh                                |    2 +-
 94 files changed, 6602 insertions(+), 2752 deletions(-)
 create mode 100755 build/getg729.sh.in
 mode change 100644 => 100755 libs/freetdm/cyginstall.sh
 create mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_relay.c
 create mode 100644 src/mod/codecs/mod_com_g729/Makefile.am
 create mode 100644 src/mod/codecs/mod_opus/Makefile
 create mode 100644 src/mod/codecs/mod_opus/mod_opus.c

this email was generated because of /git/your-repo.git/hooks/post-receive by the file /git-core/contrib/hooks/post-receive-email
For more info, see http://blog.chomperstomp.com/?p=630 --
FreeSWITCH Source