diff --git a/.gitignore b/.gitignore
index adcfda37f4..304b42c1f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -70,10 +70,12 @@ config.status
configure.lineno
/freeswitch
/fs_cli
+/fs_encode
/fs_ivrd
/libtool
/modules.conf
/quiet_libtool
+/tone2wav
/scripts/fsxs
/scripts/gentls_cert
/a.out.dSYM
diff --git a/Freeswitch.2010.sln b/Freeswitch.2010.sln
index 5722802839..186969891a 100644
--- a/Freeswitch.2010.sln
+++ b/Freeswitch.2010.sln
@@ -942,11 +942,13 @@ Global
{1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|Win32.ActiveCfg = Debug|Win32
{1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|Win32.Build.0 = Debug|Win32
{1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|x64.ActiveCfg = Debug|x64
+ {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|x64.Build.0 = Debug|x64
{1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|x64 Setup.ActiveCfg = Debug|x64
{1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|x86 Setup.ActiveCfg = Debug|Win32
{1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|Win32.ActiveCfg = Release|Win32
{1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|Win32.Build.0 = Release|Win32
{1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x64.ActiveCfg = Release|x64
+ {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x64.Build.0 = Release|x64
{1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x64 Setup.ActiveCfg = Release|x64
{1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x86 Setup.ActiveCfg = Release|Win32
{692F6330-4D87-4C82-81DF-40DB5892636E}.All|Win32.ActiveCfg = Release|x64
@@ -1442,11 +1444,13 @@ Global
{ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Debug|Win32.ActiveCfg = Debug|Win32
{ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Debug|Win32.Build.0 = Debug|Win32
{ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Debug|x64.ActiveCfg = Debug|x64
+ {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Debug|x64.Build.0 = Debug|x64
{ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Debug|x64 Setup.ActiveCfg = Debug|x64
{ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Debug|x86 Setup.ActiveCfg = Debug|Win32
{ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Release|Win32.ActiveCfg = Release|Win32
{ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Release|Win32.Build.0 = Release|Win32
{ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Release|x64.ActiveCfg = Release|x64
+ {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Release|x64.Build.0 = Release|x64
{ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Release|x64 Setup.ActiveCfg = Release|x64
{ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Release|x86 Setup.ActiveCfg = Release|Win32
{8F992C49-6C51-412F-B2A3-34EAB708EB65}.All|Win32.ActiveCfg = Release|x64
@@ -1458,11 +1462,13 @@ Global
{8F992C49-6C51-412F-B2A3-34EAB708EB65}.Debug|Win32.ActiveCfg = Debug|Win32
{8F992C49-6C51-412F-B2A3-34EAB708EB65}.Debug|Win32.Build.0 = Debug|Win32
{8F992C49-6C51-412F-B2A3-34EAB708EB65}.Debug|x64.ActiveCfg = Debug|x64
+ {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Debug|x64.Build.0 = Debug|x64
{8F992C49-6C51-412F-B2A3-34EAB708EB65}.Debug|x64 Setup.ActiveCfg = Debug|x64
{8F992C49-6C51-412F-B2A3-34EAB708EB65}.Debug|x86 Setup.ActiveCfg = Debug|Win32
{8F992C49-6C51-412F-B2A3-34EAB708EB65}.Release|Win32.ActiveCfg = Release|Win32
{8F992C49-6C51-412F-B2A3-34EAB708EB65}.Release|Win32.Build.0 = Release|Win32
{8F992C49-6C51-412F-B2A3-34EAB708EB65}.Release|x64.ActiveCfg = Release|x64
+ {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Release|x64.Build.0 = Release|x64
{8F992C49-6C51-412F-B2A3-34EAB708EB65}.Release|x64 Setup.ActiveCfg = Release|x64
{8F992C49-6C51-412F-B2A3-34EAB708EB65}.Release|x86 Setup.ActiveCfg = Release|Win32
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.All|Win32.ActiveCfg = Release|x64
@@ -1510,11 +1516,13 @@ Global
{0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Debug|Win32.ActiveCfg = Debug|Win32
{0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Debug|Win32.Build.0 = Debug|Win32
{0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Debug|x64.ActiveCfg = Debug|x64
+ {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Debug|x64.Build.0 = Debug|x64
{0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Debug|x64 Setup.ActiveCfg = Debug|x64
{0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Debug|x86 Setup.ActiveCfg = Debug|Win32
{0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Release|Win32.ActiveCfg = Release|Win32
{0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Release|Win32.Build.0 = Release|Win32
{0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Release|x64.ActiveCfg = Release|x64
+ {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Release|x64.Build.0 = Release|x64
{0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Release|x64 Setup.ActiveCfg = Release|x64
{0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Release|x86 Setup.ActiveCfg = Release|Win32
{AB91A099-7690-4ECF-8994-E458F4EA1ED4}.All|Win32.ActiveCfg = Release|x64
@@ -1670,11 +1678,13 @@ Global
{028C7278-05D7-4E18-82FE-BE231B844F41}.Debug|Win32.ActiveCfg = Debug|Win32
{028C7278-05D7-4E18-82FE-BE231B844F41}.Debug|Win32.Build.0 = Debug|Win32
{028C7278-05D7-4E18-82FE-BE231B844F41}.Debug|x64.ActiveCfg = Debug|x64
+ {028C7278-05D7-4E18-82FE-BE231B844F41}.Debug|x64.Build.0 = Debug|x64
{028C7278-05D7-4E18-82FE-BE231B844F41}.Debug|x64 Setup.ActiveCfg = Debug|x64
{028C7278-05D7-4E18-82FE-BE231B844F41}.Debug|x86 Setup.ActiveCfg = Debug|Win32
{028C7278-05D7-4E18-82FE-BE231B844F41}.Release|Win32.ActiveCfg = Release|Win32
{028C7278-05D7-4E18-82FE-BE231B844F41}.Release|Win32.Build.0 = Release|Win32
{028C7278-05D7-4E18-82FE-BE231B844F41}.Release|x64.ActiveCfg = Release|x64
+ {028C7278-05D7-4E18-82FE-BE231B844F41}.Release|x64.Build.0 = Release|x64
{028C7278-05D7-4E18-82FE-BE231B844F41}.Release|x64 Setup.ActiveCfg = Release|x64
{028C7278-05D7-4E18-82FE-BE231B844F41}.Release|x86 Setup.ActiveCfg = Release|Win32
{D7F1E3F2-A3F4-474C-8555-15122571AF52}.All|Win32.ActiveCfg = Release|x64
@@ -1938,11 +1948,13 @@ Global
{36E854E3-CE12-4348-A125-CCF3F9D74813}.Debug|Win32.ActiveCfg = Debug|Win32
{36E854E3-CE12-4348-A125-CCF3F9D74813}.Debug|Win32.Build.0 = Debug|Win32
{36E854E3-CE12-4348-A125-CCF3F9D74813}.Debug|x64.ActiveCfg = Debug|x64
+ {36E854E3-CE12-4348-A125-CCF3F9D74813}.Debug|x64.Build.0 = Debug|x64
{36E854E3-CE12-4348-A125-CCF3F9D74813}.Debug|x64 Setup.ActiveCfg = Debug|x64
{36E854E3-CE12-4348-A125-CCF3F9D74813}.Debug|x86 Setup.ActiveCfg = Debug|Win32
{36E854E3-CE12-4348-A125-CCF3F9D74813}.Release|Win32.ActiveCfg = Release|Win32
{36E854E3-CE12-4348-A125-CCF3F9D74813}.Release|Win32.Build.0 = Release|Win32
{36E854E3-CE12-4348-A125-CCF3F9D74813}.Release|x64.ActiveCfg = Release|x64
+ {36E854E3-CE12-4348-A125-CCF3F9D74813}.Release|x64.Build.0 = Release|x64
{36E854E3-CE12-4348-A125-CCF3F9D74813}.Release|x64 Setup.ActiveCfg = Release|x64
{36E854E3-CE12-4348-A125-CCF3F9D74813}.Release|x86 Setup.ActiveCfg = Release|Win32
{7B077E7F-1BE7-4291-AB86-55E527B25CAC}.All|Win32.ActiveCfg = Release|x64
diff --git a/Makefile.am b/Makefile.am
index 944511dac9..e701494a2e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -90,6 +90,8 @@ $(RECURSIVE_TARGETS):
fi; \
if test -z "$$fail" ; then \
cd $(top_builddir)/build && $(MAKE) $(AM_MAKEFLAGS) $$target || exit 1; \
+ else \
+ exit 1; \
fi ;
CORE_CFLAGS = `$(switch_builddir)/libs/apr/apr-1-config --cflags --cppflags --includes`
@@ -374,7 +376,7 @@ src/include/switch_version.h: src/include/switch_version.h.in .version $(libfree
touch .version ; \
else \
if [ -d .git ] ; then \
- version=`git log --format="%h %ci" -1 HEAD | head -1 | sed -e 's|:|-|g' || echo hacked` ; \
+ version=`git log --pretty=format:"%h %ci" -1 HEAD | head -1 | sed -e 's|:|-|g' || echo hacked` ; \
if [ "x$$version" = "xhacked" ] ; then \
version="hacked-`date -u +%Y%m%dT%H%M%SZ`" ; \
else \
diff --git a/build/Makefile.am b/build/Makefile.am
index 4b426ef6e3..1d57dad528 100644
--- a/build/Makefile.am
+++ b/build/Makefile.am
@@ -6,8 +6,13 @@ all:
@echo " + Install by running: +"
@echo " + +"
@echo " + $(MK) install +"
+ @echo " + +"
+ @echo " + While you're waiting, register for ClueCon! +"
+ @echo " + http://www.cluecon.com +"
+ @echo " + +"
@echo " +-----------------------------------------------+"
+
install:
@echo " +---------- FreeSWITCH install Complete ----------+"
@echo " + FreeSWITCH has been successfully installed. +"
diff --git a/build/modules.conf.in b/build/modules.conf.in
index 37244a188a..13e655672c 100644
--- a/build/modules.conf.in
+++ b/build/modules.conf.in
@@ -62,6 +62,7 @@ endpoints/mod_loopback
#endpoints/mod_skinny
#endpoints/mod_skypopen
#endpoints/mod_h323
+#endpoints/mod_khomp
#../../libs/openzap/mod_openzap
#../../libs/freetdm/mod_freetdm
#asr_tts/mod_unimrcp
@@ -105,5 +106,4 @@ say/mod_say_ru
#say/mod_say_th
## Experimental Modules (don't cry if they're broken)
-#endpoints/mod_khomp
#../../contrib/mod/xml_int/mod_xml_odbc
diff --git a/conf/autoload_configs/modules.conf.xml b/conf/autoload_configs/modules.conf.xml
index f5627fe965..118d7c4d81 100644
--- a/conf/autoload_configs/modules.conf.xml
+++ b/conf/autoload_configs/modules.conf.xml
@@ -38,6 +38,7 @@
+
diff --git a/conf/autoload_configs/sangoma_codec.conf.xml b/conf/autoload_configs/sangoma_codec.conf.xml
index 05d70de0a7..eed9d673e1 100644
--- a/conf/autoload_configs/sangoma_codec.conf.xml
+++ b/conf/autoload_configs/sangoma_codec.conf.xml
@@ -4,14 +4,15 @@
diff --git a/conf/dialplan/default.xml b/conf/dialplan/default.xml
index 42a3bcc31f..a19f68399e 100644
--- a/conf/dialplan/default.xml
+++ b/conf/dialplan/default.xml
@@ -265,7 +265,7 @@
-
+
diff --git a/conf/directory/default.xml b/conf/directory/default.xml
index 1e583033a9..8af7aea135 100644
--- a/conf/directory/default.xml
+++ b/conf/directory/default.xml
@@ -21,7 +21,7 @@
-
+
diff --git a/conf/sip_profiles/internal.xml b/conf/sip_profiles/internal.xml
index 93558a3584..3e756a85c0 100644
--- a/conf/sip_profiles/internal.xml
+++ b/conf/sip_profiles/internal.xml
@@ -132,6 +132,8 @@
+
+
diff --git a/configure.in b/configure.in
index de7261266e..77df2a614c 100644
--- a/configure.in
+++ b/configure.in
@@ -373,6 +373,11 @@ if test "x$have_libz" = "xyes" ; then
APR_ADDTO(SWITCH_AM_LDFLAGS, -lz)
fi
+AC_CHECK_LIB(resolv, res_init, have_libresolv=yes, have_libresolv=no)
+if test "x$have_libresolv" = "xyes" ; then
+APR_ADDTO(SWITCH_AM_LDFLAGS, -lresolv)
+fi
+
ESL_LDFLAGS=
PLATFORM_CORE_DEPLIBS=
# tweak platform specific flags
diff --git a/docs/ChangeLog b/docs/ChangeLog
index d6fddd6bfa..96066b6e8c 100644
--- a/docs/ChangeLog
+++ b/docs/ChangeLog
@@ -19,6 +19,7 @@ freeswitch (1.0.7)
build: add mod_osp Makefile to configure generated Makefiles (r:dc06a039/FS-122)
build: Remove mod_spidermonkey from windows 2008 x64 builds - does not work (r:280e894d)
build: fix warnings on windows x64 builds src and mods projects - only libsofia included on the libs side (r:45ecbc2f)
+ build: Patch debian init.d script to set ulimit values (r:0eb33e57/FS-2844)
codec2: working prototype, still for testing only (r:04ca0751)
config: move limit.conf to db.conf
config: Update VM phrase macros to voice option then action on main, config menus
@@ -30,6 +31,8 @@ freeswitch (1.0.7)
config: Add att_xfer example to default dialplan (r:20ec962a)
config: default example to resolve some issues with SCA in cases where host and ip are mixed causing the phone to be confused. (r:0279261b)
config: Fix phrase files, still missing a sound file (r:6741f350/FS-2742)
+ config: Disallow global-intercept and group-intercept can intercept an outbound call in default dialplan (r:890871ba/FS-2777)
+ config: fix single domain assumption in default config to be more portable *cough* bkw *cough* (r:f987903e)
core: Add RTCP support (FSRTP-14)
core: handle some errors on missing db handle conditions
core: add ... and shutdown as a fail-safe when no modules are loaded
@@ -110,6 +113,38 @@ freeswitch (1.0.7)
core: add bitrate patch from moc with some extra stuff for late neg mode (r:633f193d)
core: refactor fmtp parser as a core func (r:56f8c11f)
core: add switch_ivr_dmachine async digit parser to core (r:7f3319dc)
+ core: make parens optional on functions as vars ${foo(bar)} is now the same as ${foo bar} (r:fdba0e07)
+ core: fix default ptime for iLBC and make new configurable global map in switch.conf.xml (r:e3c427ad)
+ core: only pause recording media bugs in fifo (r:c1d41dd9)
+ core: Allow IPv6 in proxy mode (r:4e5911c2/FS-2776)
+ core: "Silent recovery" (r:93c2ed94)
+ core: fix switch_find_local_ip to properly handle force_local_ip_v4 and _v6 (r:f42c9036/FS-2778)
+ core: fix att_xfer/3-way scenario (r:0559cc50)
+ core: dmachine - timeout instantly when you have exact match and are equal to max digits (r:81a9f8ef)
+ core: Core ODBC support for transactions with MSSQL (r:d2ca8d40/FS-2050)
+ core: Show the UUID of the session in the log when sending RFC2833 DTMF packet and when receiving a RTP DTMF (r:9241a35e)
+ core: add record_post_process_exec_app and record_post_process_exec_api both can have : (r:07adca56)
+ core: add -ncwait for Unix based implememtations to make the backgrounder wait to make sure the process starts before detaching (r:23d5fc19)
+ core: fire DTMF event when converting dtmf to inband with start_dtmf_generate (r:dcdd3811)
+ core: fail calls with uninitialized frame (r:7dafe4e2)
+ core: allow switch_process_import to specify a prefix (r:e0c37c1f)
+ core: add additional info when fail (r:4bbd9a4c/FS-2825)
+ core: avoid hypothetical problem with flushing queue with delayed events (r:49b6237e)
+ core: add send_silence_when_idle and dmachine honoring to park loop (r:3be3cd76)
+ core: ivr_enterprise_originate: Fix export of variable from the originator channel to the called channels (r:025c82e7)
+ core: Better handling of progress and answering to prevent sip profile from locking up at higher volumes (r:04e57577/FS-2801)
+ core: ACL for IPv6 address and swigall to boot (r:db91f0e8/FS-2842)
+ core: add intercept_unanswered_only var akin to intercept_unbridged_only (r:68f18efe)
+ core: switch_odbc_handle_exec_string duplication SQLExecute (r:8b0e7d24/FS-2880)
+ core: Fix timeout while bridge is waiting for CF_BRIDGED flag (r:2572621b/FS-2368)
+ core: don't parse events for b legs from a leg thread in case they are using a monolothic python script as a group_confirm exec over socket to send it messages while the call is ringing (r:ed5266d3)
+ core: add new function to check when messages need parsing to improve performance on parsing messages during originate (r:8b0421ff)
+ core: run execute_on_answer on_media _on_ring apps async (r:ef4a4ed0)
+ core: add switch_ivr_insert_file to insert one file into another at an arbitrary sample point (r:82394b37)
+ core: Slow reload cause calls to hang (r:1ba98b02/FS-2852)
+ core: Application intercept causes FS to stop processing calls (r:12fc65f7/FS-2872)
+ core: fix edge cases for endless loop in sql thread (r:5d7c09ed)
+ core: prevent race while changing codecs mid call (r:7aa72b67)
lang: Improve French phrase files (FSCONFIG-23)
libapr: Fix issue where after a bridge with a member, uuid of Agent is set to single quote character ' (r:3fee704d/FS-2738)
libdingaling: fix race on shutdown causing crash (FSMOD-47)
@@ -126,6 +161,8 @@ freeswitch (1.0.7)
libesl: use uint32_t instead of long for timeout as in the rest of the lib, 0 means forever. Also added esl_send_recv_timed() (r:49d6c803)
libesl: Fix SEGV when using serialize function without any arguments (r:910729b5/ESL-44)
libesl: fix leak-on-error in esl_connect_timeout() (r:4263d60e)
+ libesl: Call close on connection handle if the connection fails (r:413dcc4c/ESL-50)
+ libesl: allow fs_cli -x to have args up to 1024 chars (was 256) (r:7039ba47)
libfreetdm: implemented freetdm config nodes and ss7 initial configuration
libfreetdm: fix codec for CAS signaling (r:b76e7f18)
libfreetdm: freetdm: ss7- added support for incoming group blocks, started adding support for ansi (r:c219a73c)
@@ -137,13 +174,16 @@ freeswitch (1.0.7)
libsofiasip: Fix random crashes (r:c15ee980/SFSIP-219)
libsofiasip: Fix T.38 bug in sofia_glue (r:2843f1ad/MODSOFIA-94)
libsofiasip: VS2010 sofia posix problem (r:46dd24c2/SFSIP-220)
+ libsofiasip: set minimum initital sip t1 timer to 1000ms to work around race condition on retry timer firing before all the things that are supposed to be handled by the timer are set. The base resolution on this timer is 500ms, so doubling up makes sure we always hit the initial retry timer on the next run, where everything should be set. The side effect was, 1/2 the time on a request that did not get immediate response, the timer would be fired and cleared, but the action (sending retry) was never done, and a new timer was not set, causing the request to just sit zombied and never retry. A better solution would be to find and correct the race condition so the timer is never set to early and we never hit this condition. (r:20c2740c)
libspandsp: Fixed a typo in spandsp's msvc/inttypes.h Updated sig_tone processing in spandsp to the latest, to allow moy to proceed with his signaling work.
libspandsp: removed a saturate16 from spandsp that was causing problems fixed a typo in the MSVC inttypes.h file for spandsp
libspandsp: Changes to the signaling tone detector to detect concurrent 2400Hz + 2600Hz tones. This passes voice immunity and other key tests, but it bounces a bit when transitions like 2400 -> 2400+2600 -> 2600 occur. Transitions between tone off and tone on are clean. (r:bc13e944)
libspandsp: Fix Windows build after libspandsp update (r:d70cc852/FSBUILD-293)
libspandsp: Fix for T.30 processing of operator interrupts, to improve compatibility with some machines, which seem to send them when no operator is around. (r:84ee0ae6)
+ libspandsp: spandsp t38 fax receiving error in win XP - regression from f029f7ef (r:761cec8f/FS-2766)
mod_avmd: Initial check in - Advanced Voicemail Detect (r:10c6a30a) (by Eric Des Courtis)
mod_avmd: Add to windows build (r:df4bd935)
+ mod_avmd: Fix mem leak (r:cd951384/FS-2839)
mod_callcenter: Initial commit of the mod_callcenter application. This module is in it early state of developpement. You can see documentation on the wiki at : http://wiki.freeswitch.org/wiki/Mod_callcenter For support/comments, please use http://jira.freeswitch.org/ and select the MOD CALLCENTER module. (r:ba09b96d)
mod_callcenter: Add ability to unload/reload/load a queue setting (You still need to reloadxml before). Note that joining a queue will check for it in the config and load it on the fly... I've used the same system as in mod_voicemail. Not sure if we should allow this, but just comment it out of the config before unload and it wont be available anymore (r:3eafca60)
mod_callcenter: Try to fix the ring-all, also add cli auto complete done in previous commit (r:1666783c)
@@ -159,6 +199,10 @@ freeswitch (1.0.7)
mod_callcenter: Added max-wait-time and max-wait-time-with-no-agent param to a queue. (r:3482f95e)
mod_callcenter: Make sure we fail to load if config is not present (r:e1fb79a1)
mod_callcenter: Fix invalid update of agent field (r:426a448f/FS-2738)
+ mod_callcenter: Allow to get queue info via api (r:70d592ae)
+ mod_callcenter: Fix bad return type so it compile on archlinux, thx bougyman (r:3a475986)
+ mod_callcenter: Make callcenter_config agent get return the value of the item requested. Also added queue param max-wait-time-with-no-agent-time-reached: If the max-wai-time-with-no-agent is already reached for the queue, then new caller can wait for x amount of second before it kicked out of the queue rather than get rejected automatically. (r:81a03869)
+ mod_callcenter: Add new event socket agent-offering. Plus some documentation and better handling of bad agent type -- FS-2869 (r:80174cf3/FS-2869)
mod_cidlookup: null xml is bad (r:095815f8)
mod_cid_lookup: honor skipcitystate when using whitepages (r:a66654de/FSMOD-53)
mod_commands: make break uuid_break and add cascade flag
@@ -173,6 +217,9 @@ freeswitch (1.0.7)
mod_commands: Allow cond API to return empty false value (r:c8a897b9)
mod_commands: ***BEHAVIOUR CHANGE*** reloadacl, load , reload will now explicitly call reloadxml (r:42c9df72)
mod_commands: add nat_map usage (r:7577b8aa)
+ mod_commands: add escaping empty strings to sql_escape (r:7bd0a5a6/FS-2833)
+ mod_commands: add uuid_fileman : <-- same vals as the callbacks in js and lua to control the currently playing file of a channel from the cli or ESL (for the people who were ignoring me on the conference call so I decided to implement it instead of try to explain it ) (r:c4369fc8)
+ mod_commands: FS-2210 Add support for auto completion for uuid_simplify (r:72bcc01b/FS-2210)
mod_conference: Fix reporting of volume up/down (MODAPP-419)
mod_conference: add last talking time per member to conference xml list
mod_conference: add terminate-on-silence conference param
@@ -180,30 +227,43 @@ freeswitch (1.0.7)
mod_conference: add conference_member_id variable to all sessions with the member id used by their conference participation (For drk__) (r:49c9bfdb)
mod_conference: fix relate nohear (r:f029ce07/MODAPP-428)
mod_conference: Fix floor change events not always firing (r:8f1767d3/MODAPP-424)
+ mod_conference: refactor conference to use switch_ivr_dmachine for the digit parsing controls are now bound to each member separately based on conference_controls channel var, then the caller-controls param in the profile or a default to "default" (r:ac19f73c)
+ mod_conference: Fix crash on dtmf action (r:4d5389bd/FS-2781)
mod_curl: use method=post when post requested (r:c6a4ddd0/FSMOD-69)
+ mod_db: fix stack corruption (MODAPP-407)
mod_dialplan_xml: Add in the INFO log the caller id number when processing a request (Currenly only show the caller name) (r:e1df5e13)
mod_dingaling: make mod_dingaling compat with google's new free phonecalls thing (r:ba0a2a32)
mod_dingaling: make dingaling work with google voice inbound too (r:4ee68141)
mod_dingaling: Fix crash when testing the new gv-dingaling with around 24 concurrent calls (r:73e1ec5e/FSCORE-667)
mod_dingaling: Fix NULL pointer (r:e3eff816/FS-1103)
+ mod_dingaling: fix leak in chat_send (r:eb109a85)
+ mod_dingaling: use the login as message source when not in component mode. (chat_send) (r:58c28aab)
mod_directory: Add variable directory_search_order to allow to search by first name by default is set to "first_name" (r:163ca31f)
- mod_db: fix stack corruption (MODAPP-407)
+ mod_distributor: Add mod_distributor to VS2010 - not built by default (r:bac79ba1)
mod_dptools: add eavesdrop_enable_dtmf chan var (r:596c0012)
mod_dptools: Make park app not send 183 session progress (r:76932995/FSCORE-567)
mod_dptools: add block_dtmf and unblock_dtmf apps (r:d9eb0197)
mod_dptools: refactor export code and add new bridge_export app which is like export but exports across when one channel bridges another (r:4aa9a838)
+ mod_dptools: add bind_digit_action application (r:9537197b)
+ mod_dptools: emit event when user presses DTMFs (r:37298f56)
mod_erlang_event: Make XML fetch reply ACKs distinguishable, update freeswitch.erl (r:9d44ed04)
mod_erlang_event: Add 3 new commands; session_event, session_noevents, session_nixevent (r:698fa045)
mod_erlang_event: generate long node names the same as erlang does (r:9ad509c2)
mod_erlang_event: Improve some logging to include UUIDs (r:c0d51b83)
+ mod_erlang_event: Support for reading erlang cookie from a file (r:094ffe37)
+ mod_erlang_event: Rewrite XML fetch conditional wait to be more sane (Reported by James Aimonetti) (r:6941c6eb/FS-2775)
mod_event_socket: fix up other users of switch_event_xmlize() to use SWITCH_EVENT_NONE (r:d6eb7562)
mod_event_socket: Fix small mem leaks (r:e4f90584/MODEVENT-68)
+ mod_event_socket: Add "-ERR" to api cmd response when failure occurs (r:58759052/FS-2827)
mod_fifo: allow multiple dtmf to exit fifo, set fifo_caller_exit_key to specify which (MODAPP-420)
mod_fifo: cancel outbound call if customer hangs up (r:cadb4d94)
mod_fifo: add taking_calls param to fifo member add and config file (r:821488bf)
mod_fifo: add nomedia flag (r:2d30a8c2)
mod_fifo: Fix inconsistency between the fifo queue and the channels (num callers in queue can become "-1") (r:07487114/FS-1659)
mod_fifo: fix issue leaving stale records in fifo_bridge table (r:b36d015f)
+ mod_fifo: fix fifo race in use count dec (r:402e383b)
+ mod_fifo: add outbound_ring_timeout param to mod_fifo (r:3885eea7)
+ mod_fifo: add default_lag to fifo (r:dd4fb5be)
mod_freetdm: Fix for TON and NPI not passed through to channel variables on incoming calls
mod_freetdm: add pvt data to freetdm channels fix fxs features (r:9d456900)
mod_freetdm: export and import boost custom data (r:edb2d582)
@@ -234,7 +294,12 @@ freeswitch (1.0.7)
mod_freetdm: OPENZAP-107 - Patched by Jeff Lenk (r:aa075136/OPENZAP-107)
mod_freetdm: allocate channels in their own memory page when debugging (r:fcd8df0a)
mod_freetdm: lock the channel when placing call (r:705dd237)
+ mod_freetdm: created cmake files for freetdm (r:fc55997b)
+ mod_freetdm: ss7 - added support to control mtp2, mtp3, and isup timers via freetdm.conf.xml (r:4455d581)
+ mod_freetdm: made ftmod_r2 use FTDM_SPAN_USE_SIGNALS_QUEUE and properly send FTDM_SIGEVENT_SIGSTATUS_CHANGED (r:af5f0a4a)
mod_gsmopen: copy from branch
+ mod_gsmopen: fix FS-2793, compilation stops (r:355c0dbb/FS-2793)
+ mod_gsmopen: retry serial initialization if failed, zeroing audio buffers, slower retry on soundcard busy (EAGAIN) (r:c7aefe93)
mod_hash: free all hashtables on shutdown (r:e76d7d92)
mod_hash: remove unneeded initializer (r:10d468a6)
mod_hash: begin working on remote support (r:c5ad49da)
@@ -258,6 +323,8 @@ freeswitch (1.0.7)
mod_java: fix eventConsumer issue and add flush() method (r:7fd3aff6)
mod_java: Allow user defined java methods to be called at startup and shutdown of JVM (r:1339e218/MODLANG-117)
mod_json_cdr: Fix segfault in mod_json_cdr.c (r:f347698a/MODEVENT-66)
+ mod_khomp: Added mod_khomp Endpoint. (r:5fea197b)
+ mod_khomp: Removed alternative contexts / extensions - New struct for matchs - On calls originated from an FXS branch, the Endpoint searches for a valid extension (digits sent) after the DTMF '#' or after the timeout (option fxs-digit-timeout). That search is done in the context defined in section , or if no context configured, the search is done in context defined in context-fxs. - Added "dialplan" configuration: Name of the dialplan module in use (default XML) - Group context enabled. If set, the search for a valid extension is done only in that context. - Updated documentation (r:1ef3fc9a)
mod_lcr: Expand variables (MODAPP-418)
mod_lcr: add enable_sip_redir parameter (r:70bf7a0a/MODAPP-427)
mod_lcr: don't validate profiles with ${} vars since they are dynamic and we can't guess what the proper value should be (r:af33afaa)
@@ -268,12 +335,17 @@ freeswitch (1.0.7)
mod_loopback: add loopback_bowout_on_execute var to make 1 legged loopback calls bow out of the picture
mod_loopback: only execute app once in app mode (r:64f58f2d)
mod_loopback: fix bug in mod_loopback where bowout=false (r:e9ab5368)
+ mod_loopback: pass indication when in app mode on mod_loopback (r:c423e209)
+ mod_loopback: fix voicemail failure (r:1a1881e8/FS-2795)
+ mod_loopback: pass ring_ready like we do with pre_answer (r:9d087d45)
mod_lua: Add switch_core_sqldb functionality from inside Lua script (r:26f2e095/FS-1384)
mod_lua: Made 2nd arg to freeswitch.Dbh:query (cb func) optional (r:87db11af)
mod_lua: Added SAF_ROUTING_EXEC flag to lua app, so it can be run inline (r:7d5ca1c0)
mod_managed: Added wrapper for switch_event_bind for .net (r:a5f07a80/MODLANG-165)
mod_managed: add additional support (r:5be58aac)
+ mod_managed: add mono 2.8 patch file see FS-2774 (r:6a948bd9/FS-2774)
mod_mp4v: MP4V-ES passthru for washibechi on IRC
+ mod_mp4: New module. Supports playback of MP4 files. Depends on libmp4v2 (originally compiled against v1.6.1)
mod_nibblebill: free allocated mem at shutdown; free properly if using custom_sql
mod_nibblebill: Add SAF_SUPPORT_NOMEDIA to nibblebill
mod_nibblebill: fix compile issues in latest HEAD (r:b073e82b/FSMOD-51)
@@ -291,7 +363,17 @@ freeswitch (1.0.7)
mod_sangoma_codec: added load/noload options for the supported codecs
mod_sangoma_codec: rename load/noload to register/noregister
mod_sangoma_codec: silence suppression (r:73d9d56f)
- mod_say_es: fix grammar when saying dates and time (r:6bed19b2/MODAPP-429)
+ mod_sangoma_codec: do not return 0 len frames and return silence instead when there is no transcoding output update stats only when we really receive a frame (r:dc4d19e9)
+ mod_sangoma_codec: flush sockets on first use (r:bbba1148)
+ mod_sangoma_codec: use native L16 for the source codec (r:d2e25519)
+ mod_sangoma_codec: default to G729 only and remove L16 since it did not make any sense (r:1d5aa062)
+ mod_sangoma_codec: add iLBC 13.3k and 15.2k (r:68abb39e)
+ mod_sangoma_codec: add G723.1 (r:3e33540a)
+ mod_sangoma_codec: register AMR (r:31cc2502)
+ mod_sangoma_codec: add G722 (r:ca8c2336)
+ mod_sangoma_codec: add siren7 32kbps (r:fcaf2677)
+ mod_sangoma_codec: add SIREN7 24kbps (r:3acc5fdb)
+ mod_say_es: fix grammar when saying dates and time (r:6bed19b2/MODAPP-429)
mod_say_ja: initial commit, still needs sound files (r:b2423158/FS-2755)
mod_say_ru: Fix saying time with +1 hour of current time (r:68d74c31/MODAPP-444)
mod_say_zh: Number reading should now be OK for the whole range of integers for Cantonese and Mandarin
@@ -320,6 +402,7 @@ freeswitch (1.0.7)
mod_skypopen: now answer a call only when directed to do it (before was trying to answer any incoming call). Lot of changes to a messy part, so maybe some problem will come out... (r:45c6c4d3)
mod_skypopen: ignore early media sent by channels to be bridged before our channel is answered (r:ef14b78a)
mod_sndfile: Add support for .alaw and .ulaw to mod_sndfile (r:facf09b8/MODFORM-41)
+ mod_sndfile: return break in mod_sndfile when seek returns failure (r:564dc7e4)
mod_sofia: Send SIP MESSAGE to unregistered users by prefixing sip: to user@domain
mod_sofia: fix callee being updated with callee information
mod_sofia: set appearance-index in update statement for SLA
@@ -391,6 +474,32 @@ freeswitch (1.0.7)
mod_sofia: fix parsing of sofia tracelevel param, moved param from profile params to global_settings as its global, and it only worked on reparse before anyways. Please correct any documentation on this issue on the wiki (r:82c4c4cc/FS-523)
mod_sofia: fix nat acl count check to check against the number of nat acls (r:e11550e7/FS-502)
mod_sofia: add sofia_glue_find_parameter_value function to get a specific value from a url params string (r:c701d41c)
+ mod_sofia: Sofia SIP Stack Lockup (r:8f13eb89/FS-2762)
+ mod_sofia: ix memory leak caused by regression from FS-2747 (r:6c4cb07b/FS-2747)
+ mod_sofia: Set SDP proper connection type of "c=" field to IP6 or IP4 when IPv6 called IPv4 (r:14361c09/FS-620)
+ mod_sofia: FS wrongly assumes NAT on Cisco 7941G (r:42f534fa/FS-2773)
+ mod_sofia: sofia_reg.c doesn't pass profile name into query, also, typo with all-reg-options-ping (r:6772c795/FS-2787)
+ mod_sofia: adjust sql stmts in presence to allow even non-registered entities to be tracked (r:4e0399d0)
+ mod_sofia: dont update display to ring when call is hungup in pidf presence (r:36851a90)
+ mod_sofia: 1) Add force-publish-expires to set custom presence update expires delta (-1 means endless) 2) Check how many users are registered when receiving a PUBLISH AND Multiple Registrations is enabled: if there is more than just 1 AND you are sending a offline message: skip publishing it to everyone to prevent clients from thinking themselves has gone offline. (r:fd1736b3)
+ mod_sofia: profile param ignore-183nosdp, chanvar sip_ignore_183nosdp FS-1978 (r:59d3b84d/FS-1978)
+ mod_sofia: fix race in codec failure condition, then fix bug in sdp parsing (likely a regression from recent codec changes) to never have the problem in the first place so you are double-protected (r:19325c43)
+ mod_sofia: fix mem leak (r:1970ec1d/FS-2810)
+ mod_sofia: parse static route in sip uri in notify by event (r:35676e7e)
+ mod_sofia: add support for NDLB-force-rport=safe param that does force-rport behavior only on endpoints we know are safe to do so on. This is a dirty hack to try to work with certain endpoints behind sonicwall which does not use the same port when it does nat, when the devices do not support rport, while not breaking devices that acutally use different ports that force-rport will break (r:fc4d290c)
+ mod_sofia: add separate reg timeout from retry sec (r:e5b891ee)
+ mod_sofia: fix display of timeout (r:2043d5a)
+ mod_sofia: fix missing name and potential segfault in gateway status (r:40ac860a)
+ mod_sofia: Add missing RTP info for early SDP in bypass media (r:10119e9e/FS-2824)
+ mod_sofia: add manual_rtp_bugs to profile and chan var and 3 new RTP bugs SEND_LINEAR_TIMESTAMPS|START_SEQ_AT_ZERO|NEVER_SEND_MARKER (r:b278dd23)
+ mod_sofia: apparently some sip device vendors did not read the RFC (who knew?) adding verbose_sdp=true var to add needless a= lines for standard iana codecs that explicitly do not require them (r:6c4f49a8)
+ mod_sofia: Fix registering a gateway, sofia always places a Via header with ext-sip-ip, even if this gateway is local (r:cf398e1a/FS-535)
+ mod_sofia: add presence-probe-on-register sofia param to send a probe on register instead of presence to deal with some broken phones and add some general improvements to allow multi homed presence (r:14394994)
+ mod_sofia: Fix issue when fs_path is used so we pick the correct media IP in our outbound invite this was soemthing that wouldn't work correctly over ATT on the iphone. (r:a669f76f)
+ mod_sofia: Default T38 Options (r:92f43440/FS-2892)
+ mod_sofia: Fix wrong IP in VIA and contact HEADER for MESSAGE method while fs run in private network (r:59ea4a1b/FS-2886)
+ mod_sofia: SIP-header History-Info might exist multiple times, but only last header is exposed as a channel variable (r:8cf15012/FS-2881)
+ mod_sofia: Add support to reboot Yealink phone remotely (r:fdc31908/FS-2897)
mod_spandsp: initial checkin of mod_fax/mod_voipcodecs merge into mod_spandsp (r:fa9a59a8)
mod_spandsp: rework of new mod_spandsp to have functions broken up into different c files (r:65400642)
mod_spandsp: improve duplicate digit detection and add 'min_dup_digit_spacing_ms' channel variable for use with the dtmf detector (r:eab4f246/FSMOD-45)
@@ -420,14 +529,18 @@ freeswitch (1.0.7)
mod_voicemail: fix vm_inject to a group and change syntax for sending to a whole domain to domain= for clarity sake (r:f30a1cc6)
mod_voicemail: add quotes to vm_cc command generated internally to escape spaces in the caller id name (r:5f012813)
mod_voicemail: Play caller id of callee prior to playing a vmail (r:e7b97907/FS-2719)
+ mod_voicemail: FS-1776 Add support for per user operator exten override param vm-operator-extension (r:df5b3498/FS-1776)
mod_xml_cdr: add force_process_cdr var to process b leg cdr on a case by case basis when b leg cdr is disabled (XML-17)
mod_xml_cdr: add leg param to query string (XML-24)
mod_xml_cdr: fix locked sessions (XML-26)
mod_xml_cdr: fix minor memory leaks and config bug (r:19253d83/MODEVENT-62)
mod_xml_rpc: Fix crash if unauthorized XML RPC is attempted (r:9835395c/FS-184)
scripts: added honeypot.pl and blacklist.pl which add extra SIP security options (r:b6a81ba7)
+ scripts: do simple verification to make sure we are getting IP addresses from VoIP abuse blacklist (r:b0049160)
+ scripts: add_user - cmd line utility that lets admin create new users very easily. (r:ec8f2c2b)
sofia-sip: fix null derefernce segfault in soa (r:f356c5e6)
sofia-sip: extend timeout for session expires on short timeouts to be 90% of timeout instead of 1/3 to handle devices that do not refresh in time such as polycom (r:a7f48928/SFSIP-212)
+ tools: Add fs_encode tool (r:89b17601)
freeswitch (1.0.6)
diff --git a/libs/apr-util/.update b/libs/apr-util/.update
index f430e64b3b..a573c80504 100644
--- a/libs/apr-util/.update
+++ b/libs/apr-util/.update
@@ -1 +1 @@
-Mon Dec 28 14:55:57 EST 2009
+Thu 18 Nov 2010 20:56:38 EST
diff --git a/libs/apr-util/include/apr_queue.h b/libs/apr-util/include/apr_queue.h
index 5a0181b29e..dcf0c137ed 100644
--- a/libs/apr-util/include/apr_queue.h
+++ b/libs/apr-util/include/apr_queue.h
@@ -78,6 +78,22 @@ APU_DECLARE(apr_status_t) apr_queue_push(apr_queue_t *queue, void *data);
*/
APU_DECLARE(apr_status_t) apr_queue_pop(apr_queue_t *queue, void **data);
+/**
+ * pop/get an object from the queue, blocking if the queue is already empty
+ *
+ * @param queue the queue
+ * @param data the data
+ * @param timeout The amount of time in microseconds to wait. This is
+ * a maximum, not a minimum. If the condition is signaled, we
+ * will wake up before this time, otherwise the error APR_TIMEUP
+ * is returned.
+ * @returns APR_TIMEUP the request timed out
+ * @returns APR_EINTR the blocking was interrupted (try again)
+ * @returns APR_EOF if the queue has been terminated
+ * @returns APR_SUCCESS on a successfull pop
+ */
+APU_DECLARE(apr_status_t) apr_queue_pop_timeout(apr_queue_t *queue, void **data, apr_interval_time_t timeout);
+
/**
* push/add a object to the queue, returning immediatly if the queue is full
*
diff --git a/libs/apr-util/misc/apr_queue.c b/libs/apr-util/misc/apr_queue.c
index 28d79afcb5..e905a53ebb 100644
--- a/libs/apr-util/misc/apr_queue.c
+++ b/libs/apr-util/misc/apr_queue.c
@@ -313,6 +313,71 @@ APU_DECLARE(apr_status_t) apr_queue_pop(apr_queue_t *queue, void **data)
return rv;
}
+/**
+ * Retrieves the next item from the queue. If there are no
+ * items available, it will block until one becomes available, or
+ * until timeout is elapsed. Once retrieved, the item is placed into
+ * the address specified by'data'.
+ */
+APU_DECLARE(apr_status_t) apr_queue_pop_timeout(apr_queue_t *queue, void **data, apr_interval_time_t timeout)
+{
+ apr_status_t rv;
+
+ if (queue->terminated) {
+ return APR_EOF; /* no more elements ever again */
+ }
+
+ rv = apr_thread_mutex_lock(queue->one_big_mutex);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ /* Keep waiting until we wake up and find that the queue is not empty. */
+ if (apr_queue_empty(queue)) {
+ if (!queue->terminated) {
+ queue->empty_waiters++;
+ rv = apr_thread_cond_timedwait(queue->not_empty, queue->one_big_mutex, timeout);
+ queue->empty_waiters--;
+ /* In the event of a timemout, APR_TIMEUP will be returned */
+ if (rv != APR_SUCCESS) {
+ apr_thread_mutex_unlock(queue->one_big_mutex);
+ return rv;
+ }
+ }
+ /* If we wake up and it's still empty, then we were interrupted */
+ if (apr_queue_empty(queue)) {
+ Q_DBG("queue empty (intr)", queue);
+ rv = apr_thread_mutex_unlock(queue->one_big_mutex);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ if (queue->terminated) {
+ return APR_EOF; /* no more elements ever again */
+ }
+ else {
+ return APR_EINTR;
+ }
+ }
+ }
+
+ *data = queue->data[queue->out];
+ queue->nelts--;
+
+ queue->out = (queue->out + 1) % queue->bounds;
+ if (queue->full_waiters) {
+ Q_DBG("signal !full", queue);
+ rv = apr_thread_cond_signal(queue->not_full);
+ if (rv != APR_SUCCESS) {
+ apr_thread_mutex_unlock(queue->one_big_mutex);
+ return rv;
+ }
+ }
+
+ rv = apr_thread_mutex_unlock(queue->one_big_mutex);
+ return rv;
+}
+
+
/**
* Retrieves the next item from the queue. If there are no
* items available, return APR_EAGAIN. Once retrieved,
diff --git a/libs/esl/fs_cli.c b/libs/esl/fs_cli.c
index 60dd8d8012..73bee7ab5e 100644
--- a/libs/esl/fs_cli.c
+++ b/libs/esl/fs_cli.c
@@ -999,7 +999,7 @@ int main(int argc, char *argv[])
int temp_log = -1;
int argv_error = 0;
int argv_exec = 0;
- char argv_command[256] = "";
+ char argv_command[1024] = "";
char argv_loglevel[128] = "";
int argv_quiet = 0;
int loops = 2, reconnect = 0;
diff --git a/libs/esl/perl/logger.pl b/libs/esl/perl/logger.pl
index d0dbb1750e..08213c033f 100644
--- a/libs/esl/perl/logger.pl
+++ b/libs/esl/perl/logger.pl
@@ -17,13 +17,13 @@ my $USAGE = "
FreeSWITCH Logger Utility
USAGE:
--h --helpThis help
+-h --help This help
-p --port Choose port
-P -pass Choose password
-f --file Output file
-pb --paste-bin Post to FreeSWITCH Paste Bin
-sp --sip-profiles List of SIP profiles to trace
--sd --sip-debug Set SIP debug level
+-sd --sip-debug Set SIP debug level
No arguments given will trace profile 'internal' to STDOUT
";
diff --git a/libs/freetdm/Makefile.am b/libs/freetdm/Makefile.am
index bc92e1db58..af26f7f2af 100644
--- a/libs/freetdm/Makefile.am
+++ b/libs/freetdm/Makefile.am
@@ -55,10 +55,6 @@ COMPILE = $(CC) $(FTDM_CFLAGS)
LTCOMPILE = $(LIBTOOL) --mode=compile --tag=CC $(COMPILE)
LINK = $(LIBTOOL) --mode=link --tag=CC $(CC) $(FTDM_CFLAGS) $(LDFLAGS) -o $@
-if WANT_DEBUGDTMF
-FTDM_CFLAGS += -DFTDM_DEBUG_DTMF
-endif
-
#
# GNU pkgconfig file
diff --git a/libs/freetdm/conf/freetdm.conf b/libs/freetdm/conf/freetdm.conf
index bbaf1e3687..2f9643dedd 100644
--- a/libs/freetdm/conf/freetdm.conf
+++ b/libs/freetdm/conf/freetdm.conf
@@ -45,3 +45,29 @@ fxs-channel => 1
number => 2
fxo-channel => 3
+; MFC-R2 typical span configuration
+
+; MFC-R2 with wanpipe (Sangoma)
+[span wanpipe myWanpipeSpan]
+trunk_type => E1
+cas-channel => 1-15:1101
+cas-channel => 17-31:1101
+
+; MFC-R2 with Zaptel/DAHDI
+[span zt myWanpipeSpan]
+trunk_type => E1
+cas-channel => 1-15:1101
+cas-channel => 17-31:1101
+
+; generic channel parameters
+; this parameters are accepted by any type of span/channel
+; remember that for generic channel parameters only channels
+; below the parameter within the span will be affected
+
+; Channel audio gain
+; rxgain => 0.0
+; txgain => 0.0
+
+; Whether to perform media dumps for DTMF debugging
+; debugdtmf => yes
+
diff --git a/libs/freetdm/conf/freetdm.conf.xml b/libs/freetdm/conf/freetdm.conf.xml
index 986074dffb..63a3ea62cd 100644
--- a/libs/freetdm/conf/freetdm.conf.xml
+++ b/libs/freetdm/conf/freetdm.conf.xml
@@ -1,52 +1,220 @@
+
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libs/freetdm/configure.ac b/libs/freetdm/configure.ac
index 8b878edc09..592dfd82a3 100644
--- a/libs/freetdm/configure.ac
+++ b/libs/freetdm/configure.ac
@@ -24,7 +24,12 @@ AC_PROG_MAKE_SET
AM_PROG_CC_C_O
AC_PROG_LIBTOOL
AC_PROG_INSTALL
-PKG_PROG_PKG_CONFIG
+
+# NOTE: pkg-config is used to detect libisdn
+m4_ifdef([PKG_PROG_PKG_CONFIG],
+ [PKG_PROG_PKG_CONFIG],
+ [AC_MSG_WARN([pkg-config missing (required for libisdn detection)])]
+)
AX_COMPILER_VENDOR
@@ -162,17 +167,6 @@ AC_ARG_WITH([pritap],
HAVE_PRITAP="${enable_pritap}"
AM_CONDITIONAL([HAVE_PRITAP],[test "${enable_pritap}" = "yes"])
-# debug dtmf?
-AC_ARG_WITH([debugdtmf],
- [AS_HELP_STRING([--with-debugdtmf], [Debug DTMF])],
- [case "${withval}" in
- no) enable_debugdtmf="no" ;;
- *) enable_debugdtmf="yes" ;;
- esac],
- [enable_debugdtmf="no"]
-)
-AM_CONDITIONAL([WANT_DEBUGDTMF], [test "${enable_debugdtmf}" = "yes"])
-
##
# OpenR2 stack
#
@@ -305,41 +299,44 @@ AC_ARG_WITH([libisdn],
if test "${with_libisdn}" != "no"
then
AC_MSG_RESULT([${as_nl}<<>> ftmod_isdn (libisdn stack)])
- PKG_CHECK_MODULES([libisdn],
- [libisdn >= 0.0.1],
- [AC_MSG_CHECKING([libisdn version])
- LIBISDN_VERSION="`${PKG_CONFIG} --modversion libisdn`"
- if test -z "${LIBISDN_VERSION}"; then
- AC_MSG_ERROR([Failed to retrieve libisdn version])
- fi
- AC_MSG_RESULT([${LIBISDN_VERSION}])
+ m4_ifdef([PKG_CHECK_MODULES],
+ [PKG_CHECK_MODULES([libisdn],
+ [libisdn >= 0.0.1],
+ [AC_MSG_CHECKING([libisdn version])
+ LIBISDN_VERSION="`${PKG_CONFIG} --modversion libisdn`"
+ if test -z "${LIBISDN_VERSION}"; then
+ AC_MSG_ERROR([Failed to retrieve libisdn version])
+ fi
+ AC_MSG_RESULT([${LIBISDN_VERSION}])
- # check features
- AC_MSG_CHECKING([for new experimental API])
- AC_COMPILE_IFELSE(
- [AC_LANG_PROGRAM(
- [#include
- #if !LIBISDN_FEATURE(API2)
- #error "libisdn API v2 not available"
- #endif
- ],
- [;]
- )],
- [AC_MSG_RESULT([yes])],
- [AC_MSG_RESULT([no])]
+ # check features
+ AC_MSG_CHECKING([for new experimental API])
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [#include
+ #if !LIBISDN_FEATURE(API2)
+ #error "libisdn API v2 not available"
+ #endif
+ ],
+ [;]
+ )],
+ [AC_MSG_RESULT([yes])],
+ [AC_MSG_RESULT([no])]
+ )
+
+ HAVE_LIBISDN="yes"
+ AC_DEFINE([HAVE_LIBISDN], [1], [libisdn support])
+ AC_SUBST([LIBISDN_CFLAGS], [${libisdn_CFLAGS}])
+ AC_SUBST([LIBISDN_CPPFLAGS],[${libisdn_CPPFLAGS}])
+ AC_SUBST([LIBISDN_LDFLAGS], [${libisdn_LDFLAGS}])
+ AC_SUBST([LIBISDN_LIBS], [${libisdn_LIBS}])
+ AC_SUBST([LIBISDN_VERSION])
+ ],
+ [AC_MSG_ERROR([Need libisdn-0.0.1 or higher])]
)
-
- HAVE_LIBISDN="yes"
- AC_DEFINE([HAVE_LIBISDN], [1], [libisdn support])
- AC_SUBST([LIBISDN_CFLAGS], [${libisdn_CFLAGS}])
- AC_SUBST([LIBISDN_CPPFLAGS],[${libisdn_CPPFLAGS}])
- AC_SUBST([LIBISDN_LDFLAGS], [${libisdn_LDFLAGS}])
- AC_SUBST([LIBISDN_LIBS], [${libisdn_LIBS}])
- AC_SUBST([LIBISDN_VERSION])
- ],
- [AC_MSG_ERROR([Need libisdn-0.0.1 or higher])]
+ AX_LIB_PCAP],
+ [AC_MSG_WARN([pkg-config missing (required for libisdn detection)])]
)
- AX_LIB_PCAP
fi
AM_CONDITIONAL([HAVE_LIBISDN], [test "${HAVE_LIBISDN}" = "yes"])
diff --git a/libs/freetdm/cyginstall.sh b/libs/freetdm/cyginstall.sh
index 9d486b7dce..e2d5885c4e 100644
--- a/libs/freetdm/cyginstall.sh
+++ b/libs/freetdm/cyginstall.sh
@@ -5,8 +5,9 @@ fsdir=../..
set -x
cp Debug/mod/*.dll $fsdir/Debug/mod/
cp mod_freetdm/Debug/*.pdb $fsdir/Debug/mod/
-cp Debug/*.dll $fsdir/Debug/
-cp Debug/*.pdb $fsdir/Debug/
+cp Debug/freetdm.dll $fsdir/Debug/
+cp Debug/ftmod_*.dll $fsdir/Debug/mod/
+cp Debug/*.pdb $fsdir/Debug/mod/
#cp Debug/testsangomaboost.exe $fsdir/Debug/
echo "FRIENDLY REMINDER: RECOMPILE ftmod_wanpipe WHENEVER YOU INSTALL NEW DRIVERS"
set +x
diff --git a/libs/freetdm/freetdm.2008.sln b/libs/freetdm/freetdm.2008.sln
index f059d941d3..0e374545eb 100644
--- a/libs/freetdm/freetdm.2008.sln
+++ b/libs/freetdm/freetdm.2008.sln
@@ -64,6 +64,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_sangoma_isdn", "src\f
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_r2", "src\ftmod\ftmod_r2\ftmod_r2.2008.vcproj", "{08C3EA27-A51D-47F8-B47D-B189C649CF30}"
+ ProjectSection(ProjectDependencies) = postProject
+ {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D}
+ EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -131,7 +134,6 @@ Global
{1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|Win32.ActiveCfg = Release|Win32
{1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|x64.ActiveCfg = Release|x64
{D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|Win32.ActiveCfg = Debug|Win32
- {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|Win32.Build.0 = Debug|Win32
{D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|x64.ActiveCfg = Debug|x64
{D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|x64.Build.0 = Debug|x64
{D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|Win32.ActiveCfg = Release|Win32
@@ -139,7 +141,6 @@ Global
{D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|x64.ActiveCfg = Release|x64
{D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|x64.Build.0 = Release|x64
{2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|Win32.ActiveCfg = Debug|Win32
- {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|Win32.Build.0 = Debug|Win32
{2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|x64.ActiveCfg = Debug|x64
{2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|x64.Build.0 = Debug|x64
{2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|Win32.ActiveCfg = Release|Win32
@@ -147,7 +148,6 @@ Global
{2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|x64.ActiveCfg = Release|x64
{2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|x64.Build.0 = Release|x64
{0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|Win32.ActiveCfg = Debug|Win32
- {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|Win32.Build.0 = Debug|Win32
{0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|x64.ActiveCfg = Debug|x64
{0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|x64.Build.0 = Debug|x64
{0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|Win32.ActiveCfg = Release|Win32
@@ -155,16 +155,13 @@ Global
{0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.ActiveCfg = Release|x64
{0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.Build.0 = Release|x64
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.ActiveCfg = Debug|Win32
- {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.Build.0 = Debug|Win32
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|x64.ActiveCfg = Debug|Win32
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.ActiveCfg = Release|Win32
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.Build.0 = Release|Win32
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|x64.ActiveCfg = Release|Win32
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.ActiveCfg = Debug|Win32
- {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.Build.0 = Debug|Win32
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|x64.ActiveCfg = Debug|Win32
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|Win32.ActiveCfg = Release|Win32
- {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|Win32.Build.0 = Release|Win32
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|x64.ActiveCfg = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
diff --git a/libs/freetdm/freetdm.2010.sln b/libs/freetdm/freetdm.2010.sln
new file mode 100644
index 0000000000..f4bd907a6d
--- /dev/null
+++ b/libs/freetdm/freetdm.2010.sln
@@ -0,0 +1,135 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "freetdm", "msvc\freetdm.2010.vcxproj", "{93B8812C-3EC4-4F78-8970-FFBFC99E167D}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testanalog", "msvc\testanalog\testanalog.2010.vcxproj", "{BB833648-BAFF-4BE2-94DB-F8BB043C588C}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testisdn", "msvc\testisdn\testisdn.2010.vcxproj", "{6DA6FD42-641D-4147-92F5-3BC4AAA6589B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_freetdm", "mod_freetdm\mod_freetdm.2010.vcxproj", "{FE3540C5-3303-46E0-A69E-D92F775687F1}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_analog", "src\ftmod\ftmod_analog\ftmod_analog.2010.vcxproj", "{37C94798-6E33-4B4F-8EE0-C72A7DC91157}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_analog_em", "src\ftmod\ftmod_analog_em\ftmod_analog_em.2010.vcxproj", "{B3F49375-2834-4937-9D8C-4AC2EC911010}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_isdn", "src\ftmod\ftmod_isdn\ftmod_isdn.2010.vcxproj", "{729344A5-D5E9-434D-8EE8-AF8C6C795D15}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_pika", "src\ftmod\ftmod_pika\ftmod_pika.2010.vcxproj", "{E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_wanpipe", "src\ftmod\ftmod_wanpipe\ftmod_wanpipe.2010.vcxproj", "{1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_sangoma_boost", "src\ftmod\ftmod_sangoma_boost\ftmod_sangoma_boost.2010.vcxproj", "{D021EF2A-460D-4827-A0F7-41FDECF46F1B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testboost", "msvc\testboost\testboost.2010.vcxproj", "{2B1BAF36-0241-43E7-B865-A8338AD48E2E}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testsangomaboost", "msvc\testboost\testsangomaboost.2010.vcxproj", "{0DA69C18-4FA1-4E8C-89CE-12498637C5BE}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_sangoma_isdn", "src\ftmod\ftmod_sangoma_isdn\ftmod_sangoma_isdn.2010.vcxproj", "{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_r2", "src\ftmod\ftmod_r2\ftmod_r2.2010.vcxproj", "{08C3EA27-A51D-47F8-B47D-B189C649CF30}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|Win32.ActiveCfg = Debug|Win32
+ {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|Win32.Build.0 = Debug|Win32
+ {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|x64.ActiveCfg = Debug|x64
+ {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|x64.Build.0 = Debug|x64
+ {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|Win32.ActiveCfg = Release|Win32
+ {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|Win32.Build.0 = Release|Win32
+ {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|x64.ActiveCfg = Release|x64
+ {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|x64.Build.0 = Release|x64
+ {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|Win32.ActiveCfg = Debug|Win32
+ {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|Win32.Build.0 = Debug|Win32
+ {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|x64.ActiveCfg = Debug|x64
+ {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|x64.Build.0 = Debug|x64
+ {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|Win32.ActiveCfg = Release|Win32
+ {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|Win32.Build.0 = Release|Win32
+ {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|x64.ActiveCfg = Release|x64
+ {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|x64.Build.0 = Release|x64
+ {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|x64.ActiveCfg = Debug|x64
+ {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|Win32.ActiveCfg = Release|Win32
+ {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|x64.ActiveCfg = Release|x64
+ {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.ActiveCfg = Debug|Win32
+ {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.Build.0 = Debug|Win32
+ {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|x64.ActiveCfg = Debug|x64
+ {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|x64.Build.0 = Debug|x64
+ {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|Win32.ActiveCfg = Release|Win32
+ {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|Win32.Build.0 = Release|Win32
+ {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|x64.ActiveCfg = Release|x64
+ {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|x64.Build.0 = Release|x64
+ {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|Win32.ActiveCfg = Debug|Win32
+ {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|Win32.Build.0 = Debug|Win32
+ {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|x64.ActiveCfg = Debug|x64
+ {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|x64.Build.0 = Debug|x64
+ {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|Win32.ActiveCfg = Release|Win32
+ {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|Win32.Build.0 = Release|Win32
+ {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|x64.ActiveCfg = Release|x64
+ {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|x64.Build.0 = Release|x64
+ {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|Win32.Build.0 = Debug|Win32
+ {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|x64.ActiveCfg = Debug|x64
+ {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|x64.Build.0 = Debug|x64
+ {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|Win32.ActiveCfg = Release|Win32
+ {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|Win32.Build.0 = Release|Win32
+ {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|x64.ActiveCfg = Release|x64
+ {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|x64.Build.0 = Release|x64
+ {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|Win32.ActiveCfg = Debug|Win32
+ {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|x64.ActiveCfg = Debug|x64
+ {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|Win32.ActiveCfg = Release|Win32
+ {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|x64.ActiveCfg = Release|x64
+ {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Debug|Win32.ActiveCfg = Debug|Win32
+ {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Debug|x64.ActiveCfg = Debug|x64
+ {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Release|Win32.ActiveCfg = Release|Win32
+ {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Release|x64.ActiveCfg = Release|x64
+ {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|Win32.ActiveCfg = Debug|Win32
+ {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|Win32.Build.0 = Debug|Win32
+ {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|x64.ActiveCfg = Debug|x64
+ {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|Win32.ActiveCfg = Release|Win32
+ {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|x64.ActiveCfg = Release|x64
+ {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|Win32.Build.0 = Debug|Win32
+ {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|x64.ActiveCfg = Debug|x64
+ {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|x64.Build.0 = Debug|x64
+ {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|Win32.ActiveCfg = Release|Win32
+ {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|Win32.Build.0 = Release|Win32
+ {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|x64.ActiveCfg = Release|x64
+ {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|x64.Build.0 = Release|x64
+ {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|Win32.ActiveCfg = Debug|Win32
+ {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|Win32.Build.0 = Debug|Win32
+ {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|x64.ActiveCfg = Debug|x64
+ {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|x64.Build.0 = Debug|x64
+ {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|Win32.ActiveCfg = Release|Win32
+ {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|Win32.Build.0 = Release|Win32
+ {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|x64.ActiveCfg = Release|x64
+ {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|x64.Build.0 = Release|x64
+ {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|Win32.ActiveCfg = Debug|Win32
+ {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|Win32.Build.0 = Debug|Win32
+ {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|x64.ActiveCfg = Debug|x64
+ {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|x64.Build.0 = Debug|x64
+ {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|Win32.ActiveCfg = Release|Win32
+ {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|Win32.Build.0 = Release|Win32
+ {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.ActiveCfg = Release|x64
+ {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.Build.0 = Release|x64
+ {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.Build.0 = Debug|Win32
+ {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|x64.ActiveCfg = Debug|x64
+ {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.ActiveCfg = Release|Win32
+ {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.Build.0 = Release|Win32
+ {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|x64.ActiveCfg = Release|x64
+ {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.ActiveCfg = Debug|Win32
+ {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|x64.ActiveCfg = Debug|x64
+ {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|Win32.ActiveCfg = Release|Win32
+ {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|x64.ActiveCfg = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.2010.vcxproj b/libs/freetdm/mod_freetdm/mod_freetdm.2010.vcxproj
new file mode 100644
index 0000000000..ec69333410
--- /dev/null
+++ b/libs/freetdm/mod_freetdm/mod_freetdm.2010.vcxproj
@@ -0,0 +1,217 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ mod_freetdm
+ {FE3540C5-3303-46E0-A69E-D92F775687F1}
+ mod_freetdm
+ Win32Proj
+
+
+
+ DynamicLibrary
+ MultiByte
+
+
+ DynamicLibrary
+ MultiByte
+
+
+ DynamicLibrary
+ MultiByte
+
+
+ DynamicLibrary
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ $(SolutionDir)$(PlatformName)\$(Configuration)\mod\
+ $(Platform)\$(Configuration)\
+ true
+ $(SolutionDir)$(PlatformName)\$(Configuration)\mod\
+ $(Platform)\$(Configuration)\
+ false
+ $(SolutionDir)$(PlatformName)\$(Configuration)\mod\
+ $(Platform)\$(Configuration)\
+ true
+ $(SolutionDir)$(PlatformName)\$(Configuration)\mod\
+ $(Platform)\$(Configuration)\
+ false
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+
+
+
+ Disabled
+ ../../../src/include;../src/include;../src/isdn/include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level4
+ true
+ ProgramDatabase
+
+
+ FreeSwitchCore.lib;%(AdditionalDependencies)
+ ../../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)
+ true
+ $(OutDir)$(TargetName).pdb
+ Windows
+ false
+
+
+ $(OutDir)mod_freetdm.lib
+ MachineX86
+
+
+
+
+ ../../../src/include;../src/include;../src/isdn/include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+
+
+ Level4
+ true
+ ProgramDatabase
+
+
+ FreeSwitchCore.lib;%(AdditionalDependencies)
+ ../../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)
+ true
+ $(OutDir)$(TargetName).pdb
+ Windows
+ true
+ true
+ UseLinkTimeCodeGeneration
+ false
+
+
+ $(OutDir)mod_freetdm.lib
+ MachineX86
+
+
+
+
+ X64
+
+
+ Disabled
+ ../../../src/include;../src/include;../src/isdn/include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level4
+ true
+ ProgramDatabase
+
+
+ FreeSwitchCore.lib;%(AdditionalDependencies)
+ ../../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)
+ true
+ $(OutDir)$(TargetName).pdb
+ Windows
+ false
+
+
+ $(OutDir)mod_freetdm.lib
+ MachineX64
+
+
+
+
+ X64
+
+
+ ../../../src/include;../src/include;../src/isdn/include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+
+
+ Level4
+ true
+ ProgramDatabase
+
+
+ FreeSwitchCore.lib;%(AdditionalDependencies)
+ ../../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)
+ true
+ $(OutDir)$(TargetName).pdb
+ Windows
+ true
+ true
+ UseLinkTimeCodeGeneration
+ false
+
+
+ $(OutDir)mod_freetdm.lib
+ MachineX64
+
+
+
+
+
+
+
+ {93b8812c-3ec4-4f78-8970-ffbfc99e167d}
+ false
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.2010.vcxproj.filters b/libs/freetdm/mod_freetdm/mod_freetdm.2010.vcxproj.filters
new file mode 100644
index 0000000000..92ac5ead47
--- /dev/null
+++ b/libs/freetdm/mod_freetdm/mod_freetdm.2010.vcxproj.filters
@@ -0,0 +1,14 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c
index a410e4eac6..38197bb2f0 100755
--- a/libs/freetdm/mod_freetdm/mod_freetdm.c
+++ b/libs/freetdm/mod_freetdm/mod_freetdm.c
@@ -149,6 +149,7 @@ 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 const char* channel_get_variable(switch_core_session_t *session, switch_event_t *var_event, const char *variable_name);
ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session_t **sp);
void dump_chan(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stream);
void dump_chan_xml(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stream);
@@ -425,8 +426,11 @@ static switch_status_t channel_on_routing(switch_core_session_t *session)
tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL);
+ assert(tech_pvt->ftdmchan != NULL);
+
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel));
+ ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROCEED);
return SWITCH_STATUS_SUCCESS;
}
@@ -837,9 +841,9 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session,
assert(tech_pvt != NULL);
if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
- switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE);
- return SWITCH_STATUS_FALSE;
- }
+ switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE);
+ return SWITCH_STATUS_FALSE;
+ }
if (ftdm_channel_call_check_hangup(tech_pvt->ftdmchan)) {
return SWITCH_STATUS_SUCCESS;
@@ -852,7 +856,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session,
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_RINGING:
{
- ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROGRESS);
+ ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_RINGING);
}
break;
case SWITCH_MESSAGE_INDICATE_PROGRESS:
@@ -884,9 +888,9 @@ static switch_status_t channel_receive_message_fxo(switch_core_session_t *sessio
assert(tech_pvt != NULL);
if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
- switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE);
- return SWITCH_STATUS_FALSE;
- }
+ switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE);
+ return SWITCH_STATUS_FALSE;
+ }
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
return SWITCH_STATUS_SUCCESS;
@@ -935,7 +939,7 @@ static switch_status_t channel_receive_message_fxs(switch_core_session_t *sessio
!switch_channel_test_flag(channel, CF_EARLY_MEDIA) &&
!switch_channel_test_flag(channel, CF_RING_READY)
) {
- ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_RING);
+ ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_RINGING);
switch_channel_mark_ring_ready(channel);
}
break;
@@ -1046,6 +1050,27 @@ switch_io_routines_t freetdm_io_routines = {
/*.receive_message*/ channel_receive_message
};
+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;
+ }
+ }
+ if ((variable = switch_core_get_variable(variable_name))) {
+ return variable;
+ }
+ return NULL;
+}
+
/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines
that allocate memory or you will have 1 channel with memory allocated from another channel's pool!
*/
@@ -1223,20 +1248,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
}
}
- if (session) {
- /* take out some other values from the session if they're present */
- switch_channel_t *channel = switch_core_session_get_channel(session);
- const char *freetdmvar;
- freetdmvar = switch_channel_get_variable(channel, "freetdm_bearer_capability");
- if (freetdmvar) {
- caller_data.bearer_capability = (uint8_t)atoi(freetdmvar);
- }
- freetdmvar = switch_channel_get_variable(channel, "freetdm_bearer_layer1");
- if (freetdmvar) {
- caller_data.bearer_layer1 = (uint8_t)atoi(freetdmvar);
- }
- }
-
if (switch_test_flag(outbound_profile, SWITCH_CPF_SCREEN)) {
caller_data.screen = 1;
}
@@ -1245,29 +1256,37 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
caller_data.pres = 1;
}
- if (!zstr(dest)) {
- ftdm_set_string(caller_data.dnis.digits, dest);
+ if ((var = channel_get_variable(session, var_event, "freetdm_bearer_capability"))) {
+ caller_data.bearer_capability = (uint8_t)atoi(var);
}
- if ((var = switch_event_get_header(var_event, "freetdm_outbound_ton")) || (var = switch_core_get_variable("freetdm_outbound_ton"))) {
- if (!strcasecmp(var, "national")) {
- caller_data.dnis.type = FTDM_TON_NATIONAL;
- } else if (!strcasecmp(var, "international")) {
- caller_data.dnis.type = FTDM_TON_INTERNATIONAL;
- } else if (!strcasecmp(var, "local")) {
- caller_data.dnis.type = FTDM_TON_SUBSCRIBER_NUMBER;
- } else if (!strcasecmp(var, "unknown")) {
- caller_data.dnis.type = FTDM_TON_UNKNOWN;
- }
+ if ((var = channel_get_variable(session, var_event, "freetdm_bearer_layer1"))) {
+ caller_data.bearer_layer1 = (uint8_t)atoi(var);
+ }
+
+ if ((var = channel_get_variable(session, var_event, "freetdm_screening_ind"))) {
+ ftdm_set_screening_ind(var, &caller_data.screen);
+ }
+
+ if ((var = channel_get_variable(session, var_event, "freetdm_presentation_ind"))) {
+ ftdm_set_presentation_ind(var, &caller_data.pres);
+ }
+
+ if ((var = channel_get_variable(session, var_event, "freetdm_outbound_ton"))) {
+ ftdm_set_ton(var, &caller_data.dnis.type);
} else {
caller_data.dnis.type = outbound_profile->destination_number_ton;
}
- if ((var = switch_event_get_header(var_event, "freetdm_custom_call_data")) || (var = switch_core_get_variable("freetdm_custom_call_data"))) {
+ if ((var = channel_get_variable(session, var_event, "freetdm_custom_call_data"))) {
ftdm_set_string(caller_data.raw_data, var);
caller_data.raw_data_len = (uint32_t)strlen(var);
}
+ if (!zstr(dest)) {
+ ftdm_set_string(caller_data.dnis.digits, dest);
+ }
+
caller_data.dnis.plan = outbound_profile->destination_number_numplan;
/* blindly copy data from outbound_profile. They will be overwritten
@@ -1310,7 +1329,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
char *v = h->name + FREETDM_VAR_PREFIX_LEN;
if (!zstr(v)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding outbound freetdm variable %s=%s to channel %d:%d\n", v, h->value, span_id, chan_id);
- ftdm_channel_add_var(ftdmchan, v, h->value);
+ ftdm_call_add_var(&caller_data, v, h->value);
}
}
}
@@ -1398,6 +1417,24 @@ fail:
}
+static void ftdm_enable_channel_dtmf(ftdm_channel_t *fchan, switch_channel_t *channel)
+{
+ if (channel) {
+ const char *var;
+ if ((var = switch_channel_get_variable(channel, "freetdm_disable_dtmf"))) {
+ if (switch_true(var)) {
+ ftdm_channel_command(fchan, FTDM_COMMAND_DISABLE_DTMF_DETECT, NULL);
+ ftdm_log(FTDM_LOG_INFO, "DTMF detection disabled in channel %d:%d\n", ftdm_channel_get_span_id(fchan), ftdm_channel_get_id(fchan));
+ return;
+ }
+ }
+ /* the variable is not present or has a negative value then proceed to enable DTMF ... */
+ }
+ if (ftdm_channel_command(fchan, FTDM_COMMAND_ENABLE_DTMF_DETECT, NULL) != FTDM_SUCCESS) {
+ ftdm_log(FTDM_LOG_ERROR, "Failed to enable DTMF detection in channel %d:%d\n", ftdm_channel_get_span_id(fchan), ftdm_channel_get_id(fchan));
+ }
+}
+
ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session_t **sp)
{
switch_core_session_t *session = NULL;
@@ -1421,6 +1458,9 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session
return FTDM_FAIL;
}
+ /* I guess we always want DTMF detection */
+ ftdm_enable_channel_dtmf(sigmsg->channel, NULL);
+
switch_core_session_add_stream(session, NULL);
tech_pvt = (private_t *) switch_core_session_alloc(session, sizeof(private_t));
@@ -1488,6 +1528,7 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session
switch_channel_set_variable_printf(channel, "freetdm_chan_number", "%d", chanid);
switch_channel_set_variable_printf(channel, "freetdm_bearer_capability", "%d", channel_caller_data->bearer_capability);
switch_channel_set_variable_printf(channel, "freetdm_bearer_layer1", "%d", channel_caller_data->bearer_layer1);
+
if (globals.sip_headers) {
switch_channel_set_variable(channel, "sip_h_X-FreeTDM-SpanName", ftdm_channel_get_span_name(sigmsg->channel));
switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-SpanNumber", "%d", spanid);
@@ -1521,8 +1562,18 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session
ftdm_channel_get_current_var(curr, &var_name, &var_value);
snprintf(name, sizeof(name), FREETDM_VAR_PREFIX "%s", var_name);
switch_channel_set_variable_printf(channel, name, "%s", var_value);
+ }
+
+ /* Add any call variable to the dial plan */
+ iter = ftdm_call_get_var_iterator(channel_caller_data, iter);
+ for (curr = iter ; curr; curr = ftdm_iterator_next(curr)) {
+ ftdm_call_get_current_var(curr, &var_name, &var_value);
+ snprintf(name, sizeof(name), FREETDM_VAR_PREFIX "%s", var_name);
+ switch_channel_set_variable_printf(channel, name, "%s", var_value);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Call Variable: %s=%s\n", name, var_value);
}
ftdm_iterator_free(iter);
+
switch_channel_set_state(channel, CS_INIT);
if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) {
@@ -1614,24 +1665,6 @@ static FIO_SIGNAL_CB_FUNCTION(on_common_signal)
return FTDM_BREAK;
}
-static void ftdm_enable_channel_dtmf(ftdm_channel_t *fchan, switch_channel_t *channel)
-{
- if (channel) {
- const char *var;
- if ((var = switch_channel_get_variable(channel, "freetdm_disable_dtmf"))) {
- if (switch_true(var)) {
- ftdm_channel_command(fchan, FTDM_COMMAND_DISABLE_DTMF_DETECT, NULL);
- ftdm_log(FTDM_LOG_INFO, "DTMF detection disabled in channel %d:%d\n", ftdm_channel_get_span_id(fchan), ftdm_channel_get_id(fchan));
- return;
- }
- }
- /* the variable is not present or has a negative value then proceed to enable DTMF ... */
- }
- if (ftdm_channel_command(fchan, FTDM_COMMAND_ENABLE_DTMF_DETECT, NULL) != FTDM_SUCCESS) {
- ftdm_log(FTDM_LOG_ERROR, "Failed to enable DTMF detection in channel %d:%d\n", ftdm_channel_get_span_id(fchan), ftdm_channel_get_id(fchan));
- }
-}
-
static FIO_SIGNAL_CB_FUNCTION(on_fxo_signal)
{
switch_core_session_t *session = NULL;
@@ -1639,11 +1672,11 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxo_signal)
ftdm_status_t status;
uint32_t spanid;
uint32_t chanid;
- ftdm_caller_data_t *callerdata;
+ ftdm_caller_data_t *caller_data;
spanid = ftdm_channel_get_span_id(sigmsg->channel);
chanid = ftdm_channel_get_id(sigmsg->channel);
- callerdata = ftdm_channel_get_caller_data(sigmsg->channel);
+ caller_data = ftdm_channel_get_caller_data(sigmsg->channel);
ftdm_log(FTDM_LOG_DEBUG, "got FXO sig %d:%d [%s]\n", spanid, chanid, ftdm_signal_event2str(sigmsg->event_id));
@@ -1666,7 +1699,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxo_signal)
switch_set_flag_locked(tech_pvt, TFLAG_DEAD);
ftdm_channel_clear_token(sigmsg->channel, 0);
channel = switch_core_session_get_channel(session);
- switch_channel_hangup(channel, callerdata->hangup_cause);
+ switch_channel_hangup(channel, caller_data->hangup_cause);
ftdm_channel_clear_token(sigmsg->channel, switch_core_session_get_uuid(session));
switch_core_session_rwunlock(session);
}
@@ -1690,7 +1723,8 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxo_signal)
}
}
break;
-
+ case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
+
default:
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled msg type %d for channel %d:%d\n",
@@ -1744,6 +1778,8 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxs_signal)
}
}
break;
+ case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
+
case FTDM_SIGEVENT_STOP:
{
private_t *tech_pvt = NULL;
@@ -1966,7 +2002,9 @@ static FIO_SIGNAL_CB_FUNCTION(on_r2_signal)
status = ftdm_channel_from_event(sigmsg, &session);
}
break;
-
+
+ case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
+
/* on DNIS received from the R2 forward side, return status == FTDM_BREAK to stop requesting DNIS */
case FTDM_SIGEVENT_COLLECTED_DIGIT:
{
@@ -2007,7 +2045,6 @@ static FIO_SIGNAL_CB_FUNCTION(on_r2_signal)
break;
case FTDM_SIGEVENT_PROGRESS:
- case FTDM_SIGEVENT_PROGRESS_MEDIA:
{
if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
channel = switch_core_session_get_channel(session);
@@ -2017,6 +2054,16 @@ static FIO_SIGNAL_CB_FUNCTION(on_r2_signal)
}
break;
+ case FTDM_SIGEVENT_PROGRESS_MEDIA:
+ {
+ if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
+ channel = switch_core_session_get_channel(session);
+ switch_channel_mark_pre_answered(channel);
+ switch_core_session_rwunlock(session);
+ }
+ }
+ break;
+
case FTDM_SIGEVENT_UP:
{
if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
@@ -2028,6 +2075,16 @@ static FIO_SIGNAL_CB_FUNCTION(on_r2_signal)
}
break;
+ case FTDM_SIGEVENT_SIGSTATUS_CHANGED:
+ {
+ ftdm_signaling_status_t sigstatus = sigmsg->raw_data ? *((ftdm_signaling_status_t*)(sigmsg->raw_data)) : sigmsg->sigstatus;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%d:%d signalling changed to: %s\n",
+ spanid, chanid, ftdm_signaling_status2str(sigstatus));
+ }
+ break;
+
+ case FTDM_SIGEVENT_PROCEED:{} break;
+
default:
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled event %d from R2 for channel %d:%d\n",
@@ -2059,10 +2116,14 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
switch(sigmsg->event_id) {
case FTDM_SIGEVENT_START:
{
- ftdm_enable_channel_dtmf(sigmsg->channel, NULL);
+ ftdm_call_add_var(caller_data, "screening_ind", ftdm_screening2str(caller_data->screen));
+ ftdm_call_add_var(caller_data, "presentation_ind", ftdm_presentation2str(caller_data->pres));
return ftdm_channel_from_event(sigmsg, &session);
}
break;
+
+ case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
+
case FTDM_SIGEVENT_STOP:
case FTDM_SIGEVENT_RESTART:
{
@@ -2118,7 +2179,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
spanid, chanid, (uuid) ? uuid : "N/A");
}
}
- break;
+ break;
case FTDM_SIGEVENT_SIGSTATUS_CHANGED:
{
ftdm_signaling_status_t sigstatus = sigmsg->raw_data ? *((ftdm_signaling_status_t*)(sigmsg->raw_data)) : sigmsg->sigstatus;
@@ -2126,6 +2187,10 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
spanid, chanid, ftdm_signaling_status2str(sigstatus));
}
break;
+ case FTDM_SIGEVENT_PROCEED:
+ case FTDM_SIGEVENT_FACILITY:
+ /* FS does not have handlers for these messages, so ignore them for now */
+ break;
default:
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled msg type %d for channel %d:%d\n",
@@ -3193,33 +3258,10 @@ static switch_status_t load_config(void)
if ((spans = switch_xml_child(cfg, "r2_spans"))) {
for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) {
- char *id = (char *) switch_xml_attr(myspan, "id");
char *name = (char *) switch_xml_attr(myspan, "name");
+ char *configname = (char *) switch_xml_attr(myspan, "cfgprofile");
ftdm_status_t zstatus = FTDM_FAIL;
- /* strings */
- const char *variant = "itu";
- const char *category = "national_subscriber";
- const char *logdir = "/usr/local/freeswitch/log/"; /* FIXME: get PREFIX variable */
- const char *logging = "notice,warning,error";
- const char *advanced_protocol_file = "";
-
- /* booleans */
- int call_files = 0;
- int get_ani_first = -1;
- int immediate_accept = -1;
- int double_answer = -1;
- int skip_category = -1;
- int forced_release = -1;
- int charge_calls = -1;
-
- /* integers */
- int mfback_timeout = -1;
- int metering_pulse_timeout = -1;
- int allow_collect_calls = -1;
- int max_ani = 10;
- int max_dnis = 4;
-
/* common non r2 stuff */
const char *context = "default";
const char *dialplan = "XML";
@@ -3228,53 +3270,29 @@ static switch_status_t load_config(void)
uint32_t span_id = 0;
ftdm_span_t *span = NULL;
+ ftdm_conf_parameter_t spanparameters[30];
+ unsigned paramindex = 0;
+
+ if (!name) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "'name' attribute required for R2 spans!\n");
+ continue;
+ }
+
+ memset(spanparameters, 0, sizeof(spanparameters));
+
+ if (configname) {
+ paramindex = add_profile_parameters(cfg, configname, spanparameters, ftdm_array_len(spanparameters));
+ if (paramindex) {
+ ftdm_log(FTDM_LOG_DEBUG, "Added %d parameters from profile %s for span %d\n", paramindex, configname, span_id);
+ }
+ }
for (param = switch_xml_child(myspan, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
/* string parameters */
- if (!strcasecmp(var, "variant")) {
- variant = val;
- } else if (!strcasecmp(var, "category")) {
- category = val;
- } else if (!strcasecmp(var, "logdir")) {
- logdir = val;
- } else if (!strcasecmp(var, "logging")) {
- logging = val;
- } else if (!strcasecmp(var, "advanced_protocol_file")) {
- advanced_protocol_file = val;
-
- /* booleans */
- } else if (!strcasecmp(var, "allow_collect_calls")) {
- allow_collect_calls = switch_true(val);
- } else if (!strcasecmp(var, "immediate_accept")) {
- immediate_accept = switch_true(val);
- } else if (!strcasecmp(var, "double_answer")) {
- double_answer = switch_true(val);
- } else if (!strcasecmp(var, "skip_category")) {
- skip_category = switch_true(var);
- } else if (!strcasecmp(var, "forced_release")) {
- forced_release = switch_true(val);
- } else if (!strcasecmp(var, "charge_calls")) {
- charge_calls = switch_true(val);
- } else if (!strcasecmp(var, "get_ani_first")) {
- get_ani_first = switch_true(val);
- } else if (!strcasecmp(var, "call_files")) {
- call_files = switch_true(val);
-
- /* integers */
- } else if (!strcasecmp(var, "mfback_timeout")) {
- mfback_timeout = atoi(val);
- } else if (!strcasecmp(var, "metering_pulse_timeout")) {
- metering_pulse_timeout = atoi(val);
- } else if (!strcasecmp(var, "max_ani")) {
- max_ani = atoi(val);
- } else if (!strcasecmp(var, "max_dnis")) {
- max_dnis = atoi(val);
-
- /* common non r2 stuff */
- } else if (!strcasecmp(var, "context")) {
+ if (!strcasecmp(var, "context")) {
context = val;
} else if (!strcasecmp(var, "dialplan")) {
dialplan = val;
@@ -3282,57 +3300,23 @@ static switch_status_t load_config(void)
dial_regex = val;
} else if (!strcasecmp(var, "fail-dial-regex")) {
fail_dial_regex = val;
+ } else {
+ spanparameters[paramindex].var = var;
+ spanparameters[paramindex].val = val;
+ paramindex++;
}
}
- if (!id && !name) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required param 'id'\n");
- continue;
- }
-
- if (name) {
- zstatus = ftdm_span_find_by_name(name, &span);
- } else {
- if (switch_is_number(id)) {
- span_id = atoi(id);
- zstatus = ftdm_span_find(span_id, &span);
- }
-
- if (zstatus != FTDM_SUCCESS) {
- zstatus = ftdm_span_find_by_name(id, &span);
- }
- }
-
+ zstatus = ftdm_span_find_by_name(name, &span);
if (zstatus != FTDM_SUCCESS) {
- ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name));
+ ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM R2 Span '%s'\n", name);
continue;
}
+ span_id = ftdm_span_get_id(span);
- if (!span_id) {
- span_id = ftdm_span_get_id(span);
- }
-
- if (ftdm_configure_span(span, "r2", on_r2_signal,
- "variant", variant,
- "max_ani", max_ani,
- "max_dnis", max_dnis,
- "category", category,
- "logdir", logdir,
- "logging", logging,
- "advanced_protocol_file", advanced_protocol_file,
- "allow_collect_calls", allow_collect_calls,
- "immediate_accept", immediate_accept,
- "double_answer", double_answer,
- "skip_category", skip_category,
- "forced_release", forced_release,
- "charge_calls", charge_calls,
- "get_ani_first", get_ani_first,
- "call_files", call_files,
- "mfback_timeout", mfback_timeout,
- "metering_pulse_timeout", metering_pulse_timeout,
- FTDM_TAG_END) != FTDM_SUCCESS) {
- ftdm_log(FTDM_LOG_ERROR, "Error configuring R2 FreeTDM span %d, error: %s\n",
- span_id, ftdm_span_get_last_error(span));
+ if (ftdm_configure_span_signaling(span, "r2", on_r2_signal, spanparameters) != FTDM_SUCCESS) {
+ ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM R2 span %s, error: %s\n",
+ name, ftdm_span_get_last_error(span));
continue;
}
@@ -3347,10 +3331,10 @@ static switch_status_t load_config(void)
SPAN_CONFIG[span_id].span = span;
switch_copy_string(SPAN_CONFIG[span_id].context, context, sizeof(SPAN_CONFIG[span_id].context));
switch_copy_string(SPAN_CONFIG[span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span_id].dialplan));
- switch_copy_string(SPAN_CONFIG[span_id].type, "r2", sizeof(SPAN_CONFIG[span_id].type));
+ switch_copy_string(SPAN_CONFIG[span_id].type, "R2", sizeof(SPAN_CONFIG[span_id].type));
if (ftdm_span_start(span) == FTDM_FAIL) {
- ftdm_log(FTDM_LOG_ERROR, "Error starting R2 FreeTDM span %d, error: %s\n", span_id, ftdm_span_get_last_error(span));
+ ftdm_log(FTDM_LOG_ERROR, "Error starting FreeTDM R2 span %s, error: %s\n", name, ftdm_span_get_last_error(span));
continue;
}
}
diff --git a/libs/freetdm/msvc/freetdm.2010.vcxproj b/libs/freetdm/msvc/freetdm.2010.vcxproj
new file mode 100644
index 0000000000..71eb6dbf22
--- /dev/null
+++ b/libs/freetdm/msvc/freetdm.2010.vcxproj
@@ -0,0 +1,223 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ freetdm
+ {93B8812C-3EC4-4F78-8970-FFBFC99E167D}
+ freetdm
+ Win32Proj
+
+
+
+ DynamicLibrary
+ MultiByte
+ true
+
+
+ DynamicLibrary
+ MultiByte
+
+
+ DynamicLibrary
+ MultiByte
+ true
+
+
+ DynamicLibrary
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+
+
+
+ $(IntDir)BuildLog-freetdm.htm
+
+
+ Disabled
+ ../src/include;../src/include/private;../src/isdn/include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+ false
+ false
+
+
+ Level4
+ true
+ ProgramDatabase
+ CompileAsC
+
+
+ true
+
+
+
+
+ $(IntDir)BuildLog-freetdm.htm
+
+
+ ../src/include;../src/include/private;../src/isdn/include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ false
+ false
+
+
+ Level4
+ true
+ ProgramDatabase
+ CompileAsC
+
+
+
+
+ $(IntDir)BuildLog-freetdm.htm
+
+
+ X64
+
+
+ Disabled
+ ../src/include;../src/include/private;../src/isdn/include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+ false
+ false
+
+
+ Level4
+ true
+ ProgramDatabase
+ CompileAsC
+
+
+ true
+ MachineX64
+
+
+
+
+ $(IntDir)BuildLog-freetdm.htm
+
+
+ X64
+
+
+ ../src/include;../src/include/private;../src/isdn/include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ false
+ false
+
+
+ Level4
+ true
+ ProgramDatabase
+ CompileAsC
+
+
+ MachineX64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/msvc/freetdm.2010.vcxproj.filters b/libs/freetdm/msvc/freetdm.2010.vcxproj.filters
new file mode 100644
index 0000000000..ed642baf3d
--- /dev/null
+++ b/libs/freetdm/msvc/freetdm.2010.vcxproj.filters
@@ -0,0 +1,128 @@
+
+
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj b/libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj
new file mode 100644
index 0000000000..719dc618a9
--- /dev/null
+++ b/libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj
@@ -0,0 +1,213 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ testanalog
+ {BB833648-BAFF-4BE2-94DB-F8BB043C588C}
+ testanalog
+ Win32Proj
+
+
+
+ Application
+ Unicode
+ true
+
+
+ Application
+ Unicode
+
+
+ Application
+ Unicode
+ true
+
+
+ Application
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ false
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ false
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+
+
+
+ $(IntDir)BuildLog-testanalog.htm
+
+
+ Disabled
+ ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level4
+ true
+ EditAndContinue
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Console
+ false
+
+
+ MachineX86
+
+
+
+
+ $(IntDir)BuildLog-testanalog.htm
+
+
+ ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+
+
+ Level4
+ true
+ ProgramDatabase
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Console
+ true
+ true
+ false
+
+
+ MachineX86
+
+
+
+
+ $(IntDir)BuildLog-testanalog.htm
+
+
+ X64
+
+
+ Disabled
+ ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level4
+ true
+ ProgramDatabase
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Console
+ false
+
+
+ MachineX64
+
+
+
+
+ $(IntDir)BuildLog-testanalog.htm
+
+
+ X64
+
+
+ ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+
+
+ Level4
+ true
+ ProgramDatabase
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Console
+ true
+ true
+ false
+
+
+ MachineX64
+
+
+
+
+
+
+
+ {93b8812c-3ec4-4f78-8970-ffbfc99e167d}
+ false
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj.filters b/libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj.filters
new file mode 100644
index 0000000000..7ac3635cc5
--- /dev/null
+++ b/libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj.filters
@@ -0,0 +1,14 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/msvc/testboost/testboost.2008.vcproj b/libs/freetdm/msvc/testboost/testboost.2008.vcproj
index afb44b6469..5707033f33 100644
--- a/libs/freetdm/msvc/testboost/testboost.2008.vcproj
+++ b/libs/freetdm/msvc/testboost/testboost.2008.vcproj
@@ -22,7 +22,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ testboost
+ {2B1BAF36-0241-43E7-B865-A8338AD48E2E}
+ testboost
+ Win32Proj
+
+
+
+ Application
+ Unicode
+ true
+
+
+ Application
+ Unicode
+
+
+ Application
+ Unicode
+ true
+
+
+ Application
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\testboost\$(Configuration)\
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\testboost\$(Configuration)\
+ false
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\testboost\$(Configuration)\
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\testboost\$(Configuration)\
+ false
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+
+
+
+ $(IntDir)BuildLog-testboost.htm
+
+
+ Disabled
+ ../../src/include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level4
+ true
+ EditAndContinue
+ 4100;%(DisableSpecificWarnings)
+
+
+ ..\..\debug\freetdm.lib;%(AdditionalDependencies)
+ true
+ Console
+ false
+
+
+ MachineX86
+
+
+
+
+ $(IntDir)BuildLog-testboost.htm
+
+
+ ../../src/include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+
+
+ Level4
+ true
+ ProgramDatabase
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Console
+ true
+ true
+ false
+
+
+ MachineX86
+
+
+
+
+ $(IntDir)BuildLog-testboost.htm
+
+
+ X64
+
+
+ Disabled
+ ../../src/include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level4
+ true
+ ProgramDatabase
+ 4100;%(DisableSpecificWarnings)
+
+
+ freetdm.lib;%(AdditionalDependencies)
+ true
+ Console
+ false
+
+
+ MachineX64
+ ../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)
+
+
+
+
+ $(IntDir)BuildLog-testboost.htm
+
+
+ X64
+
+
+ ../../src/include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+
+
+ Level4
+ true
+ ProgramDatabase
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Console
+ true
+ true
+ false
+
+
+ MachineX64
+ freetdm.lib;%(AdditionalDependencies)
+ ../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)
+
+
+
+
+
+
+
+ {93b8812c-3ec4-4f78-8970-ffbfc99e167d}
+ false
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/msvc/testboost/testboost.2010.vcxproj.filters b/libs/freetdm/msvc/testboost/testboost.2010.vcxproj.filters
new file mode 100644
index 0000000000..74181d60a8
--- /dev/null
+++ b/libs/freetdm/msvc/testboost/testboost.2010.vcxproj.filters
@@ -0,0 +1,14 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/msvc/testboost/testsangomaboost.2008.vcproj b/libs/freetdm/msvc/testboost/testsangomaboost.2008.vcproj
index 834b298505..29c4a2723e 100644
--- a/libs/freetdm/msvc/testboost/testsangomaboost.2008.vcproj
+++ b/libs/freetdm/msvc/testboost/testsangomaboost.2008.vcproj
@@ -97,83 +97,6 @@
Name="VCPostBuildEventTool"
/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj b/libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj
new file mode 100644
index 0000000000..5994da6f1a
--- /dev/null
+++ b/libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj
@@ -0,0 +1,218 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ testsangomaboost
+ {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}
+ testsangomaboost
+ Win32Proj
+
+
+
+ Application
+ Unicode
+ true
+
+
+ Application
+ Unicode
+
+
+ Application
+ Unicode
+ true
+
+
+ Application
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ false
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ false
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+
+
+
+ $(IntDir)BuildLog-testsangomaboost.htm
+
+
+ Disabled
+ ../../src/include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level4
+ true
+ EditAndContinue
+ 4100;%(DisableSpecificWarnings)
+
+
+ ..\..\debug\freetdm.lib;%(AdditionalDependencies)
+ true
+ Console
+ false
+
+
+ MachineX86
+
+
+
+
+ $(IntDir)BuildLog-testsangomaboost.htm
+
+
+ ../../src/include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+
+
+ Level4
+ true
+ ProgramDatabase
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Console
+ true
+ true
+ false
+
+
+ MachineX86
+
+
+
+
+ $(IntDir)BuildLog-testsangomaboost.htm
+
+
+ X64
+
+
+ Disabled
+ ../../src/include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level4
+ false
+ ProgramDatabase
+ 4100;%(DisableSpecificWarnings)
+
+
+ freetdm.lib;%(AdditionalDependencies)
+ true
+ Console
+ false
+
+
+ MachineX64
+ ../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)
+
+
+
+
+ $(IntDir)BuildLog-testsangomaboost.htm
+
+
+ X64
+
+
+ ../../src/include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+
+
+ Level4
+ false
+ ProgramDatabase
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Console
+ true
+ true
+ false
+
+
+ MachineX64
+ freetdm.lib;%(AdditionalDependencies)
+ ../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)
+
+
+
+
+
+
+
+ {93b8812c-3ec4-4f78-8970-ffbfc99e167d}
+ false
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj.filters b/libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj.filters
new file mode 100644
index 0000000000..e72f14e161
--- /dev/null
+++ b/libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj.filters
@@ -0,0 +1,14 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj b/libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj
new file mode 100644
index 0000000000..2dfdeb042f
--- /dev/null
+++ b/libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj
@@ -0,0 +1,213 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ testisdn
+ {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}
+ testisdn
+ Win32Proj
+
+
+
+ Application
+ Unicode
+ true
+
+
+ Application
+ Unicode
+
+
+ Application
+ Unicode
+ true
+
+
+ Application
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ false
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ false
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+
+
+
+ $(IntDir)BuildLog-testisdn.htm
+
+
+ Disabled
+ ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level4
+ true
+ EditAndContinue
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Console
+ false
+
+
+ MachineX86
+
+
+
+
+ $(IntDir)BuildLog-testisdn.htm
+
+
+ ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+
+
+ Level4
+ true
+ ProgramDatabase
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Console
+ true
+ true
+ false
+
+
+ MachineX86
+
+
+
+
+ $(IntDir)BuildLog-testisdn.htm
+
+
+ X64
+
+
+ Disabled
+ ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level4
+ true
+ ProgramDatabase
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Console
+ false
+
+
+ MachineX64
+
+
+
+
+ $(IntDir)BuildLog-testisdn.htm
+
+
+ X64
+
+
+ ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+
+
+ Level4
+ true
+ ProgramDatabase
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Console
+ true
+ true
+ false
+
+
+ MachineX64
+
+
+
+
+
+
+
+ {93b8812c-3ec4-4f78-8970-ffbfc99e167d}
+ false
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj.filters b/libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj.filters
new file mode 100644
index 0000000000..9d48828d4a
--- /dev/null
+++ b/libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj.filters
@@ -0,0 +1,14 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/openzap.2005.sln b/libs/freetdm/openzap.2005.sln
deleted file mode 100644
index c9f666b381..0000000000
--- a/libs/freetdm/openzap.2005.sln
+++ /dev/null
@@ -1,82 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 9.00
-# Visual Studio 2005
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openzap", "msvc\openzap.2005.vcproj", "{93B8812C-3EC4-4F78-8970-FFBFC99E167D}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testanalog", "msvc\testanalog\testanalog.2005.vcproj", "{BB833648-BAFF-4BE2-94DB-F8BB043C588C}"
- ProjectSection(ProjectDependencies) = postProject
- {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testisdn", "msvc\testisdn\testisdn.2005.vcproj", "{6DA6FD42-641D-4147-92F5-3BC4AAA6589B}"
- ProjectSection(ProjectDependencies) = postProject
- {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_openzap", "mod_openzap\mod_openzap.2005.vcproj", "{FE3540C5-3303-46E0-A69E-D92F775687F1}"
- ProjectSection(ProjectDependencies) = postProject
- {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ozmod_analog", "src\ozmod\ozmod_analog\ozmod_analog.2005.vcproj", "{37C94798-6E33-4B4F-8EE0-C72A7DC91157}"
- ProjectSection(ProjectDependencies) = postProject
- {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ozmod_analog_em", "src\ozmod\ozmod_analog_em\ozmod_analog_em.2005.vcproj", "{C539D7C8-26A8-4A94-B938-77672165C130}"
- ProjectSection(ProjectDependencies) = postProject
- {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ozmod_isdn", "src\ozmod\ozmod_isdn\ozmod_isdn.2005.vcproj", "{729344A5-D5E9-434D-8EE8-AF8C6C795D15}"
- ProjectSection(ProjectDependencies) = postProject
- {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ozmod_wanpipe", "src\ozmod\ozmod_wanpipe\ozmod_wanpipe.2005.vcproj", "{1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ozmod_pika", "src\ozmod\ozmod_pika\ozmod_pika.2005.vcproj", "{E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Win32 = Debug|Win32
- Release|Win32 = Release|Win32
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|Win32.ActiveCfg = Debug|Win32
- {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|Win32.Build.0 = Debug|Win32
- {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|Win32.ActiveCfg = Release|Win32
- {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|Win32.Build.0 = Release|Win32
- {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|Win32.ActiveCfg = Debug|Win32
- {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|Win32.Build.0 = Debug|Win32
- {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|Win32.ActiveCfg = Release|Win32
- {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|Win32.Build.0 = Release|Win32
- {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|Win32.ActiveCfg = Debug|Win32
- {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|Win32.Build.0 = Debug|Win32
- {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|Win32.ActiveCfg = Release|Win32
- {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|Win32.Build.0 = Release|Win32
- {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.ActiveCfg = Debug|Win32
- {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.Build.0 = Debug|Win32
- {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|Win32.ActiveCfg = Release|Win32
- {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|Win32.Build.0 = Release|Win32
- {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|Win32.ActiveCfg = Debug|Win32
- {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|Win32.Build.0 = Debug|Win32
- {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|Win32.ActiveCfg = Release|Win32
- {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|Win32.Build.0 = Release|Win32
- {C539D7C8-26A8-4A94-B938-77672165C130}.Debug|Win32.ActiveCfg = Debug|Win32
- {C539D7C8-26A8-4A94-B938-77672165C130}.Debug|Win32.Build.0 = Debug|Win32
- {C539D7C8-26A8-4A94-B938-77672165C130}.Release|Win32.ActiveCfg = Release|Win32
- {C539D7C8-26A8-4A94-B938-77672165C130}.Release|Win32.Build.0 = Release|Win32
- {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|Win32.ActiveCfg = Debug|Win32
- {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|Win32.Build.0 = Debug|Win32
- {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|Win32.ActiveCfg = Release|Win32
- {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|Win32.Build.0 = Release|Win32
- {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|Win32.ActiveCfg = Debug|Win32
- {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|Win32.ActiveCfg = Release|Win32
- {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Debug|Win32.ActiveCfg = Debug|Win32
- {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Release|Win32.ActiveCfg = Release|Win32
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
diff --git a/libs/freetdm/src/ftdm_call_utils.c b/libs/freetdm/src/ftdm_call_utils.c
index d91b3bc9e2..69f2fb4fff 100644
--- a/libs/freetdm/src/ftdm_call_utils.c
+++ b/libs/freetdm/src/ftdm_call_utils.c
@@ -36,80 +36,101 @@
#include
-FT_DECLARE(ftdm_status_t) ftdm_span_set_npi(const char *npi_string, uint8_t *target)
+FT_DECLARE(ftdm_status_t) ftdm_set_npi(const char *string, uint8_t *target)
{
- if (!strcasecmp(npi_string, "isdn") || !strcasecmp(npi_string, "e164")) {
- *target = FTDM_NPI_ISDN;
- } else if (!strcasecmp(npi_string, "data")) {
- *target = FTDM_NPI_DATA;
- } else if (!strcasecmp(npi_string, "telex")) {
- *target = FTDM_NPI_TELEX;
- } else if (!strcasecmp(npi_string, "national")) {
- *target = FTDM_NPI_NATIONAL;
- } else if (!strcasecmp(npi_string, "private")) {
- *target = FTDM_NPI_PRIVATE;
- } else if (!strcasecmp(npi_string, "reserved")) {
- *target = FTDM_NPI_RESERVED;
- } else if (!strcasecmp(npi_string, "unknown")) {
- *target = FTDM_NPI_UNKNOWN;
- } else {
- ftdm_log(FTDM_LOG_WARNING, "Invalid NPI value (%s)\n", npi_string);
- *target = FTDM_NPI_UNKNOWN;
- return FTDM_FAIL;
+ uint8_t val;
+ ftdm_status_t status = FTDM_SUCCESS;
+
+ val = ftdm_str2ftdm_npi(string);
+ if (val == FTDM_NPI_INVALID) {
+ ftdm_log(FTDM_LOG_WARNING, "Invalid NPI string (%s)\n", string);
+ status = FTDM_FAIL;
+ val = FTDM_NPI_UNKNOWN;
}
- return FTDM_SUCCESS;
+ *target = val;
+ return status;
}
-FT_DECLARE(ftdm_status_t) ftdm_span_set_ton(const char *ton_string, uint8_t *target)
+FT_DECLARE(ftdm_status_t) ftdm_set_ton(const char *string, uint8_t *target)
{
- if (!strcasecmp(ton_string, "national")) {
- *target = FTDM_TON_NATIONAL;
- } else if (!strcasecmp(ton_string, "international")) {
- *target = FTDM_TON_INTERNATIONAL;
- } else if (!strcasecmp(ton_string, "local")) {
- *target = FTDM_TON_SUBSCRIBER_NUMBER;
- } else if (!strcasecmp(ton_string, "unknown")) {
- *target = FTDM_TON_UNKNOWN;
- } else {
- ftdm_log(FTDM_LOG_WARNING, "Invalid TON value (%s)\n", ton_string);
- *target = FTDM_TON_UNKNOWN;
- return FTDM_FAIL;
+ uint8_t val;
+ ftdm_status_t status = FTDM_SUCCESS;
+
+ val = ftdm_str2ftdm_ton(string);
+ if (val == FTDM_TON_INVALID) {
+ ftdm_log(FTDM_LOG_WARNING, "Invalid TON string (%s)\n", string);
+ status = FTDM_FAIL;
+ val = FTDM_TON_UNKNOWN;
}
- return FTDM_SUCCESS;
+ *target = val;
+ return status;
}
-FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_capability(const char *bc_string, ftdm_bearer_cap_t *target)
+FT_DECLARE(ftdm_status_t) ftdm_set_bearer_capability(const char *string, uint8_t *target)
{
- if (!strcasecmp(bc_string, "speech")) {
- *target = FTDM_BEARER_CAP_SPEECH;
- } else if (!strcasecmp(bc_string, "unrestricted-digital")) {
- *target = FTDM_BEARER_CAP_64K_UNRESTRICTED;
- } else if (!strcasecmp(bc_string, "3.1Khz")) {
- *target = FTDM_BEARER_CAP_3_1KHZ_AUDIO;
- } else {
- ftdm_log(FTDM_LOG_WARNING, "Unsupported Bearer Capability value (%s)\n", bc_string);
- return FTDM_FAIL;
+ uint8_t val;
+ ftdm_status_t status = FTDM_SUCCESS;
+
+ val = ftdm_str2ftdm_bearer_cap(string);
+ if (val == FTDM_NPI_INVALID) {
+ ftdm_log(FTDM_LOG_WARNING, "Invalid Bearer-Capability string (%s)\n", string);
+ status = FTDM_FAIL;
+ val = FTDM_BEARER_CAP_SPEECH;
}
- return FTDM_SUCCESS;
+
+ *target = val;
+ return status;
}
-FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_layer1(const char *bc_string, ftdm_user_layer1_prot_t *target)
+FT_DECLARE(ftdm_status_t) ftdm_set_bearer_layer1(const char *string, uint8_t *target)
{
- if (!strcasecmp(bc_string, "v110")) {
- *target = FTDM_USER_LAYER1_PROT_V110;
- } else if (!strcasecmp(bc_string, "ulaw")) {
- *target = FTDM_USER_LAYER1_PROT_ULAW;
- } else if (!strcasecmp(bc_string, "alaw")) {
- *target =FTDM_USER_LAYER1_PROT_ALAW ;
- } else {
- ftdm_log(FTDM_LOG_WARNING, "Unsupported Bearer Layer1 Prot value (%s)\n", bc_string);
- return FTDM_FAIL;
+ uint8_t val;
+ ftdm_status_t status = FTDM_SUCCESS;
+
+ val = ftdm_str2ftdm_usr_layer1_prot(string);
+ if (val == FTDM_USER_LAYER1_PROT_INVALID) {
+ ftdm_log(FTDM_LOG_WARNING, "Invalid Bearer Layer 1 Protocol string (%s)\n", string);
+ status = FTDM_FAIL;
+ val = FTDM_USER_LAYER1_PROT_ULAW;
}
- return FTDM_SUCCESS;
+
+ *target = val;
+ return status;
}
+FT_DECLARE(ftdm_status_t) ftdm_set_screening_ind(const char *string, uint8_t *target)
+{
+ uint8_t val;
+ ftdm_status_t status = FTDM_SUCCESS;
-FT_DECLARE(ftdm_status_t) ftdm_is_number(char *number)
+ val = ftdm_str2ftdm_screening(string);
+ if (val == FTDM_SCREENING_INVALID) {
+ ftdm_log(FTDM_LOG_WARNING, "Invalid screening indicator string (%s)\n", string);
+ status = FTDM_FAIL;
+ val = FTDM_SCREENING_NOT_SCREENED;
+ }
+
+ *target = val;
+ return status;
+}
+
+FT_DECLARE(ftdm_status_t) ftdm_set_presentation_ind(const char *string, uint8_t *target)
+{
+ uint8_t val;
+ ftdm_status_t status = FTDM_SUCCESS;
+
+ val = ftdm_str2ftdm_presentation(string);
+ if (val == FTDM_PRES_INVALID) {
+ ftdm_log(FTDM_LOG_WARNING, "Invalid presentation string (%s)\n", string);
+ status = FTDM_FAIL;
+ val = FTDM_PRES_ALLOWED;
+ }
+
+ *target = val;
+ return status;
+}
+
+FT_DECLARE(ftdm_status_t) ftdm_is_number(const char *number)
{
if (!number) {
return FTDM_FAIL;
diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c
index 0aeaeedce4..eaa25e3da5 100644
--- a/libs/freetdm/src/ftdm_io.c
+++ b/libs/freetdm/src/ftdm_io.c
@@ -38,8 +38,6 @@
*/
#define _GNU_SOURCE
-#ifndef WIN32
-#endif
#include "private/ftdm_core.h"
#include
#ifdef WIN32
@@ -50,12 +48,21 @@
#endif
#include "ftdm_cpu_monitor.h"
+#ifndef localtime_r
+struct tm *localtime_r(const time_t *clock, struct tm *result);
+#endif
+
#define FORCE_HANGUP_TIMER 3000
#define SPAN_PENDING_CHANS_QUEUE_SIZE 1000
#define SPAN_PENDING_SIGNALS_QUEUE_SIZE 1000
#define FTDM_READ_TRACE_INDEX 0
#define FTDM_WRITE_TRACE_INDEX 1
+ftdm_time_t time_last_throttle_log = 0;
+ftdm_time_t time_current_throttle_log = 0;
+
+static ftdm_iterator_t *get_iterator(ftdm_iterator_type_t type, ftdm_iterator_t *iter);
+
static int time_is_init = 0;
static void time_init(void)
@@ -85,6 +92,123 @@ FT_DECLARE(ftdm_time_t) ftdm_current_time_in_ms(void)
#endif
}
+static void write_chan_io_dump(ftdm_io_dump_t *dump, char *dataptr, int dlen)
+{
+ int windex = dump->windex;
+ int avail = (int)dump->size - windex;
+
+ if (!dump->buffer) {
+ return;
+ }
+
+ if (dlen > avail) {
+ int diff = dlen - avail;
+
+ ftdm_assert(diff < (int)dump->size, "Very small buffer or very big IO chunk!\n");
+
+ /* write only what we can and the rest at the beginning of the buffer */
+ memcpy(&dump->buffer[windex], dataptr, avail);
+ memcpy(&dump->buffer[0], &dataptr[avail], diff);
+ windex = diff;
+
+ /*ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "wrapping around dump buffer %p up to index %d\n\n", dump, windex);*/
+ dump->wrapped = 1;
+ } else {
+ memcpy(&dump->buffer[windex], dataptr, dlen);
+ windex += dlen;
+ }
+
+ if (windex == (int)dump->size) {
+ /*ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "wrapping around dump buffer %p\n", dump);*/
+ windex = 0;
+ dump->wrapped = 1;
+ }
+
+ dump->windex = windex;
+}
+
+static void dump_chan_io_to_file(ftdm_channel_t *fchan, ftdm_io_dump_t *dump, FILE *file)
+{
+ /* write the saved audio buffer */
+ ftdm_size_t rc = 0;
+ ftdm_size_t towrite = 0;
+
+ if (!dump->buffer) {
+ return;
+ }
+
+ towrite = dump->size - dump->windex;
+
+ if (dump->wrapped) {
+ rc = fwrite(&dump->buffer[dump->windex], 1, towrite, file);
+ if (rc != towrite) {
+ ftdm_log_chan(fchan, FTDM_LOG_ERROR, "only wrote %d out of %d bytes in io dump buffer\n",
+ rc, towrite, strerror(errno));
+ }
+ }
+ if (dump->windex) {
+ towrite = dump->windex;
+ rc = fwrite(&dump->buffer[0], 1, towrite, file);
+ if (rc != towrite) {
+ ftdm_log_chan(fchan, FTDM_LOG_ERROR, "only wrote %d out of %d bytes in io dump buffer: %s\n",
+ rc, towrite, strerror(errno));
+ }
+ }
+ dump->windex = 0;
+ dump->wrapped = 0;
+}
+
+static void stop_chan_io_dump(ftdm_io_dump_t *dump)
+{
+ if (!dump->buffer) {
+ return;
+ }
+ ftdm_safe_free(dump->buffer);
+ memset(dump, 0, sizeof(dump));
+}
+
+static ftdm_status_t start_chan_io_dump(ftdm_channel_t *chan, ftdm_io_dump_t *dump, ftdm_size_t size)
+{
+ if (dump->buffer) {
+ ftdm_log_chan_msg(chan, FTDM_LOG_ERROR, "IO dump is already started\n");
+ return FTDM_FAIL;
+ }
+ memset(dump, 0, sizeof(*dump));
+ dump->buffer = ftdm_malloc(size);
+ if (!dump->buffer) {
+ return FTDM_FAIL;
+ }
+ dump->size = size;
+ return FTDM_SUCCESS;
+}
+
+
+static void close_dtmf_debug_file(ftdm_channel_t *ftdmchan)
+{
+ if (ftdmchan->dtmfdbg.file) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "closing debug dtmf file\n");
+ fclose(ftdmchan->dtmfdbg.file);
+ ftdmchan->dtmfdbg.file = NULL;
+ }
+}
+
+static ftdm_status_t disable_dtmf_debug(ftdm_channel_t *ftdmchan)
+{
+ if (!ftdmchan->dtmfdbg.enabled) {
+ return FTDM_SUCCESS;
+ }
+
+ if (!ftdmchan->rxdump.buffer) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "DTMF debug enabled but no rx dump?\n");
+ return FTDM_FAIL;
+ }
+
+ close_dtmf_debug_file(ftdmchan);
+ stop_chan_io_dump(&ftdmchan->rxdump);
+ ftdmchan->dtmfdbg.enabled = 0;
+ return FTDM_SUCCESS;
+}
+
typedef struct {
uint8_t enabled;
uint8_t running;
@@ -147,6 +271,24 @@ FTDM_STR2ENUM(ftdm_str2ftdm_chan_type, ftdm_chan_type2str, ftdm_chan_type_t, CHA
FTDM_ENUM_NAMES(SIGNALING_STATUS_NAMES, SIGSTATUS_STRINGS)
FTDM_STR2ENUM(ftdm_str2ftdm_signaling_status, ftdm_signaling_status2str, ftdm_signaling_status_t, SIGNALING_STATUS_NAMES, FTDM_SIG_STATE_INVALID)
+FTDM_ENUM_NAMES(TON_NAMES, TON_STRINGS)
+FTDM_STR2ENUM(ftdm_str2ftdm_ton, ftdm_ton2str, ftdm_ton_t, TON_NAMES, FTDM_TON_INVALID)
+
+FTDM_ENUM_NAMES(NPI_NAMES, NPI_STRINGS)
+FTDM_STR2ENUM(ftdm_str2ftdm_npi, ftdm_npi2str, ftdm_npi_t, NPI_NAMES, FTDM_NPI_INVALID)
+
+FTDM_ENUM_NAMES(PRESENTATION_NAMES, PRESENTATION_STRINGS)
+FTDM_STR2ENUM(ftdm_str2ftdm_presentation, ftdm_presentation2str, ftdm_presentation_t, PRESENTATION_NAMES, FTDM_PRES_INVALID)
+
+FTDM_ENUM_NAMES(SCREENING_NAMES, SCREENING_STRINGS)
+FTDM_STR2ENUM(ftdm_str2ftdm_screening, ftdm_screening2str, ftdm_screening_t, SCREENING_NAMES, FTDM_SCREENING_INVALID)
+
+FTDM_ENUM_NAMES(BEARER_CAP_NAMES, BEARER_CAP_STRINGS)
+FTDM_STR2ENUM(ftdm_str2ftdm_bearer_cap, ftdm_bearer_cap2str, ftdm_bearer_cap_t, BEARER_CAP_NAMES, FTDM_BEARER_CAP_INVALID)
+
+FTDM_ENUM_NAMES(USER_LAYER1_PROT_NAMES, USER_LAYER1_PROT_STRINGS)
+FTDM_STR2ENUM(ftdm_str2ftdm_usr_layer1_prot, ftdm_user_layer1_prot2str, ftdm_user_layer1_prot_t, USER_LAYER1_PROT_NAMES, FTDM_USER_LAYER1_PROT_INVALID)
+
static ftdm_status_t ftdm_group_add_channels(ftdm_span_t* span, int currindex, const char* name);
static const char *cut_path(const char *in)
@@ -217,7 +359,7 @@ static __inline__ void *ftdm_std_malloc(void *pool, ftdm_size_t size)
{
void *ptr = malloc(size);
pool = NULL; /* fix warning */
- ftdm_assert_return(ptr != NULL, NULL, "Out of memory");
+ ftdm_assert_return(ptr != NULL, NULL, "Out of memory\n");
return ptr;
}
@@ -225,7 +367,7 @@ static __inline__ void *ftdm_std_calloc(void *pool, ftdm_size_t elements, ftdm_s
{
void *ptr = calloc(elements, size);
pool = NULL;
- ftdm_assert_return(ptr != NULL, NULL, "Out of memory");
+ ftdm_assert_return(ptr != NULL, NULL, "Out of memory\n");
return ptr;
}
@@ -233,7 +375,7 @@ static __inline__ void *ftdm_std_realloc(void *pool, void *buff, ftdm_size_t siz
{
buff = realloc(buff, size);
pool = NULL;
- ftdm_assert_return(buff != NULL, NULL, "Out of memory");
+ ftdm_assert_return(buff != NULL, NULL, "Out of memory\n");
return buff;
}
@@ -295,43 +437,43 @@ static ftdm_status_t ftdm_set_caller_data(ftdm_span_t *span, ftdm_caller_data_t
return FTDM_FAIL;
}
- if (caller_data->dnis.plan == FTDM_NPI_INVALID) {
+ if (caller_data->dnis.plan >= FTDM_NPI_INVALID) {
caller_data->dnis.plan = span->default_caller_data.dnis.plan;
}
- if (caller_data->dnis.type == FTDM_TON_INVALID) {
+ if (caller_data->dnis.type >= FTDM_TON_INVALID) {
caller_data->dnis.type = span->default_caller_data.dnis.type;
}
- if (caller_data->cid_num.plan == FTDM_NPI_INVALID) {
+ if (caller_data->cid_num.plan >= FTDM_NPI_INVALID) {
caller_data->cid_num.plan = span->default_caller_data.cid_num.plan;
}
- if (caller_data->cid_num.type == FTDM_TON_INVALID) {
+ if (caller_data->cid_num.type >= FTDM_TON_INVALID) {
caller_data->cid_num.type = span->default_caller_data.cid_num.type;
}
- if (caller_data->ani.plan == FTDM_NPI_INVALID) {
+ if (caller_data->ani.plan >= FTDM_NPI_INVALID) {
caller_data->ani.plan = span->default_caller_data.ani.plan;
}
- if (caller_data->ani.type == FTDM_TON_INVALID) {
+ if (caller_data->ani.type >= FTDM_TON_INVALID) {
caller_data->ani.type = span->default_caller_data.ani.type;
}
- if (caller_data->rdnis.plan == FTDM_NPI_INVALID) {
+ if (caller_data->rdnis.plan >= FTDM_NPI_INVALID) {
caller_data->rdnis.plan = span->default_caller_data.rdnis.plan;
}
- if (caller_data->rdnis.type == FTDM_NPI_INVALID) {
+ if (caller_data->rdnis.type >= FTDM_NPI_INVALID) {
caller_data->rdnis.type = span->default_caller_data.rdnis.type;
}
- if (caller_data->bearer_capability == FTDM_INVALID_INT_PARM) {
+ if (caller_data->bearer_capability >= FTDM_INVALID_INT_PARM) {
caller_data->bearer_capability = span->default_caller_data.bearer_capability;
}
- if (caller_data->bearer_layer1 == FTDM_INVALID_INT_PARM) {
+ if (caller_data->bearer_layer1 >= FTDM_INVALID_INT_PARM) {
caller_data->bearer_layer1 = span->default_caller_data.bearer_layer1;
}
@@ -429,10 +571,6 @@ static ftdm_status_t ftdm_channel_destroy(ftdm_channel_t *ftdmchan)
ftdm_sleep(500);
}
-#ifdef FTDM_DEBUG_DTMF
- ftdm_mutex_destroy(&ftdmchan->dtmfdbg.mutex);
-#endif
-
ftdm_mutex_lock(ftdmchan->pre_buffer_mutex);
ftdm_buffer_destroy(&ftdmchan->pre_buffer);
ftdm_mutex_unlock(ftdmchan->pre_buffer_mutex);
@@ -851,9 +989,6 @@ FT_DECLARE(ftdm_status_t) ftdm_span_add_channel(ftdm_span_t *span, ftdm_socket_t
ftdm_mutex_create(&new_chan->mutex);
ftdm_mutex_create(&new_chan->pre_buffer_mutex);
-#ifdef FTDM_DEBUG_DTMF
- ftdm_mutex_create(&new_chan->dtmfdbg.mutex);
-#endif
ftdm_buffer_create(&new_chan->digit_buffer, 128, 128, 0);
ftdm_buffer_create(&new_chan->gen_dtmf_buffer, 128, 128, 0);
@@ -985,6 +1120,51 @@ FT_DECLARE(ftdm_status_t) ftdm_span_next_event(ftdm_span_t *span, ftdm_event_t *
return status;
}
+FT_DECLARE(ftdm_status_t) ftdm_channel_read_event(ftdm_channel_t *ftdmchan, ftdm_event_t **event)
+{
+ ftdm_status_t status = FTDM_FAIL;
+ ftdm_sigmsg_t sigmsg;
+ ftdm_span_t *span = ftdmchan->span;
+ ftdm_assert_return(span->fio != NULL, FTDM_FAIL, "No I/O module attached to this span!\n");
+
+ if (!span->fio->channel_next_event) {
+ ftdm_log(FTDM_LOG_ERROR, "channel_next_event method not implemented in module %s!", span->fio->name);
+ return FTDM_NOTIMPL;
+ }
+
+ status = span->fio->channel_next_event(ftdmchan, event);
+ if (status != FTDM_SUCCESS) {
+ return status;
+ }
+
+ /* before returning the event to the user we do some core operations with certain OOB events */
+ memset(&sigmsg, 0, sizeof(sigmsg));
+ sigmsg.span_id = span->span_id;
+ sigmsg.chan_id = (*event)->channel->chan_id;
+ sigmsg.channel = (*event)->channel;
+ switch ((*event)->enum_id) {
+ case FTDM_OOB_ALARM_CLEAR:
+ {
+ sigmsg.event_id = FTDM_SIGEVENT_ALARM_CLEAR;
+ ftdm_clear_flag_locked((*event)->channel, FTDM_CHANNEL_IN_ALARM);
+ ftdm_span_send_signal(span, &sigmsg);
+ }
+ break;
+ case FTDM_OOB_ALARM_TRAP:
+ {
+ sigmsg.event_id = FTDM_SIGEVENT_ALARM_TRAP;
+ ftdm_set_flag_locked((*event)->channel, FTDM_CHANNEL_IN_ALARM);
+ ftdm_span_send_signal(span, &sigmsg);
+ }
+ break;
+ default:
+ /* NOOP */
+ break;
+ }
+
+ return status;
+}
+
static ftdm_status_t ftdmchan_fsk_write_sample(int16_t *buf, ftdm_size_t buflen, void *user_data)
{
ftdm_channel_t *ftdmchan = (ftdm_channel_t *) user_data;
@@ -1715,7 +1895,9 @@ static ftdm_status_t ftdm_channel_reset(ftdm_channel_t *ftdmchan)
if (!ftdmchan->dtmf_off) {
ftdmchan->dtmf_off = FTDM_DEFAULT_DTMF_OFF;
}
-
+
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
+
memset(ftdmchan->dtmf_hangup_buf, '\0', ftdmchan->span->dtmf_hangup_len);
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE)) {
@@ -1745,16 +1927,26 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan)
ftdm_mutex_lock(ftdmchan->mutex);
- if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) {
- snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is suspended\n");
- ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is suspended\n");
- goto done;
- }
-
- if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM) && !ftdm_test_flag(ftdmchan->span, FTDM_SPAN_PWR_SAVING)) {
- snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is alarmed\n");
- ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is alarmed\n");
- goto done;
+ if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) {
+ if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) {
+ snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is suspended\n");
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is suspended\n");
+ goto done;
+ }
+
+ if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM) && !ftdm_test_flag(ftdmchan->span, FTDM_SPAN_PWR_SAVING)) {
+ snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is alarmed\n");
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is alarmed\n");
+ goto done;
+ }
+
+ if (globals.cpu_monitor.alarm &&
+ globals.cpu_monitor.alarm_action_flags & FTDM_CPU_ALARM_ACTION_REJECT) {
+ snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "CPU usage alarm is on - refusing to open channel\n");
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "CPU usage alarm is on - refusing to open channel\n");
+ ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_SWITCH_CONGESTION;
+ goto done;
+ }
}
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_READY)) {
@@ -1763,15 +1955,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan)
goto done;
}
- if (globals.cpu_monitor.alarm &&
- globals.cpu_monitor.alarm_action_flags & FTDM_CPU_ALARM_ACTION_REJECT) {
- snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "CPU usage alarm is on - refusing to open channel\n");
- ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "CPU usage alarm is on - refusing to open channel\n");
- ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_SWITCH_CONGESTION;
- goto done;
- }
-
-
status = ftdmchan->fio->open(ftdmchan);
if (status == FTDM_SUCCESS) {
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_OPEN | FTDM_CHANNEL_INUSE);
@@ -2030,27 +2213,31 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char
goto done;
}
+ if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_SKIP_STATES)) {
+ /* We will fail RFC's if we not skip states, but some modules apart from ftmod_sangoma_isdn
+ * expect the call to always to go PROGRESS and PROGRESS MEDIA state before going to UP, so
+ * use FTDM_SPAN_USE_SKIP_STATESfor now while we update the sig modules */
- if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) {
- ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1);
+ if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) {
+ ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1);
+ }
+
+ /* set state unlocks the channel so we need to re-confirm that the channel hasn't gone to hell */
+ if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call has moved to TERMINATING while we're moving to PROGRESS\n");
+ goto done;
+ }
+
+ if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS_MEDIA) {
+ ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1);
+ }
+
+ /* set state unlocks the channel so we need to re-confirm that the channel hasn't gone to hell */
+ if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call has moved to TERMINATING while we're moving to UP\n");
+ goto done;
+ }
}
-
- /* set state unlocks the channel so we need to re-confirm that the channel hasn't gone to hell */
- if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
- ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call has moved to TERMINATING while we're moving to PROGRESS\n");
- goto done;
- }
-
- if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS_MEDIA) {
- ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1);
- }
-
- /* set state unlocks the channel so we need to re-confirm that the channel hasn't gone to hell */
- if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
- ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call has moved to TERMINATING while we're moving to UP\n");
- goto done;
- }
-
ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_UP, 1);
done:
@@ -2078,7 +2265,7 @@ static ftdm_status_t call_hangup(ftdm_channel_t *chan, const char *file, const c
} else {
/* the signaling stack did not touch the state,
* core is responsible from clearing flags and stuff */
- ftdm_channel_done(chan);
+ ftdm_channel_close(&chan);
}
return FTDM_SUCCESS;
}
@@ -2199,14 +2386,19 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch
switch (indication) {
/* FIXME: ring and busy cannot be used with all signaling stacks
* (particularly isdn stacks I think, we should emulate or just move to hangup with busy cause) */
- case FTDM_CHANNEL_INDICATE_RING:
- ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_RING, 1);
+ case FTDM_CHANNEL_INDICATE_RINGING:
+ ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_RINGING, 1);
break;
-
case FTDM_CHANNEL_INDICATE_BUSY:
ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_BUSY, 1);
break;
-
+ case FTDM_CHANNEL_INDICATE_PROCEED:
+ if (ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_PROCEED_STATE)) {
+ if (ftdmchan->state == FTDM_CHANNEL_STATE_RING) {
+ ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROCEED, 1);
+ }
+ }
+ break;
case FTDM_CHANNEL_INDICATE_PROGRESS:
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS);
@@ -2214,7 +2406,6 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch
ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1);
}
break;
-
case FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA:
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS);
@@ -2233,7 +2424,6 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch
ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1);
}
break;
-
default:
ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "Do not know how to indicate %d\n", indication);
status = FTDM_FAIL;
@@ -2246,6 +2436,27 @@ done:
return FTDM_SUCCESS;
}
+FT_DECLARE(ftdm_status_t) _ftdm_channel_call_send_msg(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_sigmsg_t *sigmsg)
+{
+ ftdm_status_t status = FTDM_FAIL;
+ ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel");
+#ifdef __WINDOWS__
+ UNREFERENCED_PARAMETER(file);
+ UNREFERENCED_PARAMETER(func);
+ UNREFERENCED_PARAMETER(line);
+#endif
+
+ ftdm_channel_lock(ftdmchan);
+ if (ftdmchan->span->send_msg) {
+ status = ftdmchan->span->send_msg(ftdmchan, sigmsg);
+ } else {
+ status = FTDM_NOTIMPL;
+ ftdm_log(FTDM_LOG_ERROR, "send_msg method not implemented in this span!\n");
+ }
+ ftdm_channel_unlock(ftdmchan);
+ return status;
+}
+
FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan)
{
ftdm_status_t status = FTDM_FAIL;
@@ -2270,6 +2481,8 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char
UNREFERENCED_PARAMETER(line);
#endif
+ ftdm_wait_for_flag_cleared(ftdmchan, FTDM_CHANNEL_STATE_CHANGE, 100);
+
ftdm_channel_unlock(ftdmchan);
return status;
@@ -2326,23 +2539,6 @@ FT_DECLARE(ftdm_status_t) ftdm_span_get_sig_status(ftdm_span_t *span, ftdm_signa
}
}
-#ifdef FTDM_DEBUG_DTMF
-static void close_dtmf_debug(ftdm_channel_t *ftdmchan)
-{
- ftdm_mutex_lock(ftdmchan->dtmfdbg.mutex);
-
- if (ftdmchan->dtmfdbg.file) {
- ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "closing debug dtmf file\n");
- fclose(ftdmchan->dtmfdbg.file);
- ftdmchan->dtmfdbg.file = NULL;
- }
- ftdmchan->dtmfdbg.windex = 0;
- ftdmchan->dtmfdbg.wrapped = 0;
-
- ftdm_mutex_unlock(ftdmchan->dtmfdbg.mutex);
-}
-#endif
-
static ftdm_status_t ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan);
FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan)
{
@@ -2371,9 +2567,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan)
ftdm_buffer_destroy(&ftdmchan->pre_buffer);
ftdmchan->pre_buffer_size = 0;
ftdm_mutex_unlock(ftdmchan->pre_buffer_mutex);
-#ifdef FTDM_DEBUG_DTMF
- close_dtmf_debug(ftdmchan);
-#endif
ftdm_channel_clear_vars(ftdmchan);
if (ftdmchan->hangup_timer) {
ftdm_sched_cancel_timer(globals.timingsched, ftdmchan->hangup_timer);
@@ -2382,7 +2575,27 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan)
ftdmchan->init_state = FTDM_CHANNEL_STATE_DOWN;
ftdmchan->state = FTDM_CHANNEL_STATE_DOWN;
- ftdm_log(FTDM_LOG_DEBUG, "channel done %u:%u\n", ftdmchan->span_id, ftdmchan->chan_id);
+ ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_DEBUG_DTMF, NULL);
+ ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_INPUT_DUMP, NULL);
+ ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_OUTPUT_DUMP, NULL);
+
+ if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) {
+ ftdm_sigmsg_t sigmsg;
+ memset(&sigmsg, 0, sizeof(sigmsg));
+ sigmsg.span_id = ftdmchan->span_id;
+ sigmsg.chan_id = ftdmchan->chan_id;
+ sigmsg.channel = ftdmchan;
+ sigmsg.event_id = FTDM_SIGEVENT_RELEASED;
+ ftdm_span_send_signal(ftdmchan->span, &sigmsg);
+ }
+
+ if (ftdmchan->txdrops || ftdmchan->rxdrops) {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "channel dropped data: txdrops = %d, rxdrops = %d\n",
+ ftdmchan->txdrops, ftdmchan->rxdrops);
+ }
+
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "channel done\n");
+
ftdm_mutex_unlock(ftdmchan->mutex);
@@ -2392,7 +2605,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan)
FT_DECLARE(ftdm_status_t) ftdm_channel_use(ftdm_channel_t *ftdmchan)
{
- assert(ftdmchan != NULL);
+ ftdm_assert(ftdmchan != NULL, "Null channel\n");
ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_INUSE);
@@ -2466,8 +2679,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
{
ftdm_status_t status = FTDM_FAIL;
- assert(ftdmchan != NULL);
- assert(ftdmchan->fio != NULL);
+ ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "No channel\n");
+ ftdm_assert_return(ftdmchan->fio != NULL, FTDM_FAIL, "No IO attached to channel\n");
ftdm_mutex_lock(ftdmchan->mutex);
@@ -2494,7 +2707,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
break;
case FTDM_COMMAND_TRACE_INPUT:
{
- char *path = (char *) obj;
+ char *path = FTDM_COMMAND_OBJ_CHAR_P;
if (ftdmchan->fds[FTDM_READ_TRACE_INDEX] > 0) {
close(ftdmchan->fds[FTDM_READ_TRACE_INDEX]);
ftdmchan->fds[FTDM_READ_TRACE_INDEX] = -1;
@@ -2537,6 +2750,135 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
GOTO_STATUS(done, FTDM_SUCCESS);
}
break;
+
+ /*!< Enable DTMF debugging */
+ case FTDM_COMMAND_ENABLE_DEBUG_DTMF:
+ {
+ if (ftdmchan->dtmfdbg.enabled) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Cannot enable debug DTMF again\n");
+ GOTO_STATUS(done, FTDM_FAIL);
+ }
+ if (ftdmchan->rxdump.buffer) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Cannot debug DTMF if Rx dumping is already enabled\n");
+ GOTO_STATUS(done, FTDM_FAIL);
+ }
+ if (start_chan_io_dump(ftdmchan, &ftdmchan->rxdump, FTDM_IO_DUMP_DEFAULT_BUFF_SIZE) != FTDM_SUCCESS) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failed to enable rx dump for DTMF debugging\n");
+ GOTO_STATUS(done, FTDM_FAIL);
+ }
+ ftdmchan->dtmfdbg.enabled = 1;
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Enabled DTMF debugging\n");
+ GOTO_STATUS(done, FTDM_SUCCESS);
+ }
+ break;
+
+ /*!< Disable DTMF debugging (if not disabled explicitly, it is disabled automatically when calls hangup) */
+ case FTDM_COMMAND_DISABLE_DEBUG_DTMF:
+ {
+ if (!ftdmchan->dtmfdbg.enabled) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "DTMF debug is already disabled\n");
+ GOTO_STATUS(done, FTDM_SUCCESS);
+ }
+ if (disable_dtmf_debug(ftdmchan) != FTDM_SUCCESS) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failed to disable DTMF debug\n");
+ GOTO_STATUS(done, FTDM_FAIL);
+ }
+ GOTO_STATUS(done, FTDM_SUCCESS);
+ }
+ break;
+
+ /*!< Start dumping all input to a circular buffer. The size of the circular buffer can be specified, default used otherwise */
+ case FTDM_COMMAND_ENABLE_INPUT_DUMP:
+ {
+ ftdm_size_t size = obj ? FTDM_COMMAND_OBJ_SIZE : FTDM_IO_DUMP_DEFAULT_BUFF_SIZE;
+ if (ftdmchan->rxdump.buffer) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Input dump is already enabled\n");
+ GOTO_STATUS(done, FTDM_FAIL);
+ }
+ if (start_chan_io_dump(ftdmchan, &ftdmchan->rxdump, size) != FTDM_SUCCESS) {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to enable input dump of size %zd\n", size);
+ GOTO_STATUS(done, FTDM_FAIL);
+ }
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Enabled input dump with size %zd\n", size);
+ GOTO_STATUS(done, FTDM_SUCCESS);
+ }
+ break;
+
+ /*!< Stop dumping all input to a circular buffer. */
+ case FTDM_COMMAND_DISABLE_INPUT_DUMP:
+ {
+ if (!ftdmchan->rxdump.buffer) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No need to disable input dump\n");
+ GOTO_STATUS(done, FTDM_SUCCESS);
+ }
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Disabled input dump of size %zd\n", ftdmchan->rxdump.size);
+ stop_chan_io_dump(&ftdmchan->rxdump);
+ GOTO_STATUS(done, FTDM_SUCCESS);
+ }
+ break;
+
+ /*!< Start dumping all output to a circular buffer. The size of the circular buffer can be specified, default used otherwise */
+ case FTDM_COMMAND_ENABLE_OUTPUT_DUMP:
+ {
+ ftdm_size_t size = obj ? FTDM_COMMAND_OBJ_SIZE : FTDM_IO_DUMP_DEFAULT_BUFF_SIZE;
+ if (ftdmchan->txdump.buffer) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Output dump is already enabled\n");
+ GOTO_STATUS(done, FTDM_FAIL);
+ }
+ if (start_chan_io_dump(ftdmchan, &ftdmchan->txdump, size) != FTDM_SUCCESS) {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to enable output dump of size %d\n", size);
+ GOTO_STATUS(done, FTDM_FAIL);
+ }
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Enabled output dump with size %zd\n", size);
+ GOTO_STATUS(done, FTDM_SUCCESS);
+ }
+ break;
+
+ /*!< Stop dumping all output to a circular buffer. */
+ case FTDM_COMMAND_DISABLE_OUTPUT_DUMP:
+ {
+ if (!ftdmchan->txdump.buffer) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No need to disable output dump\n");
+ GOTO_STATUS(done, FTDM_SUCCESS);
+ }
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Disabled output dump of size %zd\n", ftdmchan->rxdump.size);
+ stop_chan_io_dump(&ftdmchan->txdump);
+ GOTO_STATUS(done, FTDM_SUCCESS);
+ }
+ break;
+
+ /*!< Dump the current input circular buffer to the specified FILE* structure */
+ case FTDM_COMMAND_DUMP_INPUT:
+ {
+ if (!obj) {
+ GOTO_STATUS(done, FTDM_FAIL);
+ }
+ if (!ftdmchan->rxdump.buffer) {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Not dumped input to file %p, input dump is not enabled\n", obj);
+ GOTO_STATUS(done, FTDM_FAIL);
+ }
+ dump_chan_io_to_file(ftdmchan, &ftdmchan->rxdump, obj);
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Dumped input of size %d to file %p\n", ftdmchan->rxdump.size, obj);
+ GOTO_STATUS(done, FTDM_SUCCESS);
+ }
+ break;
+
+ /*!< Dump the current output circular buffer to the specified FILE* structure */
+ case FTDM_COMMAND_DUMP_OUTPUT:
+ {
+ if (!obj) {
+ GOTO_STATUS(done, FTDM_FAIL);
+ }
+ if (!ftdmchan->txdump.buffer) {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Not dumped output to file %p, output dump is not enabled\n", obj);
+ GOTO_STATUS(done, FTDM_FAIL);
+ }
+ dump_chan_io_to_file(ftdmchan, &ftdmchan->txdump, obj);
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Dumped input of size %zd to file %p\n", ftdmchan->txdump.size, obj);
+ GOTO_STATUS(done, FTDM_SUCCESS);
+ }
+ break;
+
case FTDM_COMMAND_SET_INTERVAL:
{
if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_INTERVAL)) {
@@ -2808,21 +3150,17 @@ done:
FT_DECLARE(ftdm_status_t) ftdm_channel_wait(ftdm_channel_t *ftdmchan, ftdm_wait_flag_t *flags, int32_t to)
{
- assert(ftdmchan != NULL);
- assert(ftdmchan->fio != NULL);
+ ftdm_status_t status = FTDM_FAIL;
+ ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel\n");
+ ftdm_assert_return(ftdmchan->fio != NULL, FTDM_FAIL, "Null io interface\n");
+ ftdm_assert_return(ftdmchan->fio->wait != NULL, FTDM_NOTIMPL, "wait method not implemented\n");
- if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
- snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "channel not open");
- return FTDM_FAIL;
- }
-
- if (!ftdmchan->fio->wait) {
- snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "method not implemented");
- return FTDM_FAIL;
+ status = ftdmchan->fio->wait(ftdmchan, flags, to);
+ if (status == FTDM_TIMEOUT) {
+ /* make sure the flags are cleared on timeout */
+ *flags = 0;
}
-
- return ftdmchan->fio->wait(ftdmchan, flags, to);
-
+ return status;
}
/*******************************/
@@ -3009,55 +3347,45 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, cons
ftdm_size_t wr = 0;
const char *p;
- assert(ftdmchan != NULL);
+ ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "No channel\n");
- ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Queuing DTMF %s\n", dtmf);
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Queuing DTMF %s (debug = %d)\n", dtmf, ftdmchan->dtmfdbg.enabled);
+
+ if (!ftdmchan->dtmfdbg.enabled) {
+ goto skipdebug;
+ }
-#ifdef FTDM_DEBUG_DTMF
- ftdm_mutex_lock(ftdmchan->dtmfdbg.mutex);
if (!ftdmchan->dtmfdbg.file) {
struct tm currtime;
time_t currsec;
char dfile[512];
currsec = time(NULL);
+
+#ifdef WIN32
+ _tzset();
+ _localtime64_s(&currtime, &currsec);
+#else
localtime_r(&currsec, &currtime);
+#endif
snprintf(dfile, sizeof(dfile), "dtmf-s%dc%d-20%d-%d-%d-%d:%d:%d.%s",
ftdmchan->span_id, ftdmchan->chan_id,
currtime.tm_year-100, currtime.tm_mon+1, currtime.tm_mday,
currtime.tm_hour, currtime.tm_min, currtime.tm_sec, ftdmchan->native_codec == FTDM_CODEC_ULAW ? "ulaw" : ftdmchan->native_codec == FTDM_CODEC_ALAW ? "alaw" : "sln");
- ftdmchan->dtmfdbg.file = fopen(dfile, "w");
+ ftdmchan->dtmfdbg.file = fopen(dfile, "w");
if (!ftdmchan->dtmfdbg.file) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "failed to open debug dtmf file %s\n", dfile);
} else {
- /* write the saved audio buffer */
- int rc = 0;
- int towrite = sizeof(ftdmchan->dtmfdbg.buffer) - ftdmchan->dtmfdbg.windex;
-
- ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "created debug DTMF file %s\n", dfile);
ftdmchan->dtmfdbg.closetimeout = DTMF_DEBUG_TIMEOUT;
- if (ftdmchan->dtmfdbg.wrapped) {
- rc = fwrite(&ftdmchan->dtmfdbg.buffer[ftdmchan->dtmfdbg.windex], 1, towrite, ftdmchan->dtmfdbg.file);
- if (rc != towrite) {
- ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "only wrote %d out of %d bytes in DTMF debug buffer\n", rc, towrite);
- }
- }
- if (ftdmchan->dtmfdbg.windex) {
- towrite = ftdmchan->dtmfdbg.windex;
- rc = fwrite(&ftdmchan->dtmfdbg.buffer[0], 1, towrite, ftdmchan->dtmfdbg.file);
- if (rc != towrite) {
- ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "only wrote %d out of %d bytes in DTMF debug buffer\n", rc, towrite);
- }
- }
- ftdmchan->dtmfdbg.windex = 0;
- ftdmchan->dtmfdbg.wrapped = 0;
+ ftdm_channel_command(ftdmchan, FTDM_COMMAND_DUMP_INPUT, ftdmchan->dtmfdbg.file);
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Dumped initial DTMF output to %s\n", dfile);
}
} else {
- ftdmchan->dtmfdbg.closetimeout = DTMF_DEBUG_TIMEOUT;
+ ftdmchan->dtmfdbg.closetimeout = DTMF_DEBUG_TIMEOUT;
}
- ftdm_mutex_unlock(ftdmchan->dtmfdbg.mutex);
-#endif
+
+skipdebug:
if (ftdmchan->pre_buffer) {
ftdm_buffer_zero(ftdmchan->pre_buffer);
@@ -3102,22 +3430,32 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, cons
static FIO_WRITE_FUNCTION(ftdm_raw_write)
{
+ int dlen = (int) *datalen;
+ if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TX_DISABLED)) {
+ ftdmchan->txdrops++;
+ if (ftdmchan->txdrops <= 10) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "cannot write in channel with tx disabled\n");
+ }
+ if (ftdmchan->txdrops == 10) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Too many tx drops, not printing anymore\n");
+ }
+ return FTDM_FAIL;
+ }
if (ftdmchan->fds[FTDM_WRITE_TRACE_INDEX] > -1) {
- int dlen = (int) *datalen;
if ((write(ftdmchan->fds[FTDM_WRITE_TRACE_INDEX], data, dlen)) != dlen) {
ftdm_log(FTDM_LOG_WARNING, "Raw output trace failed to write all of the %zd bytes\n", dlen);
}
}
+ write_chan_io_dump(&ftdmchan->txdump, data, dlen);
return ftdmchan->fio->write(ftdmchan, data, datalen);
}
-
static FIO_READ_FUNCTION(ftdm_raw_read)
{
ftdm_status_t status = ftdmchan->fio->read(ftdmchan, data, datalen);
if (status == FTDM_SUCCESS && ftdmchan->fds[FTDM_READ_TRACE_INDEX] > -1) {
- int dlen = (int) *datalen;
- if (write(ftdmchan->fds[FTDM_READ_TRACE_INDEX], data, dlen) != dlen) {
+ ftdm_size_t dlen = *datalen;
+ if ((ftdm_size_t)write(ftdmchan->fds[FTDM_READ_TRACE_INDEX], data, dlen) != dlen) {
ftdm_log(FTDM_LOG_WARNING, "Raw input trace failed to write all of the %zd bytes\n", dlen);
}
}
@@ -3126,48 +3464,24 @@ static FIO_READ_FUNCTION(ftdm_raw_read)
ftdmchan->span->sig_read(ftdmchan, data, *datalen);
}
-#ifdef FTDM_DEBUG_DTMF
if (status == FTDM_SUCCESS) {
- int dlen = (int) *datalen;
- int rc = 0;
- ftdm_mutex_lock(ftdmchan->dtmfdbg.mutex);
- if (!ftdmchan->dtmfdbg.file) {
- /* no file yet, write to our circular buffer */
- int windex = ftdmchan->dtmfdbg.windex;
- int avail = sizeof(ftdmchan->dtmfdbg.buffer) - windex;
- char *dataptr = data;
+ ftdm_size_t dlen = *datalen;
+ ftdm_size_t rc = 0;
- if (dlen > avail) {
- int diff = dlen - avail;
- /* write only what we can and the rest at the beginning of the buffer */
- memcpy(&ftdmchan->dtmfdbg.buffer[windex], dataptr, avail);
- memcpy(&ftdmchan->dtmfdbg.buffer[0], &dataptr[avail], diff);
- windex = diff;
- /*ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "wrapping around dtmf read buffer up to index %d\n\n", windex);*/
- ftdmchan->dtmfdbg.wrapped = 1;
- } else {
- memcpy(&ftdmchan->dtmfdbg.buffer[windex], dataptr, dlen);
- windex += dlen;
- }
- if (windex == sizeof(ftdmchan->dtmfdbg.buffer)) {
- /*ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "wrapping around dtmf read buffer\n");*/
- windex = 0;
- ftdmchan->dtmfdbg.wrapped = 1;
- }
- ftdmchan->dtmfdbg.windex = windex;
- } else {
+ write_chan_io_dump(&ftdmchan->rxdump, data, dlen);
+
+ /* if dtmf debug is enabled and initialized, write there too */
+ if (ftdmchan->dtmfdbg.file) {
rc = fwrite(data, 1, dlen, ftdmchan->dtmfdbg.file);
if (rc != dlen) {
ftdm_log(FTDM_LOG_WARNING, "DTMF debugger wrote only %d out of %d bytes: %s\n", rc, datalen, strerror(errno));
}
ftdmchan->dtmfdbg.closetimeout--;
if (!ftdmchan->dtmfdbg.closetimeout) {
- close_dtmf_debug(ftdmchan);
+ close_dtmf_debug_file(ftdmchan);
}
}
- ftdm_mutex_unlock(ftdmchan->dtmfdbg.mutex);
}
-#endif
return status;
}
@@ -3299,6 +3613,18 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_read(ftdm_channel_t *ftdmchan, void *data
goto done;
}
+ if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED)) {
+ ftdmchan->rxdrops++;
+ if (ftdmchan->rxdrops <= 10) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "cannot read from channel with rx disabled\n");
+ }
+ if (ftdmchan->rxdrops == 10) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "too many rx drops, not logging anymore\n");
+ }
+ status = FTDM_FAIL;
+ goto done;
+ }
+
status = ftdm_raw_read(ftdmchan, data, datalen);
if (status != FTDM_SUCCESS) {
@@ -3498,7 +3824,7 @@ done:
FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t datasize, ftdm_size_t *datalen)
{
- ftdm_status_t status = FTDM_FAIL;
+ ftdm_status_t status = FTDM_SUCCESS;
fio_codec_t codec_func = NULL;
ftdm_size_t max = datasize;
unsigned int i = 0;
@@ -3506,22 +3832,28 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *dat
ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel on write!\n");
ftdm_assert_return(ftdmchan->fio != NULL, FTDM_FAIL, "null I/O on write!\n");
+ ftdm_channel_lock(ftdmchan);
+
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 */
- return FTDM_SUCCESS;
+ goto done;
}
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "cannot write in channel not open\n");
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "channel not open");
- return FTDM_FAIL;
+ status = FTDM_FAIL;
+ goto done;
}
if (!ftdmchan->fio->write) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "write method not implemented\n");
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "method not implemented");
- return FTDM_FAIL;
+ status = FTDM_FAIL;
+ goto done;
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE) && ftdmchan->effective_codec != ftdmchan->native_codec) {
@@ -3538,10 +3870,13 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *dat
if (codec_func) {
status = codec_func(data, max, datalen);
} else {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Do not know how to handle transcoding from %d to %d\n",
+ ftdmchan->effective_codec, ftdmchan->native_codec);
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "codec error!");
status = FTDM_FAIL;
+ goto done;
}
- }
+ }
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_USE_TX_GAIN)
&& (ftdmchan->native_codec == FTDM_CODEC_ALAW || ftdmchan->native_codec == FTDM_CODEC_ULAW)) {
@@ -3551,11 +3886,117 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *dat
}
}
+ if (ftdmchan->span->sig_write) {
+ status = ftdmchan->span->sig_write(ftdmchan, data, *datalen);
+ if (status == FTDM_BREAK) {
+ /* signaling module decided to drop user frame */
+ status = FTDM_SUCCESS;
+ goto done;
+ }
+ }
+
status = ftdm_raw_write(ftdmchan, data, datalen);
+done:
+ ftdm_channel_unlock(ftdmchan);
+
return status;
}
+FT_DECLARE(void) ftdm_call_clear_data(ftdm_caller_data_t *caller_data)
+{
+ ftdm_call_clear_vars(caller_data);
+ memset(&caller_data->raw_data, 0, sizeof(caller_data->raw_data));
+ caller_data->raw_data_len = 0;
+ return;
+}
+
+FT_DECLARE(ftdm_status_t) ftdm_call_clear_vars(ftdm_caller_data_t *caller_data)
+{
+ if (caller_data->variables) {
+ hashtable_destroy(caller_data->variables);
+ }
+ caller_data->variables = NULL;
+ return FTDM_SUCCESS;
+}
+
+FT_DECLARE(ftdm_status_t) ftdm_call_remove_var(ftdm_caller_data_t *caller_data, const char *var_name)
+{
+ if (caller_data->variables) {
+ hashtable_remove(caller_data->variables, (void *)var_name);
+ }
+
+ return FTDM_SUCCESS;
+}
+
+
+FT_DECLARE(ftdm_status_t) ftdm_call_add_var(ftdm_caller_data_t *caller_data, const char *var_name, const char *value)
+{
+ char *t_name = 0, *t_val = 0;
+
+ if (!var_name || !value) {
+ return FTDM_FAIL;
+ }
+
+ if (!caller_data->variables) {
+ /* initialize on first use */
+ caller_data->variables = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys);
+ ftdm_assert_return(caller_data->variables, FTDM_FAIL, "Failed to create hash table\n");
+ }
+
+ t_name = ftdm_strdup(var_name);
+ t_val = ftdm_strdup(value);
+ hashtable_insert(caller_data->variables, t_name, t_val, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_FLAG_FREE_VALUE);
+ return FTDM_SUCCESS;
+}
+
+FT_DECLARE(const char *) ftdm_call_get_var(ftdm_caller_data_t *caller_data, const char *var_name)
+{
+ const char *var = NULL;
+
+ if (!caller_data->variables || !var_name) {
+ return NULL;
+ }
+
+ var = (const char *)hashtable_search(((struct hashtable*)caller_data->variables), (void *)var_name);
+ return var;
+}
+
+FT_DECLARE(ftdm_iterator_t *) ftdm_call_get_var_iterator(const ftdm_caller_data_t *caller_data, ftdm_iterator_t *iter)
+{
+ ftdm_hash_iterator_t *hashiter = NULL;
+ hashiter = caller_data->variables == NULL ? NULL : hashtable_first(caller_data->variables);
+
+ if (hashiter == NULL) {
+ return NULL;
+ }
+
+ if (!(iter = get_iterator(FTDM_ITERATOR_VARS, iter))) {
+ return NULL;
+ }
+ iter->pvt.hashiter = hashiter;
+ return iter;
+}
+
+FT_DECLARE(ftdm_status_t) ftdm_call_get_current_var(ftdm_iterator_t *iter, const char **var_name, const char **var_val)
+{
+ const void *key = NULL;
+ void *val = NULL;
+
+ *var_name = NULL;
+ *var_val = NULL;
+
+ ftdm_assert_return(iter && (iter->type == FTDM_ITERATOR_VARS) && iter->pvt.hashiter, FTDM_FAIL, "Cannot get variable from invalid iterator!\n");
+
+ hashtable_this(iter->pvt.hashiter, &key, NULL, &val);
+
+ *var_name = key;
+ *var_val = val;
+
+ return FTDM_SUCCESS;
+}
+
+
static ftdm_status_t ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan)
{
ftdm_channel_lock(ftdmchan);
@@ -3602,6 +4043,7 @@ done:
return status;
}
+
FT_DECLARE(const char *) ftdm_channel_get_var(ftdm_channel_t *ftdmchan, const char *var_name)
{
const char *var = NULL;
@@ -3766,6 +4208,53 @@ static struct {
ftdm_io_interface_t *pika_interface;
} interfaces;
+static void print_channels_by_flag(ftdm_stream_handle_t *stream, int32_t flagval, int not, int *count)
+{
+ ftdm_hash_iterator_t *i = NULL;
+ ftdm_span_t *span;
+ ftdm_channel_t *fchan = NULL;
+ ftdm_iterator_t *citer = NULL;
+ ftdm_iterator_t *curr = NULL;
+ const void *key = NULL;
+ void *val = NULL;
+ uint32_t flag = (1 << flagval);
+
+ *count = 0;
+
+ ftdm_mutex_lock(globals.mutex);
+
+ for (i = hashtable_first(globals.span_hash); i; i = hashtable_next(i)) {
+ hashtable_this(i, &key, NULL, &val);
+ if (!key || !val) {
+ break;
+ }
+ span = val;
+ citer = ftdm_span_get_chan_iterator(span, NULL);
+ if (!citer) {
+ continue;
+ }
+ for (curr = citer ; curr; curr = ftdm_iterator_next(curr)) {
+ fchan = ftdm_iterator_current(curr);
+ if (not && !ftdm_test_flag(fchan, flag)) {
+ stream->write_function(stream, "[s%dc%d][%d:%d] has not flag %d\n",
+ fchan->span_id, fchan->chan_id,
+ fchan->physical_span_id, fchan->physical_chan_id,
+ flagval);
+ (*count)++;
+ } else if (!not && ftdm_test_flag(fchan, flag)) {
+ stream->write_function(stream, "[s%dc%d][%d:%d] has flag %d\n",
+ fchan->span_id, fchan->chan_id,
+ fchan->physical_span_id, fchan->physical_chan_id,
+ flagval);
+ (*count)++;
+ }
+ }
+ ftdm_iterator_free(citer);
+ }
+
+ ftdm_mutex_unlock(globals.mutex);
+}
+
static void print_channels_by_state(ftdm_stream_handle_t *stream, ftdm_channel_state_t state, int not, int *count)
{
ftdm_hash_iterator_t *i = NULL;
@@ -3818,6 +4307,8 @@ static char *handle_core_command(const char *cmd)
int not = 0;
char *argv[10] = { 0 };
char *state = NULL;
+ char *flag = NULL;
+ uint32_t flagval = 0;
ftdm_channel_state_t i = FTDM_CHANNEL_STATE_INVALID;
ftdm_stream_handle_t stream = { 0 };
@@ -3852,6 +4343,19 @@ static char *handle_core_command(const char *cmd)
}
print_channels_by_state(&stream, i, not, &count);
stream.write_function(&stream, "\nTotal channels %s %s: %d\n", not ? "not in state" : "in state", ftdm_channel_state2str(i), count);
+ } else if (!strcasecmp(argv[0], "flag")) {
+ if (argc < 2) {
+ stream.write_function(&stream, "core state command requires an argument\n");
+ goto done;
+ }
+ flag = argv[1];
+ if (argv[1][0] == '!') {
+ not = 1;
+ flag++;
+ }
+ flagval = atoi(flag);
+ print_channels_by_flag(&stream, flagval, not, &count);
+ stream.write_function(&stream, "\nTotal channels %s %d: %d\n", not ? "without flag" : "with flag", flagval, count);
} else {
stream.write_function(&stream, "invalid core command %s\n", argv[0]);
}
@@ -3963,6 +4467,7 @@ static ftdm_status_t ftdm_set_channels_alarms(ftdm_span_t *span, int currindex)
FT_DECLARE(ftdm_status_t) ftdm_configure_span_channels(ftdm_span_t *span, const char* str, ftdm_channel_config_t *chan_config, unsigned *configured)
{
int currindex;
+ unsigned chan_index = 0;
ftdm_assert_return(span != NULL, FTDM_EINVAL, "span is null\n");
ftdm_assert_return(chan_config != NULL, FTDM_EINVAL, "config is null\n");
@@ -3996,6 +4501,14 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span_channels(ftdm_span_t *span, const
return FTDM_FAIL;
}
+ if (chan_config->debugdtmf) {
+ for (chan_index = currindex+1; chan_index <= span->chan_count; chan_index++) {
+ if (!FTDM_IS_VOICE_CHANNEL(span->channels[chan_index])) {
+ continue;
+ }
+ span->channels[chan_index]->dtmfdbg.requested = 1;
+ }
+ }
return FTDM_SUCCESS;
}
@@ -4014,7 +4527,7 @@ static ftdm_status_t load_config(void)
ftdm_channel_config_t chan_config;
memset(&chan_config, 0, sizeof(chan_config));
- sprintf(chan_config.group_name,"default");
+ sprintf(chan_config.group_name, "__default");
if (!ftdm_config_open_file(&cfg, cfg_name)) {
return FTDM_FAIL;
@@ -4051,6 +4564,9 @@ static ftdm_status_t load_config(void)
if (ftdm_span_create(type, name, &span) == FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_DEBUG, "created span %d (%s) of type %s\n", span->span_id, span->name, type);
d = 0;
+ /* it is confusing that parameters from one span affect others, so let's clear them */
+ memset(&chan_config, 0, sizeof(chan_config));
+ sprintf(chan_config.group_name, "__default");
} else {
ftdm_log(FTDM_LOG_CRIT, "failure creating span of type %s\n", type);
span = NULL;
@@ -4174,6 +4690,9 @@ static ftdm_status_t load_config(void)
if (sscanf(val, "%f", &(chan_config.rxgain)) != 1) {
ftdm_log(FTDM_LOG_ERROR, "invalid rxgain: '%s'\n", val);
}
+ } else if (!strcasecmp(var, "debugdtmf")) {
+ chan_config.debugdtmf = ftdm_true(val);
+ ftdm_log(FTDM_LOG_DEBUG, "Setting debugdtmf to '%s'\n", chan_config.debugdtmf ? "yes" : "no");
} else if (!strcasecmp(var, "group")) {
len = strlen(val);
if (len >= FTDM_MAX_NAME_STR_SZ) {
@@ -4758,7 +5277,11 @@ FT_DECLARE(ftdm_status_t) ftdm_group_create(ftdm_group_t **group, const char *na
static ftdm_status_t ftdm_span_trigger_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)
{
- return span->signal_cb(sigmsg);
+ ftdm_status_t status = span->signal_cb(sigmsg);
+ if (sigmsg->channel) {
+ ftdm_call_clear_data(&(sigmsg->channel->caller_data));
+ }
+ return status;
}
static ftdm_status_t ftdm_span_queue_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)
@@ -4807,7 +5330,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
if (sigmsg->channel) {
ftdm_mutex_lock(sigmsg->channel->mutex);
}
-
+
/* some core things to do on special events */
switch (sigmsg->event_id) {
@@ -4825,6 +5348,9 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
case FTDM_SIGEVENT_START:
{
ftdm_set_echocancel_call_begin(sigmsg->channel);
+ if (sigmsg->channel->dtmfdbg.requested) {
+ ftdm_channel_command(sigmsg->channel, FTDM_COMMAND_ENABLE_DEBUG_DTMF, NULL);
+ }
/* when cleaning up the public API I added this because mod_freetdm.c on_fxs_signal was
* doing it during SIGEVENT_START, but now that flags are private they can't, wonder if
@@ -4859,6 +5385,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
}
done:
+
if (sigmsg->channel) {
ftdm_mutex_unlock(sigmsg->channel->mutex);
}
diff --git a/libs/freetdm/src/ftdm_threadmutex.c b/libs/freetdm/src/ftdm_threadmutex.c
index 1271d80f4a..b1884ec587 100644
--- a/libs/freetdm/src/ftdm_threadmutex.c
+++ b/libs/freetdm/src/ftdm_threadmutex.c
@@ -417,7 +417,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_destroy(ftdm_interrupt_t **ininterrupt)
FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interrupts[], ftdm_size_t size, int ms)
{
int numdevices = 0;
- unsigned i;
+ unsigned i = 0;
#if defined(__WINDOWS__)
DWORD res = 0;
@@ -496,6 +496,8 @@ pollagain:
}
}
#else
+ /* for MacOS compilation, unused vars */
+ numdevices = i;
#endif
return FTDM_SUCCESS;
}
diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftdm_analog.h b/libs/freetdm/src/ftmod/ftmod_analog/ftdm_analog.h
index 487829fd7b..2c79822b29 100644
--- a/libs/freetdm/src/ftmod/ftmod_analog/ftdm_analog.h
+++ b/libs/freetdm/src/ftmod/ftmod_analog/ftdm_analog.h
@@ -46,6 +46,7 @@ typedef enum {
struct ftdm_analog_data {
uint32_t flags;
uint32_t max_dialstr;
+ uint32_t wait_dialtone_timeout;
uint32_t digit_timeout;
char hotline[FTDM_MAX_HOTLINE_STR];
};
diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2008.vcproj b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2008.vcproj
index 448f03a545..09349fc05f 100644
--- a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2008.vcproj
+++ b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2008.vcproj
@@ -1,353 +1,353 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj
new file mode 100644
index 0000000000..301d821af6
--- /dev/null
+++ b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj
@@ -0,0 +1,198 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ ftmod_analog
+ {37C94798-6E33-4B4F-8EE0-C72A7DC91157}
+ ftmod_analog
+ Win32Proj
+
+
+
+ DynamicLibrary
+ Unicode
+ true
+
+
+ DynamicLibrary
+ Unicode
+
+
+ DynamicLibrary
+ Unicode
+ true
+
+
+ DynamicLibrary
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ false
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ false
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+
+
+
+ Disabled
+ ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level4
+ true
+ EditAndContinue
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Windows
+ MachineX86
+
+
+
+
+ MaxSpeed
+ true
+ ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ true
+
+
+ Level4
+ true
+ ProgramDatabase
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Windows
+ true
+ true
+ MachineX86
+
+
+
+
+ X64
+
+
+ Disabled
+ ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level4
+ false
+ ProgramDatabase
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Windows
+ MachineX64
+
+
+
+
+ X64
+
+
+ MaxSpeed
+ true
+ ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ true
+
+
+ Level4
+ false
+ ProgramDatabase
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Windows
+ true
+ true
+ MachineX64
+
+
+
+
+
+
+
+
+
+
+ {93b8812c-3ec4-4f78-8970-ffbfc99e167d}
+ false
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj.filters
new file mode 100644
index 0000000000..b6fed5927a
--- /dev/null
+++ b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj.filters
@@ -0,0 +1,23 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c
index dacda7e448..f07f48b0d6 100644
--- a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c
+++ b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c
@@ -49,13 +49,16 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj);
*/
static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(analog_fxo_outgoing_call)
{
+ ftdm_analog_data_t *analog_data = ftdmchan->span->signal_data;
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INTHREAD)) {
ftdm_channel_clear_needed_tones(ftdmchan);
ftdm_channel_clear_detected_tones(ftdmchan);
ftdm_channel_command(ftdmchan, FTDM_COMMAND_OFFHOOK, NULL);
ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_PROGRESS_DETECT, NULL);
- ftdmchan->needed_tones[FTDM_TONEMAP_DIAL] = 1;
+ if (analog_data->wait_dialtone_timeout) {
+ ftdmchan->needed_tones[FTDM_TONEMAP_DIAL] = 1;
+ }
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DIALING);
ftdm_thread_create_detached(ftdm_analog_channel_run, ftdmchan);
return FTDM_SUCCESS;
@@ -157,6 +160,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span)
const char *tonemap = "us";
const char *hotline = "";
uint32_t digit_timeout = 10;
+ uint32_t wait_dialtone_timeout = 30000;
uint32_t max_dialstr = MAX_DTMF;
const char *var, *val;
int *intval;
@@ -191,6 +195,15 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span)
break;
}
digit_timeout = *intval;
+ } else if (!strcasecmp(var, "wait_dialtone_timeout")) {
+ if (!(intval = va_arg(ap, int *))) {
+ break;
+ }
+ wait_dialtone_timeout = *intval;
+ if (wait_dialtone_timeout < 0) {
+ wait_dialtone_timeout = 0;
+ }
+ ftdm_log_chan(span->channels[i], FTDM_LOG_DEBUG, "Wait dial tone ms = %d\n", wait_dialtone_timeout);
} else if (!strcasecmp(var, "enable_callerid")) {
if (!(val = va_arg(ap, char *))) {
break;
@@ -221,7 +234,6 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span)
}
}
-
if (digit_timeout < 2000 || digit_timeout > 10000) {
digit_timeout = 2000;
}
@@ -241,6 +253,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span)
span->stop = ftdm_analog_stop;
analog_data->flags = flags;
analog_data->digit_timeout = digit_timeout;
+ analog_data->wait_dialtone_timeout = wait_dialtone_timeout;
analog_data->max_dialstr = max_dialstr;
span->signal_cb = sig_cb;
strncpy(analog_data->hotline, hotline, sizeof(analog_data->hotline));
@@ -325,6 +338,27 @@ static void send_caller_id(ftdm_channel_t *ftdmchan)
ftdm_channel_send_fsk_data(ftdmchan, &fsk_data, -14);
}
+static void analog_dial(ftdm_channel_t *ftdmchan, uint32_t *state_counter, uint32_t *dial_timeout)
+{
+ if (ftdm_strlen_zero(ftdmchan->caller_data.dnis.digits)) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No digits to send, moving to UP!\n");
+ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
+ } else {
+ if (ftdm_channel_command(ftdmchan, FTDM_COMMAND_SEND_DTMF, ftdmchan->caller_data.dnis.digits) != FTDM_SUCCESS) {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Send Digits Failed [%s]\n", ftdmchan->last_error);
+ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
+ } else {
+ *state_counter = 0;
+ ftdmchan->needed_tones[FTDM_TONEMAP_RING] = 1;
+ ftdmchan->needed_tones[FTDM_TONEMAP_BUSY] = 1;
+ ftdmchan->needed_tones[FTDM_TONEMAP_FAIL1] = 1;
+ ftdmchan->needed_tones[FTDM_TONEMAP_FAIL2] = 1;
+ ftdmchan->needed_tones[FTDM_TONEMAP_FAIL3] = 1;
+ *dial_timeout = ((ftdmchan->dtmf_on + ftdmchan->dtmf_off) * strlen(ftdmchan->caller_data.dnis.digits)) + 2000;
+ }
+ }
+}
+
/**
* \brief Main thread function for analog channel (outgoing call)
* \param me Current thread
@@ -342,7 +376,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
ftdm_size_t dtmf_offset = 0;
ftdm_analog_data_t *analog_data = ftdmchan->span->signal_data;
ftdm_channel_t *closed_chan;
- uint32_t state_counter = 0, elapsed = 0, collecting = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = 30000;
+ uint32_t state_counter = 0, elapsed = 0, collecting = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = analog_data->wait_dialtone_timeout;
ftdm_sigmsg_t sig;
ftdm_status_t status;
@@ -383,7 +417,11 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
sig.span_id = ftdmchan->span_id;
sig.channel = ftdmchan;
- assert(interval != 0);
+ ftdm_assert(interval != 0, NULL);
+
+ if (!dial_timeout) {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Not waiting for dial tone to dial number %s\n", ftdmchan->caller_data.dnis.digits);
+ }
while (ftdm_running() && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INTHREAD)) {
ftdm_wait_flag_t flags = FTDM_READ;
@@ -400,7 +438,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
{
if (state_counter > 5000 || !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CALLERID_DETECT)) {
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_CALLERID_DETECT, NULL);
- ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
+ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING);
}
}
break;
@@ -412,7 +450,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
} else {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
}
- }
+ }
}
break;
case FTDM_CHANNEL_STATE_GENRING:
@@ -453,9 +491,10 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
ftdm_channel_command(ftdmchan, FTDM_COMMAND_GENERATE_RING_OFF, NULL);
}
- if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) &&
- (ftdmchan->last_state == FTDM_CHANNEL_STATE_RING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE
- || ftdmchan->last_state >= FTDM_CHANNEL_STATE_IDLE)) {
+ if (ftdmchan->type == FTDM_CHAN_TYPE_FXS &&
+ ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) &&
+ (ftdmchan->last_state == FTDM_CHANNEL_STATE_RINGING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE
+ || ftdmchan->last_state == FTDM_CHANNEL_STATE_RING)) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
} else {
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING;
@@ -497,7 +536,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
}
}
case FTDM_CHANNEL_STATE_UP:
- case FTDM_CHANNEL_STATE_IDLE:
+ case FTDM_CHANNEL_STATE_RING:
{
ftdm_sleep(interval);
continue;
@@ -561,7 +600,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
ftdm_channel_use(ftdmchan);
}
break;
- case FTDM_CHANNEL_STATE_IDLE:
+ case FTDM_CHANNEL_STATE_RING:
{
ftdm_channel_use(ftdmchan);
sig.event_id = FTDM_SIGEVENT_START;
@@ -631,7 +670,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
continue;
}
break;
- case FTDM_CHANNEL_STATE_RING:
+ case FTDM_CHANNEL_STATE_RINGING:
{
ftdm_buffer_zero(dt_buffer);
teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_RING]);
@@ -694,7 +733,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
if (last_digit && (!collecting || ((elapsed - last_digit > analog_data->digit_timeout) || strlen(dtmf) >= analog_data->max_dialstr))) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Number obtained [%s]\n", dtmf);
- ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
+ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING);
last_digit = 0;
collecting = 0;
}
@@ -730,28 +769,15 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failure indication detected!\n");
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
} else if (ftdmchan->detected_tones[FTDM_TONEMAP_DIAL]) {
- if (ftdm_strlen_zero(ftdmchan->caller_data.dnis.digits)) {
- ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "No Digits to send!\n");
- ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
- } else {
- if (ftdm_channel_command(ftdmchan, FTDM_COMMAND_SEND_DTMF, ftdmchan->caller_data.dnis.digits) != FTDM_SUCCESS) {
- ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Send Digits Failed [%s]\n", ftdmchan->last_error);
- ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
- } else {
- state_counter = 0;
- ftdmchan->needed_tones[FTDM_TONEMAP_RING] = 1;
- ftdmchan->needed_tones[FTDM_TONEMAP_BUSY] = 1;
- ftdmchan->needed_tones[FTDM_TONEMAP_FAIL1] = 1;
- ftdmchan->needed_tones[FTDM_TONEMAP_FAIL2] = 1;
- ftdmchan->needed_tones[FTDM_TONEMAP_FAIL3] = 1;
- dial_timeout = ((ftdmchan->dtmf_on + ftdmchan->dtmf_off) * strlen(ftdmchan->caller_data.dnis.digits)) + 2000;
- }
- }
+ analog_dial(ftdmchan, &state_counter, &dial_timeout);
} else if (ftdmchan->detected_tones[FTDM_TONEMAP_RING]) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
}
ftdm_channel_clear_detected_tones(ftdmchan);
+ } else if (!dial_timeout) {
+ /* we were requested not to wait for dial tone, we can dial immediately */
+ analog_dial(ftdmchan, &state_counter, &dial_timeout);
}
if ((ftdmchan->dtmf_buffer && ftdm_buffer_inuse(ftdmchan->dtmf_buffer)) || (ftdmchan->fsk_buffer && ftdm_buffer_inuse(ftdmchan->fsk_buffer))) {
@@ -865,7 +891,7 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
if (ftdm_test_flag(analog_data, FTDM_ANALOG_CALLERID)) {
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_GET_CALLERID);
} else {
- ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_IDLE);
+ ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_RING);
}
event->channel->ring_count = 1;
ftdm_mutex_unlock(event->channel->mutex);
diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ozmod_analog.2005.vcproj b/libs/freetdm/src/ftmod/ftmod_analog/ozmod_analog.2005.vcproj
deleted file mode 100644
index 7a1cf53b20..0000000000
--- a/libs/freetdm/src/ftmod/ftmod_analog/ozmod_analog.2005.vcproj
+++ /dev/null
@@ -1,202 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2008.vcproj b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2008.vcproj
index 8ad183797a..837ba7de0f 100644
--- a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2008.vcproj
+++ b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2008.vcproj
@@ -1,353 +1,353 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj
new file mode 100644
index 0000000000..3643e271ef
--- /dev/null
+++ b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj
@@ -0,0 +1,198 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ ftmod_analog_em
+ {B3F49375-2834-4937-9D8C-4AC2EC911010}
+ ftmod_analog_em
+ Win32Proj
+
+
+
+ DynamicLibrary
+ Unicode
+ true
+
+
+ DynamicLibrary
+ Unicode
+
+
+ DynamicLibrary
+ Unicode
+ true
+
+
+ DynamicLibrary
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ false
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ false
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+
+
+
+ Disabled
+ ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level4
+ true
+ EditAndContinue
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Windows
+ MachineX86
+
+
+
+
+ MaxSpeed
+ true
+ ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ true
+
+
+ Level4
+ true
+ ProgramDatabase
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Windows
+ true
+ true
+ MachineX86
+
+
+
+
+ X64
+
+
+ Disabled
+ ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level4
+ false
+ ProgramDatabase
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Windows
+ MachineX64
+
+
+
+
+ X64
+
+
+ MaxSpeed
+ true
+ ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ true
+
+
+ Level4
+ false
+ ProgramDatabase
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Windows
+ true
+ true
+ MachineX64
+
+
+
+
+
+
+
+
+
+
+ {93b8812c-3ec4-4f78-8970-ffbfc99e167d}
+ false
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj.filters
new file mode 100644
index 0000000000..3326f9fd16
--- /dev/null
+++ b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj.filters
@@ -0,0 +1,23 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c
index 199bba43a3..886c4a8fec 100644
--- a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c
+++ b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c
@@ -329,8 +329,8 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
{
if (state_counter > 500) {
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) &&
- (ftdmchan->last_state == FTDM_CHANNEL_STATE_RING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE
- || ftdmchan->last_state >= FTDM_CHANNEL_STATE_IDLE)) {
+ (ftdmchan->last_state == FTDM_CHANNEL_STATE_RINGING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE
+ || ftdmchan->last_state == FTDM_CHANNEL_STATE_RING)) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
} else {
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING;
@@ -340,7 +340,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
}
break;
case FTDM_CHANNEL_STATE_UP:
- case FTDM_CHANNEL_STATE_IDLE:
+ case FTDM_CHANNEL_STATE_RING:
{
ftdm_sleep(interval);
continue;
@@ -386,7 +386,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
ftdm_channel_use(ftdmchan);
}
break;
- case FTDM_CHANNEL_STATE_IDLE:
+ case FTDM_CHANNEL_STATE_RING:
{
ftdm_channel_use(ftdmchan);
@@ -421,7 +421,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
ftdm_channel_command(ftdmchan, FTDM_COMMAND_WINK, NULL);
}
break;
- case FTDM_CHANNEL_STATE_RING:
+ case FTDM_CHANNEL_STATE_RINGING:
{
ftdm_buffer_zero(dt_buffer);
teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_RING]);
@@ -477,7 +477,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
if (last_digit && (!collecting || ((elapsed - last_digit > analog_data->digit_timeout) || strlen(dtmf) > analog_data->max_dialstr))) {
ftdm_log(FTDM_LOG_DEBUG, "Number obtained [%s]\n", dtmf);
- ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
+ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING);
last_digit = 0;
collecting = 0;
}
diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ozmod_analog_em.2005.vcproj b/libs/freetdm/src/ftmod/ftmod_analog_em/ozmod_analog_em.2005.vcproj
deleted file mode 100644
index 9ecbadc232..0000000000
--- a/libs/freetdm/src/ftmod/ftmod_analog_em/ozmod_analog_em.2005.vcproj
+++ /dev/null
@@ -1,202 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj
new file mode 100644
index 0000000000..bd2e2fe4f0
--- /dev/null
+++ b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj
@@ -0,0 +1,223 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ ftmod_isdn
+ {729344A5-D5E9-434D-8EE8-AF8C6C795D15}
+ ftmod_isdn
+ Win32Proj
+
+
+
+ DynamicLibrary
+ Unicode
+ true
+
+
+ DynamicLibrary
+ Unicode
+
+
+ DynamicLibrary
+ Unicode
+ true
+
+
+ DynamicLibrary
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ $(SolutionDir)$(Configuration)\
+ $(Configuration)\
+ true
+ $(SolutionDir)$(Configuration)\
+ $(Configuration)\
+ false
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ false
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+
+
+
+ Disabled
+ ..\..\isdn\include;..\..\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ISDN_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level4
+ true
+ EditAndContinue
+
+
+ true
+ Windows
+ MachineX86
+
+
+
+
+ MaxSpeed
+ true
+ ..\..\isdn\include;..\..\include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ISDN_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ true
+
+
+ Level4
+ true
+ ProgramDatabase
+
+
+ true
+ Windows
+ true
+ true
+ MachineX86
+
+
+
+
+ X64
+
+
+ Disabled
+ ..\..\isdn\include;..\..\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ISDN_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level4
+ true
+ ProgramDatabase
+
+
+ true
+ Windows
+ MachineX64
+
+
+
+
+ X64
+
+
+ MaxSpeed
+ true
+ ..\..\isdn\include;..\..\include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ISDN_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ true
+
+
+ Level4
+ true
+ ProgramDatabase
+
+
+ true
+ Windows
+ true
+ true
+ MachineX64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {93b8812c-3ec4-4f78-8970-ffbfc99e167d}
+ false
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj.filters
new file mode 100644
index 0000000000..30824888fc
--- /dev/null
+++ b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj.filters
@@ -0,0 +1,110 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c
index 1dbd6d362e..6a8a4eb379 100644
--- a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c
+++ b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c
@@ -594,9 +594,10 @@ static void ftdm_isdn_call_event(struct Q931_Call *call, struct Q931_CallEvent *
return;
}
- if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) {
+ if (ftdm_channel_get_state(ftdmchan) != FTDM_CHANNEL_STATE_DOWN) {
ftdm_log(FTDM_LOG_DEBUG, "Channel %d:%d not in DOWN state, cleaning up\n",
- ftdmchan->span_id, ftdmchan->chan_id);
+ ftdm_channel_get_span_id(ftdmchan),
+ ftdm_channel_get_id(ftdmchan));
/*
* Send hangup signal to mod_openzap
@@ -606,7 +607,7 @@ static void ftdm_isdn_call_event(struct Q931_Call *call, struct Q931_CallEvent *
}
sig.event_id = FTDM_SIGEVENT_STOP;
- isdn_data->sig_cb(&sig);
+ ftdm_span_send_signal(ftdm_channel_get_span(ftdmchan), &sig);
/* Release zap channel */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
@@ -640,7 +641,9 @@ static void ftdm_isdn_call_event(struct Q931_Call *call, struct Q931_CallEvent *
return;
}
- ftdm_log(FTDM_LOG_DEBUG, "Call setup failed on channel %d:%d\n", ftdmchan->span_id, ftdmchan->chan_id);
+ ftdm_log(FTDM_LOG_DEBUG, "Call setup failed on channel %d:%d\n",
+ ftdm_channel_get_span_id(ftdmchan),
+ ftdm_channel_get_id(ftdmchan));
/*
* Send signal to mod_openzap
@@ -648,7 +651,7 @@ static void ftdm_isdn_call_event(struct Q931_Call *call, struct Q931_CallEvent *
sig.channel->caller_data.hangup_cause = FTDM_CAUSE_NETWORK_OUT_OF_ORDER;
sig.event_id = FTDM_SIGEVENT_STOP;
- isdn_data->sig_cb(&sig);
+ ftdm_span_send_signal(ftdm_channel_get_span(ftdmchan), &sig);
/* Release zap channel */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
@@ -908,7 +911,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
sig.channel->caller_data.hangup_cause = (cause) ? cause->Value : FTDM_CAUSE_NORMAL_UNSPECIFIED;
sig.event_id = FTDM_SIGEVENT_STOP;
- status = isdn_data->sig_cb(&sig);
+ status = ftdm_span_send_signal(span, &sig);
ftdm_log(FTDM_LOG_DEBUG, "Received %s in state %s, requested hangup for channel %d:%d\n", what,
ftdm_channel_get_state_str(ftdmchan),
@@ -1297,6 +1300,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
{
Q931mes_Generic *gen = (Q931mes_Generic *) ftdmchan->caller_data.raw_data;
ftdm_isdn_data_t *isdn_data = ftdmchan->span->signal_data;
+ ftdm_span_t *span = ftdm_channel_get_span(ftdmchan);
ftdm_sigmsg_t sig;
ftdm_status_t status;
@@ -1328,7 +1332,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
{
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
sig.event_id = FTDM_SIGEVENT_PROGRESS;
- if ((status = isdn_data->sig_cb(&sig) != FTDM_SUCCESS)) {
+ if ((status = ftdm_span_send_signal(ftdm_channel_get_span(ftdmchan), &sig) != FTDM_SUCCESS)) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
}
} else {
@@ -1376,7 +1380,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
{
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
sig.event_id = FTDM_SIGEVENT_START;
- if ((status = isdn_data->sig_cb(&sig) != FTDM_SUCCESS)) {
+ if ((status = ftdm_span_send_signal(span, &sig) != FTDM_SUCCESS)) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
}
}
@@ -1386,7 +1390,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
{
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_UNSPECIFIED;
sig.event_id = FTDM_SIGEVENT_RESTART;
- status = isdn_data->sig_cb(&sig);
+ status = ftdm_span_send_signal(span, &sig);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
}
break;
@@ -1394,7 +1398,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
{
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
sig.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA;
- if ((status = isdn_data->sig_cb(&sig) != FTDM_SUCCESS)) {
+ if ((status = ftdm_span_send_signal(span, &sig) != FTDM_SUCCESS)) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
}
} else {
@@ -1414,7 +1418,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
{
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
sig.event_id = FTDM_SIGEVENT_UP;
- if ((status = isdn_data->sig_cb(&sig) != FTDM_SUCCESS)) {
+ if ((status = ftdm_span_send_signal(span, &sig) != FTDM_SUCCESS)) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
}
} else {
@@ -1635,7 +1639,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
ftdm_log(FTDM_LOG_DEBUG, "Terminating: Direction %s\n", ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? "Outbound" : "Inbound");
sig.event_id = FTDM_SIGEVENT_STOP;
- status = isdn_data->sig_cb(&sig);
+ status = ftdm_span_send_signal(span, &sig);
gen->MesType = Q931mes_RELEASE;
gen->CRVFlag = ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? 0 : 1;
@@ -1672,7 +1676,6 @@ static __inline__ void check_state(ftdm_span_t *span)
static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *event)
{
- ftdm_isdn_data_t *isdn_data = span->signal_data;
ftdm_alarm_flag_t alarmbits;
ftdm_sigmsg_t sig;
@@ -1696,7 +1699,7 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
}
ftdm_set_flag(event->channel, FTDM_CHANNEL_SUSPENDED);
ftdm_channel_get_alarms(event->channel, &alarmbits);
- isdn_data->sig_cb(&sig);
+ ftdm_span_send_signal(span, &sig);
ftdm_log(FTDM_LOG_WARNING, "channel %d:%d (%d:%d) has alarms [%s]\n",
ftdm_channel_get_span_id(event->channel),
@@ -1711,7 +1714,7 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
sig.event_id = FTDM_OOB_ALARM_CLEAR;
ftdm_clear_flag(event->channel, FTDM_CHANNEL_SUSPENDED);
ftdm_channel_get_alarms(event->channel, &alarmbits);
- isdn_data->sig_cb(&sig);
+ ftdm_span_send_signal(span, &sig);
}
break;
#ifdef __BROKEN_BY_FREETDM_CONVERSION__
@@ -2056,8 +2059,7 @@ static void *ftdm_isdn_run(ftdm_thread_t *me, void *obj)
}
done:
-// ftdm_channel_close(&isdn_data->dchans[0]);
-// ftdm_channel_close(&isdn_data->dchans[1]);
+ ftdm_channel_close(&isdn_data->dchan);
ftdm_clear_flag(isdn_data, FTDM_ISDN_RUNNING);
#ifdef WIN32
@@ -2744,8 +2746,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(isdn_configure_span)
}
}
- isdn_data->sig_cb = sig_cb;
- isdn_data->dchan = dchan;
+ isdn_data->dchan = dchan;
isdn_data->digit_timeout = digit_timeout;
Q921_InitTrunk(&isdn_data->q921,
@@ -2787,6 +2788,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(isdn_configure_span)
span->state_map = &isdn_state_map;
span->signal_data = isdn_data;
span->signal_type = FTDM_SIGTYPE_ISDN;
+ span->signal_cb = sig_cb;
span->start = ftdm_isdn_start;
span->stop = ftdm_isdn_stop;
span->outgoing_call = isdn_outgoing_call;
diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h
index 95eee90887..6b17f2cbef 100644
--- a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h
+++ b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h
@@ -63,9 +63,6 @@ struct ftdm_isdn_data {
Q921Data_t q921;
Q931_TrunkInfo_t q931;
ftdm_channel_t *dchan;
- ftdm_channel_t *dchans[2];
- struct ftdm_sigmsg sigmsg;
- fio_signal_cb_t sig_cb;
uint32_t flags;
int32_t mode;
int32_t digit_timeout;
diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c
index 21d6674717..68f0e9e5a4 100644
--- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c
+++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c
@@ -462,7 +462,7 @@ static ftdm_state_map_t isdn_state_map = {
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_RING, FTDM_END},
- {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END}
+ {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END}
},
{
ZSD_INBOUND,
@@ -479,7 +479,7 @@ static ftdm_state_map_t isdn_state_map = {
{
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
- {FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
+ {FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA,
FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_UP, FTDM_END},
},
@@ -495,6 +495,7 @@ static ftdm_state_map_t isdn_state_map = {
/**
* \brief Handler for channel state change
* \param ftdmchan Channel to handle
+ * \note This function MUST be called with the channel locked
*/
static __inline__ void state_advance(ftdm_channel_t *chan)
{
@@ -503,15 +504,9 @@ static __inline__ void state_advance(ftdm_channel_t *chan)
ftdm_status_t status;
ftdm_sigmsg_t sig;
- ftdm_log(FTDM_LOG_DEBUG, "%d:%d STATE [%s]\n",
+ ftdm_log(FTDM_LOG_DEBUG, "-- %d:%d STATE [%s]\n",
ftdm_channel_get_span_id(chan), ftdm_channel_get_id(chan), ftdm_channel_get_state_str(chan));
-#if 0
- if (!ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND) && !call) {
- ftdm_log(FTDM_LOG_WARNING, "NO CALL!!!!\n");
- }
-#endif
-
memset(&sig, 0, sizeof(sig));
sig.chan_id = ftdm_channel_get_id(chan);
sig.span_id = ftdm_channel_get_span_id(chan);
@@ -522,10 +517,28 @@ static __inline__ void state_advance(ftdm_channel_t *chan)
{
chan->call_data = NULL;
ftdm_channel_done(chan);
+
+ /*
+ * Close channel completely, BRI PTMP will thank us
+ */
+ if (ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
+ ftdm_channel_t *chtmp = chan;
+ if (ftdm_channel_close(&chtmp) != FTDM_SUCCESS) {
+ ftdm_log(FTDM_LOG_WARNING, "-- Failed to close channel %d:%d\n",
+ ftdm_channel_get_span_id(chan),
+ ftdm_channel_get_id(chan));
+ } else {
+ ftdm_log(FTDM_LOG_DEBUG, "-- Closed channel %d:%d\n",
+ ftdm_channel_get_span_id(chan),
+ ftdm_channel_get_id(chan));
+ }
+ }
}
break;
case FTDM_CHANNEL_STATE_PROGRESS:
+ /* RINGING is an alias for PROGRESS state in inbound calls ATM */
+ case FTDM_CHANNEL_STATE_RINGING:
{
if (ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) {
sig.event_id = FTDM_SIGEVENT_PROGRESS;
@@ -548,6 +561,10 @@ static __inline__ void state_advance(ftdm_channel_t *chan)
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP);
}
} else if (call) {
+ /* make sure channel is open in this state (outbound handled in on_proceeding()) */
+ if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
+ ftdm_channel_open_chan(chan);
+ }
pri_proceeding(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 1);
} else {
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART);
@@ -557,6 +574,10 @@ static __inline__ void state_advance(ftdm_channel_t *chan)
case FTDM_CHANNEL_STATE_RING:
{
+ /*
+ * This needs more auditing for BRI PTMP:
+ * does pri_acknowledge() steal the call from other devices?
+ */
if (!ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) {
if (call) {
pri_acknowledge(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 0);
@@ -588,6 +609,10 @@ static __inline__ void state_advance(ftdm_channel_t *chan)
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP);
}
} else if (call) {
+ /* make sure channel is open in this state (outbound handled in on_answer()) */
+ if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
+ ftdm_channel_open_chan(chan);
+ }
pri_answer(isdn_data->spri.pri, call, 0, 1);
} else {
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART);
@@ -705,15 +730,13 @@ static __inline__ void check_state(ftdm_span_t *span)
for (j = 1; j <= ftdm_span_get_chan_count(span); j++) {
ftdm_channel_t *chan = ftdm_span_get_channel(span, j);
- if (ftdm_test_flag(chan, FTDM_CHANNEL_STATE_CHANGE)) {
- ftdm_channel_lock(chan);
-
+ ftdm_channel_lock(chan);
+ while (ftdm_test_flag(chan, FTDM_CHANNEL_STATE_CHANGE)) {
ftdm_clear_flag(chan, FTDM_CHANNEL_STATE_CHANGE);
state_advance(chan);
ftdm_channel_complete_state(chan);
-
- ftdm_channel_unlock(chan);
}
+ ftdm_channel_unlock(chan);
}
}
}
@@ -795,34 +818,113 @@ static int on_answer(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_even
ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->answer.channel);
if (chan) {
+ if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
+ ftdm_log(FTDM_LOG_DEBUG, "-- Call answered, opening B-Channel %d:%d\n",
+ ftdm_channel_get_span_id(chan),
+ ftdm_channel_get_id(chan));
+
+ if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) {
+ ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
+
+ ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n",
+ ftdm_channel_get_span_id(chan),
+ ftdm_channel_get_id(chan));
+
+ caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER;
+ ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING);
+ goto out;
+ }
+ }
ftdm_log(FTDM_LOG_DEBUG, "-- Answer on channel %d:%d\n", ftdm_span_get_id(span), pevent->answer.channel);
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_UP);
} else {
ftdm_log(FTDM_LOG_DEBUG, "-- Answer on channel %d:%d but it's not in the span?\n",
ftdm_span_get_id(span), pevent->answer.channel);
}
+out:
return 0;
}
/**
- * \brief Handler for libpri proceed event
+ * \brief Handler for libpri proceeding event
* \param spri Pri wrapper structure (libpri, span, dchan)
* \param event_type Event type (unused)
* \param pevent Event
* \return 0
*/
-static int on_proceed(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
+static int on_proceeding(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
{
ftdm_span_t *span = spri->span;
- ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->answer.channel);
+ ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->proceeding.channel);
if (chan) {
+ /* Open channel if inband information is available */
+ if ((pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) && !ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
+ ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, opening B-Channel %d:%d\n",
+ ftdm_channel_get_span_id(chan),
+ ftdm_channel_get_id(chan));
+
+ if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) {
+ ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
+
+ ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n",
+ ftdm_channel_get_span_id(chan),
+ ftdm_channel_get_id(chan));
+
+ caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER;
+ ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING);
+ goto out;
+ }
+ }
ftdm_log(FTDM_LOG_DEBUG, "-- Proceeding on channel %d:%d\n", ftdm_span_get_id(span), pevent->proceeding.channel);
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
} else {
ftdm_log(FTDM_LOG_DEBUG, "-- Proceeding on channel %d:%d but it's not in the span?\n",
ftdm_span_get_id(span), pevent->proceeding.channel);
}
+out:
+ return 0;
+}
+
+/**
+ * \brief Handler for libpri progress event
+ * \param spri Pri wrapper structure (libpri, span, dchan)
+ * \param event_type Event type (unused)
+ * \param pevent Event
+ * \return 0
+ * \note also uses pri_event->proceeding
+ */
+static int on_progress(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
+{
+ ftdm_span_t *span = spri->span;
+ ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->proceeding.channel);
+
+ if (chan) {
+ /* Open channel if inband information is available */
+ if ((pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) && !ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
+ ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, opening B-Channel %d:%d\n",
+ ftdm_channel_get_span_id(chan),
+ ftdm_channel_get_id(chan));
+
+ if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) {
+ ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
+
+ ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n",
+ ftdm_channel_get_span_id(chan),
+ ftdm_channel_get_id(chan));
+
+ caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER;
+ ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING);
+ goto out;
+ }
+ }
+ ftdm_log(FTDM_LOG_DEBUG, "-- Progress on channel %d:%d\n", ftdm_span_get_id(span), pevent->proceeding.channel);
+ ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
+ } else {
+ ftdm_log(FTDM_LOG_DEBUG, "-- Progress on channel %d:%d but it's not in the span?\n",
+ ftdm_span_get_id(span), pevent->proceeding.channel);
+ }
+out:
return 0;
}
@@ -840,17 +942,37 @@ static int on_ringing(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve
if (chan) {
ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d\n", ftdm_span_get_id(span), pevent->ringing.channel);
+
/* we may get on_ringing even when we're already in FTDM_CHANNEL_STATE_PROGRESS_MEDIA */
if (ftdm_channel_get_state(chan) == FTDM_CHANNEL_STATE_PROGRESS_MEDIA) {
/* dont try to move to STATE_PROGRESS to avoid annoying veto warning */
return 0;
}
+
+ /* Open channel if inband information is available */
+ if ((pevent->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) && !ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
+ ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, opening B-Channel %d:%d\n",
+ ftdm_channel_get_span_id(chan),
+ ftdm_channel_get_id(chan));
+
+ if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) {
+ ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
+
+ ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n",
+ ftdm_channel_get_span_id(chan),
+ ftdm_channel_get_id(chan));
+
+ caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER;
+ ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING);
+ goto out;
+ }
+ }
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS);
} else {
ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d but it's not in the span?\n",
ftdm_span_get_id(span), pevent->ringing.channel);
}
-
+out:
return 0;
}
@@ -868,14 +990,49 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event
ftdm_caller_data_t *caller_data = NULL;
int ret = 0;
- if (!chan || ftdm_channel_get_state(chan) != FTDM_CHANNEL_STATE_DOWN || ftdm_test_flag(chan, FTDM_CHANNEL_INUSE)) {
- ftdm_log(FTDM_LOG_WARNING, "--Duplicate Ring on channel %d:%d (ignored)\n", ftdm_span_get_id(span), pevent->ring.channel);
+ if (!chan) {
+ ftdm_log(FTDM_LOG_ERROR, "-- Unable to get channel %d:%d\n", ftdm_span_get_id(span), pevent->ring.channel);
+ return ret;
+ }
+
+ ftdm_channel_lock(chan);
+
+ if (chan->call_data) {
+ /* we could drop the incoming call, but most likely the pointer is just a ghost of the past,
+ * this check is just to detect potentially unreleased pointers */
+ ftdm_log_chan(chan, FTDM_LOG_ERROR, "channel already has call %p!\n", chan->call_data);
+ chan->call_data = NULL;
+ }
+
+ if (ftdm_channel_get_state(chan) != FTDM_CHANNEL_STATE_DOWN || ftdm_test_flag(chan, FTDM_CHANNEL_INUSE)) {
+ ftdm_log(FTDM_LOG_WARNING, "-- Duplicate Ring on channel %d:%d (ignored)\n", ftdm_span_get_id(span), pevent->ring.channel);
goto done;
}
- if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) {
- ftdm_log(FTDM_LOG_WARNING, "--Failure opening channel %d:%d (ignored)\n", ftdm_span_get_id(span), pevent->ring.channel);
- goto done;
+ if ((pevent->ring.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
+ /* Open channel if inband information is available */
+ ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, opening B-Channel %d:%d\n",
+ ftdm_channel_get_span_id(chan),
+ ftdm_channel_get_id(chan));
+
+ if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN) && ftdm_channel_open_chan(chan) != FTDM_SUCCESS) {
+// ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
+
+ ftdm_log(FTDM_LOG_WARNING, "-- Error opening channel %d:%d (ignored)\n",
+ ftdm_channel_get_span_id(chan),
+ ftdm_channel_get_id(chan));
+
+// caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER;
+// ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING);
+// goto done;
+ }
+ } else {
+ /* Reserve channel, don't open it yet */
+ if (ftdm_channel_use(chan) != FTDM_SUCCESS) {
+ ftdm_log(FTDM_LOG_WARNING, "-- Error reserving channel %d:%d (ignored)\n",
+ ftdm_span_get_id(span), pevent->ring.channel);
+ goto done;
+ }
}
ftdm_log(FTDM_LOG_NOTICE, "-- Ring on channel %d:%d (from %s to %s)\n", ftdm_span_get_id(span), pevent->ring.channel,
@@ -901,12 +1058,13 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event
}
// scary to trust this pointer, you'd think they would give you a copy of the call data so you own it......
- /* hurr, this valid as along as nobody releases the call */
+ /* hurr, this is valid as along as nobody releases the call */
chan->call_data = pevent->ring.call;
- ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RING);
+ ftdm_set_state(chan, FTDM_CHANNEL_STATE_RING);
done:
+ ftdm_channel_unlock(chan);
return ret;
}
@@ -1300,7 +1458,7 @@ static int on_dchan_down(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_
*/
static int on_anything(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
{
- ftdm_log(FTDM_LOG_DEBUG, "Caught Event span %d %u (%s)\n", ftdm_span_get_id(spri->span), event_type, lpwrap_pri_event_str(event_type));
+ ftdm_log(FTDM_LOG_DEBUG, "-- Caught Event span %d %u (%s)\n", ftdm_span_get_id(spri->span), event_type, lpwrap_pri_event_str(event_type));
return 0;
}
@@ -1313,7 +1471,7 @@ static int on_anything(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev
*/
static int on_io_fail(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
{
- ftdm_log(FTDM_LOG_DEBUG, "Caught Event span %d %u (%s)\n", ftdm_span_get_id(spri->span), event_type, lpwrap_pri_event_str(event_type));
+ ftdm_log(FTDM_LOG_DEBUG, "-- Caught Event span %d %u (%s)\n", ftdm_span_get_id(spri->span), event_type, lpwrap_pri_event_str(event_type));
return 0;
}
@@ -1401,8 +1559,8 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj)
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_ANY, on_anything);
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RING, on_ring);
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RINGING, on_ringing);
- //LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_SETUP_ACK, on_proceed);
- LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_PROCEEDING, on_proceed);
+ LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_PROCEEDING, on_proceeding);
+ LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_PROGRESS, on_progress);
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_ANSWER, on_answer);
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_DCHAN_UP, on_dchan_up);
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_DCHAN_DOWN, on_dchan_down);
diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c b/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c
index de4fa2b232..fbe6ca0822 100644
--- a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c
+++ b/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c
@@ -134,17 +134,18 @@ static int __pri_lpwrap_read(struct pri *pri, void *buf, int buflen)
spri->errs = 0;
res = (int)len;
- memset(&((unsigned char*)buf)[res], 0, 2);
- res += 2;
-
+ if (res > 0) {
+ memset(&((unsigned char*)buf)[res], 0, 2);
+ res += 2;
#ifdef IODEBUG
- {
- char bb[2048] = { 0 };
+ {
+ char bb[2048] = { 0 };
- print_hex_bytes(buf, res - 2, bb, sizeof(bb));
- ftdm_log(FTDM_LOG_DEBUG, "READ %d\n", res - 2);
- }
+ print_hex_bytes(buf, res - 2, bb, sizeof(bb));
+ ftdm_log(FTDM_LOG_DEBUG, "READ %d\n", res - 2);
+ }
#endif
+ }
return res;
}
diff --git a/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj
new file mode 100644
index 0000000000..c4004bda21
--- /dev/null
+++ b/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj
@@ -0,0 +1,198 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ ftmod_pika
+ {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}
+ ftmod_pika
+ Win32Proj
+
+
+
+ DynamicLibrary
+ Unicode
+ true
+
+
+ DynamicLibrary
+ Unicode
+
+
+ DynamicLibrary
+ Unicode
+ true
+
+
+ DynamicLibrary
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ $(SolutionDir)$(Configuration)\
+ $(Configuration)\
+ true
+ $(SolutionDir)$(Configuration)\
+ $(Configuration)\
+ false
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ false
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+
+
+
+ Disabled
+ ..\..\isdn\include;..\..\include;..\..\..\pika\aoh\inc;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_PIKA_EXPORTS;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level3
+ EditAndContinue
+
+
+ pikahmpapi.lib;%(AdditionalDependencies)
+ ..\..\..\pika\aoh\lib;%(AdditionalLibraryDirectories)
+ true
+ Windows
+ MachineX86
+
+
+
+
+ MaxSpeed
+ true
+ ..\..\isdn\include;..\..\include;..\..\..\pika\aoh\inc;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_PIKA_EXPORTS;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ true
+
+
+ Level3
+ ProgramDatabase
+
+
+ pikahmpapi.lib;%(AdditionalDependencies)
+ ..\..\..\pika\aoh\lib;%(AdditionalLibraryDirectories)
+ true
+ Windows
+ true
+ true
+ MachineX86
+
+
+
+
+ X64
+
+
+ Disabled
+ ..\..\isdn\include;..\..\include;..\..\..\pika\aoh\inc;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_PIKA_EXPORTS;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level3
+ ProgramDatabase
+
+
+ pikahmpapi.lib;%(AdditionalDependencies)
+ ..\..\..\pika\aoh\lib;%(AdditionalLibraryDirectories)
+ true
+ Windows
+ MachineX64
+
+
+
+
+ X64
+
+
+ MaxSpeed
+ true
+ ..\..\isdn\include;..\..\include;..\..\..\pika\aoh\inc;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_PIKA_EXPORTS;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ true
+
+
+ Level3
+ ProgramDatabase
+
+
+ pikahmpapi.lib;%(AdditionalDependencies)
+ ..\..\..\pika\aoh\lib;%(AdditionalLibraryDirectories)
+ true
+ Windows
+ true
+ true
+ MachineX64
+
+
+
+
+
+
+
+
+
+
+ {93b8812c-3ec4-4f78-8970-ffbfc99e167d}
+ false
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj.filters
new file mode 100644
index 0000000000..4d4cec4668
--- /dev/null
+++ b/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj.filters
@@ -0,0 +1,23 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2008.vcproj b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2008.vcproj
index 9ea351ba6a..8942a8f5b6 100644
--- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2008.vcproj
+++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2008.vcproj
@@ -60,9 +60,9 @@
/>
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ ftmod_r2
+ {08C3EA27-A51D-47F8-B47D-B189C649CF30}
+ Win32Proj
+
+
+
+ DynamicLibrary
+
+
+ DynamicLibrary
+
+
+ DynamicLibrary
+
+
+ DynamicLibrary
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ true
+ true
+ true
+ true
+ AllRules.ruleset
+ AllRules.ruleset
+
+
+
+
+ AllRules.ruleset
+ AllRules.ruleset
+
+
+
+
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ $(SolutionDir)$(Platform)\$(Configuration)\
+
+
+
+ Disabled
+ ..\..\include;c:\Program Files\openr2\include\openr2;C:\Program Files\openr2\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_R2_EXPORTS;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level3
+ EditAndContinue
+
+
+ freetdm.lib;openr2.lib;%(AdditionalDependencies)
+ C:\Program Files\openr2\lib;$(OutDir);%(AdditionalLibraryDirectories)
+ true
+ Windows
+ MachineX86
+
+
+
+
+ Disabled
+ ..\..\include;c:\Program Files\openr2\include\openr2;C:\Program Files\openr2\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_R2_EXPORTS;%(PreprocessorDefinitions)
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level3
+ ProgramDatabase
+
+
+ freetdm.lib;openr2.lib;%(AdditionalDependencies)
+ C:\Program Files\openr2\lib;$(OutDir);%(AdditionalLibraryDirectories)
+ true
+ Windows
+
+
+
+
+ ..\..\include;C:\Program Files\openr2\include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_R2_EXPORTS;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+
+
+ Level3
+ ProgramDatabase
+
+
+ true
+ Windows
+ true
+ true
+ MachineX86
+
+
+
+
+ ..\..\include;C:\Program Files\openr2\include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_R2_EXPORTS;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+
+
+ Level3
+ ProgramDatabase
+
+
+ true
+ Windows
+ true
+ true
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj.filters
new file mode 100644
index 0000000000..9c91228e09
--- /dev/null
+++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj.filters
@@ -0,0 +1,22 @@
+
+
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
index d5344814f0..654e68ad9e 100644
--- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
+++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
@@ -29,6 +29,11 @@
* 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.
+ *
+ * Contributors:
+ *
+ * Arnaldo Pereira
+ *
*/
#ifdef __linux__
@@ -56,26 +61,24 @@ typedef enum {
FTDM_R2_RUNNING = (1 << 0),
} ftdm_r2_flag_t;
-typedef enum {
- FTDM_R2_PROCESSING = (1 << 0),
- FTDM_R2_WAITING_ACK = (1 << 1),
-} ftdm_r2_call_flag_t;
-
-/* private call information stored in ftdmchan->call_data void* ptr */
+/* private call information stored in ftdmchan->call_data void* ptr,
+ * remember that each time you add a new member to this structure
+ * most likely you want to clear it in ft_r2_clean_call function
+ * */
#define R2CALL(ftdmchan) ((ftdm_r2_call_t*)((ftdmchan)->call_data))
typedef struct ftdm_r2_call_t {
openr2_chan_t *r2chan;
- ftdm_r2_call_flag_t flags;
int accepted:1;
int answer_pending:1;
- int state_ack_pending:1;
int disconnect_rcvd:1;
- int ftdm_started:1;
+ int ftdm_call_started:1;
+ int protocol_error:1;
ftdm_channel_state_t chanstate;
ftdm_size_t dnis_index;
ftdm_size_t ani_index;
+ char logname[255];
char name[10];
- unsigned long txdrops;
+ ftdm_timer_id_t protocol_error_recovery_timer;
} ftdm_r2_call_t;
/* this is just used as place holder in the stack when configuring the span to avoid using bunch of locals */
@@ -94,13 +97,13 @@ typedef struct ft_r2_conf_s {
int32_t max_dnis;
int32_t mfback_timeout;
int32_t metering_pulse_timeout;
+ ftdm_size_t mf_dump_size;
/* booleans */
int immediate_accept;
int skip_category;
int get_ani_first;
int call_files;
- int mf_files;
int double_answer;
int charge_calls;
int forced_release;
@@ -123,12 +126,26 @@ typedef struct ftdm_r2_data_s {
int forced_release:1;
/* whether accept the call when offered, or wait until the user decides to accept */
int accept_on_offer:1;
+ /* Size of multi-frequency (or any media) dumps used during protocol errors */
+ ftdm_size_t mf_dump_size;
/* max time spent in ms doing real work in a single loop */
- int jobmax;
- /* total working loops */
- unsigned long loops;
+ int32_t jobmax;
+ /* Total number of loops performed so far */
+ uint64_t total_loops;
+ /* number of loops per 10ms increment from 0-9ms, 10-19ms .. 100ms and above */
+ uint64_t loops[11];
+ /* Total number of sleeps performed so far */
+ uint64_t total_sleeps;
+ /* number of sleeps per 10ms increment from 0-9ms, 10-19ms .. 100ms and above */
+ uint64_t sleeps[11];
+ /* max time spent in ms sleeping in a single loop */
+ int32_t sleepmax;
/* LWP */
- unsigned long monitor_thread_id;
+ uint32_t monitor_thread_id;
+ /* Logging directory */
+ char logdir[512];
+ /* scheduling context */
+ ftdm_sched_t *sched;
} ftdm_r2_data_t;
/* one element per span will be stored in g_mod_data_hash global var to keep track of them
@@ -136,6 +153,7 @@ typedef struct ftdm_r2_data_s {
typedef struct ftdm_r2_span_pvt_s {
openr2_context_t *r2context; /* r2 context allocated for this span */
ftdm_hash_t *r2calls; /* hash table of allocated call data per channel for this span */
+ ftdm_sched_t *sched; /* schedule for the span */
} ftdm_r2_span_pvt_t;
/* span monitor thread */
@@ -151,7 +169,14 @@ static ftdm_hash_t *g_mod_data_hash;
static ftdm_io_interface_t g_ftdm_r2_interface;
static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan);
+static void ftdm_r2_state_advance_all(ftdm_channel_t *ftdmchan);
+/* whether R2 call accept process is pending */
+#define IS_ACCEPTING_PENDING(ftdmchan) \
+ ( (!ftdm_test_flag((ftdmchan), FTDM_CHANNEL_OUTBOUND)) && !R2CALL((ftdmchan))->accepted && \
+ ((ftdmchan)->state == FTDM_CHANNEL_STATE_PROGRESS || \
+ (ftdmchan)->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA || \
+ (ftdmchan)->state == FTDM_CHANNEL_STATE_UP) )
/* functions not available on windows */
#ifdef WIN32
@@ -220,6 +245,23 @@ static char *strsep(char **stringp, const char *delim)
}
#endif /* WIN32 */
+static void ftdm_r2_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status)
+{
+ ftdm_sigmsg_t sig;
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Signalling link status changed to %s\n", ftdm_signaling_status2str(status));
+
+ memset(&sig, 0, sizeof(sig));
+ sig.chan_id = ftdmchan->chan_id;
+ sig.span_id = ftdmchan->span_id;
+ sig.channel = ftdmchan;
+ sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
+ sig.sigstatus = status;
+ if (ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS) {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to change channel status to %s\n", ftdm_signaling_status2str(status));
+ }
+ return;
+}
+
static ftdm_call_cause_t ftdm_r2_cause_to_ftdm_cause(ftdm_channel_t *fchan, openr2_call_disconnect_cause_t cause)
{
switch (cause) {
@@ -279,6 +321,7 @@ static openr2_call_disconnect_cause_t ftdm_r2_ftdm_cause_to_openr2_cause(ftdm_ch
case FTDM_CAUSE_NETWORK_OUT_OF_ORDER:
case FTDM_CAUSE_SERVICE_UNAVAILABLE:
+ case FTDM_CAUSE_PROTOCOL_ERROR:
return OR2_CAUSE_OUT_OF_ORDER;
case FTDM_CAUSE_NO_ANSWER:
@@ -296,9 +339,21 @@ static openr2_call_disconnect_cause_t ftdm_r2_ftdm_cause_to_openr2_cause(ftdm_ch
static void ft_r2_clean_call(ftdm_r2_call_t *call)
{
- openr2_chan_t *r2chan = call->r2chan;
- memset(call, 0, sizeof(*call));
- call->r2chan = r2chan;
+ openr2_chan_t *r2chan = call->r2chan;
+
+ /* Do not memset call structure, that clears values we do not want to clear,
+ * like the log name set in on_call_log_created() */
+ call->r2chan = r2chan;
+ call->accepted = 0;
+ call->answer_pending = 0;
+ call->disconnect_rcvd = 0;
+ call->ftdm_call_started = 0;
+ call->protocol_error = 0;
+ call->chanstate = FTDM_CHANNEL_STATE_DOWN;
+ call->dnis_index = 0;
+ call->ani_index = 0;
+ call->name[0] = 0;
+ call->protocol_error_recovery_timer = 0;
}
static void ft_r2_accept_call(ftdm_channel_t *ftdmchan)
@@ -338,30 +393,32 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call)
}
ft_r2_clean_call(ftdmchan->call_data);
- R2CALL(ftdmchan)->ftdm_started = 1;
- R2CALL(ftdmchan)->chanstate = FTDM_CHANNEL_STATE_DOWN;
- ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DIALING);
+
+ /* start io dump */
+ if (r2data->mf_dump_size) {
+ ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_INPUT_DUMP, &r2data->mf_dump_size);
+ ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_OUTPUT_DUMP, &r2data->mf_dump_size);
+ }
callstatus = openr2_chan_make_call(R2CALL(ftdmchan)->r2chan,
ftdmchan->caller_data.cid_num.digits,
ftdmchan->caller_data.dnis.digits,
- OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER);
+ r2data->category);
- if (callstatus) {
- ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to make call in R2 channel, openr2_chan_make_call failed\n");
- return FTDM_FAIL;
- }
-
- if (ftdmchan->state != FTDM_CHANNEL_STATE_DIALING) {
- ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Collision after call attempt, try another channel, new state = %s\n",
- ftdm_channel_state2str(ftdmchan->state));
- ftdm_clear_flag(R2CALL(ftdmchan), FTDM_R2_WAITING_ACK);
- return FTDM_BREAK;
+ if (callstatus) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to make call in R2 channel, openr2_chan_make_call failed\n");
+ return FTDM_FAIL;
}
- /* non-threaded implementation, we're done here */
- ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "R2 call placed in non-threaded mode\n");
- return FTDM_SUCCESS;
+ R2CALL(ftdmchan)->ftdm_call_started = 1;
+ R2CALL(ftdmchan)->chanstate = FTDM_CHANNEL_STATE_DOWN;
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DIALING);
+
+ ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS);
+ ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLUSH_TX_BUFFERS, NULL);
+ ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLUSH_RX_BUFFERS, NULL);
+
+ return FTDM_SUCCESS;
}
static ftdm_status_t ftdm_r2_start(ftdm_span_t *span)
@@ -381,44 +438,50 @@ static ftdm_status_t ftdm_r2_stop(ftdm_span_t *span)
return FTDM_SUCCESS;
}
-static ftdm_status_t ftdm_r2_sig_read(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t size)
+static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_channel_sig_status)
{
- openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan;
- if (!openr2_chan_get_read_enabled(r2chan)) {
- ftdm_mutex_lock(ftdmchan->mutex);
- //openr2_chan_process_input(r2chan, data, size);
- ftdm_mutex_unlock(ftdmchan->mutex);
+ if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
+ *status = FTDM_SIG_STATE_UP;
+ } else {
+ *status = FTDM_SIG_STATE_DOWN;
}
+
return FTDM_SUCCESS;
}
/* always called from the monitor thread */
static void ftdm_r2_on_call_init(openr2_chan_t *r2chan)
{
- //ftdm_status_t status;
ftdm_r2_call_t *r2call;
ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
- //ftdm_r2_data_t *r2data = ftdmchan->span->signal_data;
+ ftdm_r2_data_t *r2data = ftdmchan->span->signal_data;
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Received request to start call\n");
- ftdm_mutex_lock(ftdmchan->mutex);
+ if (ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP) {
+ r2call = R2CALL(ftdmchan);
+ if (r2call->protocol_error) {
+ /* we had a protocol error and we were giving some recovery time, cancel the recovery timer now
+ * that is obvious that the other side recovered */
+ ftdm_sched_cancel_timer(r2data->sched, r2call->protocol_error_recovery_timer);
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Cancelled protocol error recovery timer\n");
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+ ftdm_r2_state_advance_all(ftdmchan);
+ }
+ }
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Cannot start call when channel is in use (state = %s)\n", ftdm_channel_state2str(ftdmchan->state));
- ftdm_mutex_unlock(ftdmchan->mutex);
return;
}
if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Cannot handle request to start call in state %s\n", ftdm_channel_state2str(ftdmchan->state));
- ftdm_mutex_unlock(ftdmchan->mutex);
return;
}
if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to open channel during incoming call! [%s]\n", ftdmchan->last_error);
- ftdm_mutex_unlock(ftdmchan->mutex);
return;
}
@@ -428,46 +491,123 @@ static void ftdm_r2_on_call_init(openr2_chan_t *r2chan)
memset(ftdmchan->caller_data.dnis.digits, 0, sizeof(ftdmchan->caller_data.collected));
memset(ftdmchan->caller_data.ani.digits, 0, sizeof(ftdmchan->caller_data.collected));
- /* clean the call data structure but keep the R2 processing flag on! */
ft_r2_clean_call(ftdmchan->call_data);
r2call = R2CALL(ftdmchan);
- ftdm_set_flag(r2call, FTDM_R2_PROCESSING);
- if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) {
- R2CALL(ftdmchan)->chanstate = FTDM_CHANNEL_STATE_DOWN;
- } else {
- R2CALL(ftdmchan)->chanstate = FTDM_CHANNEL_STATE_DIALING;
+ /* start io dump */
+ if (r2data->mf_dump_size) {
+ ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_INPUT_DUMP, &r2data->mf_dump_size);
+ ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_OUTPUT_DUMP, &r2data->mf_dump_size);
}
+ R2CALL(ftdmchan)->chanstate = FTDM_CHANNEL_STATE_DOWN;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT);
- ftdm_mutex_unlock(ftdmchan->mutex);
+ ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS);
+ ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLUSH_TX_BUFFERS, NULL);
+ ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLUSH_RX_BUFFERS, NULL);
}
+static void dump_mf(openr2_chan_t *r2chan);
/* only called for incoming calls when the ANI, DNIS etc is complete and the user has to decide either to accept or reject the call */
static void ftdm_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
{
ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
+ ftdm_r2_data_t *r2data = ftdmchan->span->signal_data;
- ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Call offered with ANI = %s, DNIS = %s, Priority = (%d)\n", ani, dnis, category);
- ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING);
+ ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Call offered with ANI = %s, DNIS = %s, Category = (%d)\n", ani, dnis, category);
+
+ /* nothing went wrong during call setup, MF has ended, we can and must disable the MF dump */
+ if (r2data->mf_dump_size) {
+ ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_INPUT_DUMP, NULL);
+ ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_OUTPUT_DUMP, NULL);
+ }
+
+ /* check if this is a collect call and if we should accept it */
+ if (!r2data->allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Rejecting collect call\n");
+ openr2_chan_disconnect_call(r2chan, OR2_CAUSE_COLLECT_CALL_REJECTED);
+ } else {
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
+ }
+}
+
+/*
+ * Accepting a call in R2 is a lengthy process due to MF tones,
+ * when the user sends PROGRESS indication (implicitly moving the
+ * ftdm channel to PROGRESS state) the R2 processing loop
+ * does not clear FTDM_CHANNEL_STATE_CHANGE immediately as it does
+ * for all the other states, instead has to wait for on_call_accepted
+ * callback from openr2, which means the MF has ended and the progress
+ * indication is done, in order to clear the flag. However, if
+ * a protocol error or call disconnection (which is indicated using CAS bits)
+ * occurrs while accepting, we must clear the pending flag, this function
+ * takes care of that
+ * */
+static void clear_accept_pending(ftdm_channel_t *fchan)
+{
+ if (IS_ACCEPTING_PENDING(fchan)) {
+ ftdm_clear_flag(fchan, FTDM_CHANNEL_STATE_CHANGE);
+ ftdm_channel_complete_state(fchan);
+ } else if (ftdm_test_flag(fchan, FTDM_CHANNEL_STATE_CHANGE)) {
+ ftdm_log_chan(fchan, FTDM_LOG_CRIT, "State change flag set in state %s, last state = %s\n",
+ ftdm_channel_state2str(fchan->state), ftdm_channel_state2str(fchan->last_state));
+ ftdm_clear_flag(fchan, FTDM_CHANNEL_STATE_CHANGE);
+ ftdm_channel_complete_state(fchan);
+ }
+}
+
+static void dump_mf(openr2_chan_t *r2chan)
+{
+ char dfile[512];
+ FILE *f = NULL;
+ ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
+ ftdm_r2_data_t *r2data = ftdmchan->span->signal_data;
+ if (r2data->mf_dump_size) {
+ char *logname = R2CALL(ftdmchan)->logname;
+
+ ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO output in prefix %s\n", logname);
+ 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, "w");
+ 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);
+
+ 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, "w");
+ 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);
+ }
}
static void ftdm_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
{
ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call accepted\n");
+
+ clear_accept_pending(ftdmchan);
+
/* at this point the MF signaling has ended and there is no point on keep reading */
openr2_chan_disable_read(r2chan);
+
+ /* at this point we are no longer responsible for reading and writing,
+ * we are not interested in the stats anymore */
+ ftdm_channel_clear_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS);
+
+
R2CALL(ftdmchan)->accepted = 1;
+
if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
- R2CALL(ftdmchan)->state_ack_pending = 1;
if (R2CALL(ftdmchan)->answer_pending) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Answer was pending, answering now.\n");
ft_r2_answer_call(ftdmchan);
+ R2CALL(ftdmchan)->answer_pending = 0;
return;
}
} else {
- ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
}
}
@@ -477,47 +617,30 @@ static void ftdm_r2_on_call_answered(openr2_chan_t *r2chan)
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call answered\n");
/* notify the upper layer of progress in the outbound call */
if (OR2_DIR_FORWARD == openr2_chan_get_direction(r2chan)) {
- ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP);
}
}
/* may be called in the signaling or media thread depending on whether the hangup is product of MF or CAS signaling */
static void ftdm_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
{
- ftdm_sigmsg_t sigev;
- ftdm_r2_data_t *r2data;
ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call disconnected\n");
- ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Got openr2 disconnection, clearing call\n");
+ clear_accept_pending(ftdmchan);
R2CALL(ftdmchan)->disconnect_rcvd = 1;
if (ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call had been disconnected already by the user\n");
- /* just ack the hangup to go down */
+ /* just ack the hangup to trigger the on_call_end callback and go down */
openr2_chan_disconnect_call(r2chan, OR2_CAUSE_NORMAL_CLEARING);
return;
}
- /* if the call has not been started yet we must go to HANGUP right here */
- if (!R2CALL(ftdmchan)->ftdm_started) {
- ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
- return;
- }
-
ftdmchan->caller_data.hangup_cause = ftdm_r2_cause_to_ftdm_cause(ftdmchan, cause);
-
- /* notify the user of the call terminating */
- 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_STOP;
- r2data = ftdmchan->span->signal_data;
-
- ftdm_span_send_signal(ftdmchan->span, &sigev);
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
}
static void ftdm_r2_on_call_end(openr2_chan_t *r2chan)
@@ -526,10 +649,10 @@ static void ftdm_r2_on_call_end(openr2_chan_t *r2chan)
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call finished\n");
/* the call is done as far as the stack is concerned, lets move to down here */
- ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
/* in some circumstances openr2 can call on_call_init right after this, so let's advance the state right here */
- ftdm_r2_state_advance(ftdmchan);
+ ftdm_r2_state_advance_all(ftdmchan);
}
static void ftdm_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
@@ -551,59 +674,59 @@ static void ftdm_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "OS error: %s\n", strerror(errorcode));
}
+static void ftdm_r2_recover_from_protocol_error(void *data)
+{
+ openr2_chan_t *r2chan = data;
+ ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
+ ftdm_channel_lock(ftdmchan);
+ if (ftdmchan->state != FTDM_CHANNEL_STATE_HANGUP) {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Recovering from protocol error but state is %s!\n", ftdm_channel_state2str(ftdmchan->state));
+ goto done;
+ }
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+ ftdm_r2_state_advance_all(ftdmchan);
+done:
+ ftdm_channel_unlock(ftdmchan);
+}
+
static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
{
- ftdm_sigmsg_t sigev;
- ftdm_r2_data_t *r2data;
ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
- ftdm_mutex_lock(ftdmchan->mutex);
-
if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Got protocol error when we're already down!\n");
- ftdm_mutex_unlock(ftdmchan->mutex);
+ return;
}
- ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Protocol error\n");
+ dump_mf(r2chan);
+
+ clear_accept_pending(ftdmchan);
R2CALL(ftdmchan)->disconnect_rcvd = 1;
+ R2CALL(ftdmchan)->protocol_error = 1;
- if (!R2CALL(ftdmchan)->ftdm_started) {
- ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
- ftdm_mutex_unlock(ftdmchan->mutex);
+ if (ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "The user already hung up, finishing call in protocol error\n");
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
return;
}
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_PROTOCOL_ERROR;
-
- /* FIXME: go to terminating and notify the user from the terminating handler instead of notifying here */
- 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_STOP;
- r2data = ftdmchan->span->signal_data;
-
- ftdm_span_send_signal(ftdmchan->span, &sigev);
-
- ftdm_mutex_unlock(ftdmchan->mutex);
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
}
static void ftdm_r2_on_line_blocked(openr2_chan_t *r2chan)
{
ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Far end blocked in state %s\n", ftdm_channel_state2str(ftdmchan->state));
- ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED);
+ ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_SUSPENDED);
}
static void ftdm_r2_on_line_idle(openr2_chan_t *r2chan)
{
ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Far end unblocked in state %s\n", ftdm_channel_state2str(ftdmchan->state));
- ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED);
-
- /* XXX when should we set/unset this flag? XXX */
- ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SIG_UP);
+ ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP);
}
static void ftdm_r2_write_log(openr2_log_level_t level, const char *file, const char *function, int line, const char *message)
@@ -648,14 +771,13 @@ static void ftdm_r2_on_chan_log(openr2_chan_t *r2chan, const char *file, const c
openr2_log_level_t level, const char *fmt, va_list ap)
{
ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
-#define CHAN_TAG "Chan "
- char logmsg[512];
- char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
+ char logmsg[1024];
+ char completemsg[sizeof(logmsg)];
vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
- snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d:%d [%s] %s",
- ftdmchan->span_id, ftdmchan->chan_id, ftdm_channel_state2str(ftdmchan->state), logmsg);
+ snprintf(completemsg, sizeof(completemsg), "[s%dc%d] [%d:%d] [%s] %s",
+ ftdmchan->span_id, ftdmchan->chan_id, ftdmchan->physical_span_id, ftdmchan->physical_chan_id,
+ ftdm_channel_state2str(ftdmchan->state), logmsg);
ftdm_r2_write_log(level, file, function, line, completemsg);
-#undef CHAN_TAG
}
static int ftdm_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
@@ -713,6 +835,16 @@ static void ftdm_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
R2CALL(ftdmchan)->ani_index = collected_len;
}
+static void ftdm_r2_on_billing_pulse(openr2_chan_t *r2chan) {}
+
+static void ftdm_r2_on_call_log_created(openr2_chan_t *r2chan, const char *logname)
+{
+ ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
+ ftdm_r2_call_t *r2call = R2CALL(ftdmchan);
+ /* this is used when dumping I/O for debugging */
+ snprintf(r2call->logname, sizeof(r2call->logname), "%s", logname);
+}
+
static openr2_event_interface_t ftdm_r2_event_iface = {
/* .on_call_init */ ftdm_r2_on_call_init,
/* .on_call_offered */ ftdm_r2_on_call_offered,
@@ -733,7 +865,8 @@ static openr2_event_interface_t ftdm_r2_event_iface = {
/* .on_ani_digit_received */ ftdm_r2_on_ani_digit_received,
/* so far we do nothing with billing pulses */
- /* .on_billing_pulse_received */ NULL,
+ /* .on_billing_pulse_received */ ftdm_r2_on_billing_pulse,
+ /* .on_call_log_created */ ftdm_r2_on_call_log_created,
};
static int ftdm_r2_io_set_cas(openr2_chan_t *r2chan, int cas)
@@ -774,7 +907,7 @@ static int ftdm_r2_io_write(openr2_chan_t *r2chan, const void *buf, int size)
if (FTDM_FAIL == status) {
return -1;
}
- return outsize;
+ return (int)outsize;
}
static int ftdm_r2_io_read(openr2_chan_t *r2chan, const void *buf, int size)
@@ -785,7 +918,7 @@ static int ftdm_r2_io_read(openr2_chan_t *r2chan, const void *buf, int size)
if (FTDM_FAIL == status) {
return -1;
}
- return outsize;
+ return (int)outsize;
}
static int ftdm_r2_io_wait(openr2_chan_t *r2chan, int *flags, int block)
@@ -794,7 +927,7 @@ static int ftdm_r2_io_wait(openr2_chan_t *r2chan, int *flags, int block)
int32_t timeout;
ftdm_wait_flag_t ftdmflags = 0;
- ftdm_channel_t *ftdm_chan = openr2_chan_get_fd(r2chan);
+ ftdm_channel_t *fchan = openr2_chan_get_fd(r2chan);
timeout = block ? -1 : 0;
if (*flags & OR2_IO_READ) {
@@ -807,9 +940,10 @@ static int ftdm_r2_io_wait(openr2_chan_t *r2chan, int *flags, int block)
ftdmflags |= FTDM_EVENTS;
}
- status = ftdm_channel_wait(ftdm_chan, &ftdmflags, timeout);
+ status = ftdm_channel_wait(fchan, &ftdmflags, timeout);
if (FTDM_SUCCESS != status && FTDM_TIMEOUT != status) {
+ ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Failed to wait for events on channel\n");
return -1;
}
@@ -853,8 +987,36 @@ static int ftdm_r2_io_setup(openr2_chan_t *r2chan)
static int ftdm_r2_io_get_oob_event(openr2_chan_t *r2chan, openr2_oob_event_t *event)
{
- *event = 0;
- ftdm_log(FTDM_LOG_ERROR, "I should not be called (I/O get oob event)!!\n");
+ ftdm_status_t status;
+ ftdm_event_t *fevent = NULL;
+ ftdm_channel_t *ftdmchan = openr2_chan_get_fd(r2chan);
+
+ *event = OR2_OOB_EVENT_NONE;
+
+ status = ftdm_channel_read_event(ftdmchan, &fevent);
+
+ if (status != FTDM_SUCCESS) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "failed to retrieve freetdm event!\n");
+ return -1;
+ }
+
+ switch (fevent->enum_id) {
+ case FTDM_OOB_CAS_BITS_CHANGE:
+ {
+ *event = OR2_OOB_EVENT_CAS_CHANGE;
+ }
+ break;
+ case FTDM_OOB_ALARM_TRAP:
+ {
+ *event = OR2_OOB_EVENT_ALARM_ON;
+ }
+ break;
+ case FTDM_OOB_ALARM_CLEAR:
+ {
+ *event = OR2_OOB_EVENT_ALARM_OFF;
+ }
+ break;
+ }
return 0;
}
@@ -871,54 +1033,182 @@ static openr2_io_interface_t ftdm_r2_io_iface = {
/* .get_oob_event */ ftdm_r2_io_get_oob_event /* never called */
};
-static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span)
- //ftdm_status_t (ftdm_span_t *span, fio_signal_cb_t sig_cb, va_list ap)
+/* resolve a loglevel string, such as "debug,notice,warning", to an openr2 log level integer */
+static openr2_log_level_t ftdm_r2_loglevel_from_string(const char *level)
{
- int i = 0;
+ openr2_log_level_t tmplevel;
+ openr2_log_level_t newlevel = 0;
+ char *clevel = NULL;
+ char *logval = NULL;
+
+ logval = ftdm_malloc(strlen(level)+1); /* alloca man page scared me, so better to use good ol' malloc */
+ if (!logval) {
+ ftdm_log(FTDM_LOG_WARNING, "Ignoring R2 logging parameter: '%s', failed to alloc memory\n", level);
+ return newlevel;
+ }
+ strcpy(logval, level);
+ while (logval) {
+ clevel = strsep(&logval, ",");
+ if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
+ ftdm_log(FTDM_LOG_WARNING, "Ignoring invalid R2 logging level: '%s'\n", clevel);
+ continue;
+ }
+ newlevel |= tmplevel;
+ }
+ ftdm_safe_free(logval);
+ return newlevel;
+}
+
+static ftdm_state_map_t r2_state_map = {
+ {
+ {
+ ZSD_INBOUND,
+ ZSM_UNACCEPTABLE,
+ {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
+ {FTDM_CHANNEL_STATE_COLLECT, FTDM_END}
+ },
+ {
+ ZSD_INBOUND,
+ ZSM_UNACCEPTABLE,
+ {FTDM_CHANNEL_STATE_COLLECT, FTDM_END},
+ {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
+ },
+ {
+ ZSD_INBOUND,
+ ZSM_UNACCEPTABLE,
+ {FTDM_CHANNEL_STATE_RING, FTDM_END},
+ {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END}
+ },
+ {
+ ZSD_INBOUND,
+ ZSM_UNACCEPTABLE,
+ {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
+ {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
+ },
+ {
+ ZSD_INBOUND,
+ ZSM_UNACCEPTABLE,
+ {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
+ {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
+ },
+ {
+ ZSD_INBOUND,
+ ZSM_UNACCEPTABLE,
+ {FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
+ {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
+ },
+ {
+ ZSD_INBOUND,
+ ZSM_UNACCEPTABLE,
+ {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
+ {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_END},
+ },
+ {
+ ZSD_INBOUND,
+ ZSM_UNACCEPTABLE,
+ {FTDM_CHANNEL_STATE_UP, FTDM_END},
+ {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
+ },
+
+ /* Outbound states */
+
+ {
+ ZSD_OUTBOUND,
+ ZSM_UNACCEPTABLE,
+ {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
+ {FTDM_CHANNEL_STATE_DIALING, FTDM_END}
+ },
+
+ {
+ ZSD_OUTBOUND,
+ ZSM_UNACCEPTABLE,
+ {FTDM_CHANNEL_STATE_DIALING, FTDM_END},
+ {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}
+ },
+
+ {
+ ZSD_OUTBOUND,
+ ZSM_UNACCEPTABLE,
+ {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
+ {FTDM_CHANNEL_STATE_DOWN, FTDM_END}
+ },
+
+ {
+ ZSD_OUTBOUND,
+ ZSM_UNACCEPTABLE,
+ {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
+ {FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
+ },
+
+ {
+ ZSD_OUTBOUND,
+ ZSM_UNACCEPTABLE,
+ {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
+ {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_END}
+ },
+
+ {
+ ZSD_OUTBOUND,
+ ZSM_UNACCEPTABLE,
+ {FTDM_CHANNEL_STATE_UP, FTDM_END},
+ {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
+ },
+ }
+};
+
+static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
+{
+ unsigned int i = 0;
int conf_failure = 0;
- char *var = NULL;
- char *val = NULL;
+ int intval = 0;
+ char schedname[255];
+ const char *var = NULL, *val = NULL;
+ const char *log_level = "notice,warning,error"; /* default loglevel, if none is read from conf */
ftdm_r2_data_t *r2data = NULL;
ftdm_r2_span_pvt_t *spanpvt = NULL;
ftdm_r2_call_t *r2call = NULL;
openr2_chan_t *r2chan = NULL;
- openr2_log_level_t tmplevel;
- char *clevel = NULL;
- char *logval = NULL;
+ unsigned paramindex = 0;
ft_r2_conf_t r2conf =
{
/* .variant */ OR2_VAR_ITU,
/* .category */ OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER,
/* .loglevel */ OR2_LOG_ERROR | OR2_LOG_WARNING,
- /* .logdir */ NULL,
+#ifdef WIN32
+ /* .logdir */ (char *)"c:\\",
+#else
+ /* .logdir */ (char *)"/tmp",
+#endif
/* .advanced_protocol_file */ NULL,
/* .max_ani */ 10,
/* .max_dnis */ 4,
/* .mfback_timeout */ -1,
/* .metering_pulse_timeout */ -1,
+ /* .mf_dump_size */ 0,
/* .immediate_accept */ -1,
/* .skip_category */ -1,
/* .get_ani_first */ -1,
/* .call_files */ 0,
- /* .mf_files */ 0,
- /* .double_answer */ 0,
+ /* .double_answer */ -1,
/* .charge_calls */ -1,
/* .forced_release */ -1,
/* .allow_collect_calls */ -1
};
- assert(sig_cb != NULL);
+ ftdm_assert_return(sig_cb != NULL, FTDM_FAIL, "No signaling cb provided\n");
if (span->signal_type) {
snprintf(span->last_error, sizeof(span->last_error), "Span is already configured for signalling.");
return FTDM_FAIL;
}
- while ((var = va_arg(ap, char *))) {
+ for (; ftdm_parameters[paramindex].var; paramindex++) {
+ var = ftdm_parameters[paramindex].var;
+ val = ftdm_parameters[paramindex].val;
ftdm_log(FTDM_LOG_DEBUG, "Reading R2 parameter %s for span %d\n", var, span->span_id);
if (!strcasecmp(var, "variant")) {
- if (!(val = va_arg(ap, char *))) {
+ if (!val) {
break;
}
if (ftdm_strlen_zero_buf(val)) {
@@ -933,7 +1223,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span)
}
ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d for variant %s\n", span->span_id, val);
} else if (!strcasecmp(var, "category")) {
- if (!(val = va_arg(ap, char *))) {
+ if (!val) {
break;
}
if (ftdm_strlen_zero_buf(val)) {
@@ -948,88 +1238,80 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span)
}
ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with default category %s\n", span->span_id, val);
} else if (!strcasecmp(var, "logdir")) {
- if (!(val = va_arg(ap, char *))) {
+ if (!val) {
break;
}
if (ftdm_strlen_zero_buf(val)) {
ftdm_log(FTDM_LOG_NOTICE, "Ignoring empty R2 logdir parameter\n");
continue;
}
- r2conf.logdir = val;
+ r2conf.logdir = (char *)val;
ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with logdir %s\n", span->span_id, val);
} else if (!strcasecmp(var, "logging")) {
- if (!(val = va_arg(ap, char *))) {
+ if (!val) {
break;
}
if (ftdm_strlen_zero_buf(val)) {
ftdm_log(FTDM_LOG_NOTICE, "Ignoring empty R2 logging parameter\n");
continue;
}
- logval = ftdm_malloc(strlen(val)+1); /* alloca man page scared me, so better to use good ol' malloc */
- if (!logval) {
- ftdm_log(FTDM_LOG_WARNING, "Ignoring R2 logging parameter: '%s', failed to alloc memory\n", val);
- continue;
- }
- strcpy(logval, val);
- while (logval) {
- clevel = strsep(&logval, ",");
- if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
- ftdm_log(FTDM_LOG_WARNING, "Ignoring invalid R2 logging level: '%s'\n", clevel);
- continue;
- }
- r2conf.loglevel |= tmplevel;
- ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with loglevel %s\n", span->span_id, clevel);
- }
- ftdm_safe_free(logval);
+ log_level = val;
+ ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with loglevel %s\n", span->name, val);
} else if (!strcasecmp(var, "advanced_protocol_file")) {
- if (!(val = va_arg(ap, char *))) {
+ if (!val) {
break;
}
if (ftdm_strlen_zero_buf(val)) {
ftdm_log(FTDM_LOG_NOTICE, "Ignoring empty R2 advanced_protocol_file parameter\n");
continue;
}
- r2conf.advanced_protocol_file = val;
- ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with advanced protocol file %s\n", span->span_id, val);
+ r2conf.advanced_protocol_file = (char *)val;
+ ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with advanced protocol file %s\n", span->name, val);
+ } else if (!strcasecmp(var, "mf_dump_size")) {
+ intval = atoi(val);
+ if (intval < 0) {
+ r2conf.mf_dump_size = FTDM_IO_DUMP_DEFAULT_BUFF_SIZE;
+ ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with default mf_dump_size = %d bytes\n", span->name, r2conf.mf_dump_size);
+ } else {
+ r2conf.mf_dump_size = intval;
+ ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with mf_dump_size = %d bytes\n", span->name, r2conf.mf_dump_size);
+ }
} else if (!strcasecmp(var, "allow_collect_calls")) {
- r2conf.allow_collect_calls = va_arg(ap, int);
- ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with allow collect calls max ani = %d\n", span->span_id, r2conf.allow_collect_calls);
+ r2conf.allow_collect_calls = ftdm_true(val);
+ ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with allow collect calls max ani = %d\n", span->name, r2conf.allow_collect_calls);
} else if (!strcasecmp(var, "double_answer")) {
- r2conf.double_answer = va_arg(ap, int);
- ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with double answer = %d\n", span->span_id, r2conf.double_answer);
+ r2conf.double_answer = ftdm_true(val);
+ ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with double answer = %d\n", span->name, r2conf.double_answer);
} else if (!strcasecmp(var, "immediate_accept")) {
- r2conf.immediate_accept = va_arg(ap, int);
- ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with immediate accept = %d\n", span->span_id, r2conf.immediate_accept);
+ r2conf.immediate_accept = ftdm_true(val);
+ ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with immediate accept = %d\n", span->name, r2conf.immediate_accept);
} else if (!strcasecmp(var, "skip_category")) {
- r2conf.skip_category = va_arg(ap, int);
- ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with skip category = %d\n", span->span_id, r2conf.skip_category);
+ r2conf.skip_category = ftdm_true(val);
+ ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with skip category = %d\n", span->name, r2conf.skip_category);
} else if (!strcasecmp(var, "forced_release")) {
- r2conf.forced_release = va_arg(ap, int);
- ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with forced release = %d\n", span->span_id, r2conf.forced_release);
+ r2conf.forced_release = ftdm_true(val);
+ ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with forced release = %d\n", span->name, r2conf.forced_release);
} else if (!strcasecmp(var, "charge_calls")) {
- r2conf.charge_calls = va_arg(ap, int);
- ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with charge calls = %d\n", span->span_id, r2conf.charge_calls);
+ r2conf.charge_calls = ftdm_true(val);
+ ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with charge calls = %d\n", span->name, r2conf.charge_calls);
} else if (!strcasecmp(var, "get_ani_first")) {
- r2conf.get_ani_first = va_arg(ap, int);
- ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with get ani first = %d\n", span->span_id, r2conf.get_ani_first);
+ r2conf.get_ani_first = ftdm_true(val);
+ ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with get ani first = %d\n", span->name, r2conf.get_ani_first);
} else if (!strcasecmp(var, "call_files")) {
- r2conf.call_files = va_arg(ap, int);
- ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with call files = %d\n", span->span_id, r2conf.call_files);
- } else if (!strcasecmp(var, "mf_files")) {
- r2conf.mf_files = va_arg(ap, int);
- ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with mf files = %d\n", span->span_id, r2conf.mf_files);
+ r2conf.call_files = ftdm_true(val);
+ ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with call files = %d\n", span->name, r2conf.call_files);
} else if (!strcasecmp(var, "mfback_timeout")) {
- r2conf.mfback_timeout = va_arg(ap, int);
- ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with MF backward timeout = %dms\n", span->span_id, r2conf.mfback_timeout);
+ r2conf.mfback_timeout = atoi(val);
+ ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with MF backward timeout = %dms\n", span->name, r2conf.mfback_timeout);
} else if (!strcasecmp(var, "metering_pulse_timeout")) {
- r2conf.metering_pulse_timeout = va_arg(ap, int);
- ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with metering pulse timeout = %dms\n", span->span_id, r2conf.metering_pulse_timeout);
+ r2conf.metering_pulse_timeout = atoi(val);
+ ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with metering pulse timeout = %dms\n", span->name, r2conf.metering_pulse_timeout);
} else if (!strcasecmp(var, "max_ani")) {
- r2conf.max_ani = va_arg(ap, int);
- ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with max ani = %d\n", span->span_id, r2conf.max_ani);
+ r2conf.max_ani = atoi(val);
+ ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with max ani = %d\n", span->name, r2conf.max_ani);
} else if (!strcasecmp(var, "max_dnis")) {
- r2conf.max_dnis = va_arg(ap, int);
- ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with max dnis = %d\n", span->span_id, r2conf.max_dnis);
+ r2conf.max_dnis = atoi(val);
+ ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with max dnis = %d\n", span->name, r2conf.max_dnis);
} else {
snprintf(span->last_error, sizeof(span->last_error), "Unknown R2 parameter [%s]", var);
return FTDM_FAIL;
@@ -1041,6 +1323,10 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span)
return FTDM_FAIL;
}
+ /* set span log level */
+ r2conf.loglevel = ftdm_r2_loglevel_from_string(log_level);
+ ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with loglevel %s\n", span->span_id, log_level);
+
r2data = ftdm_malloc(sizeof(*r2data));
if (!r2data) {
snprintf(span->last_error, sizeof(span->last_error), "Failed to allocate R2 data.");
@@ -1069,10 +1355,10 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span)
openr2_context_set_double_answer(r2data->r2context, r2conf.double_answer);
openr2_context_set_immediate_accept(r2data->r2context, r2conf.immediate_accept);
- if (r2conf.logdir && r2conf.logdir[0]) {
- ftdm_log(FTDM_LOG_DEBUG, "Setting openr2 for span %s logdir to %s\n", span->name, r2conf.logdir);
- openr2_context_set_log_directory(r2data->r2context, r2conf.logdir);
- }
+ ftdm_log(FTDM_LOG_DEBUG, "Setting span %s logdir to %s\n", span->name, r2conf.logdir);
+ openr2_context_set_log_directory(r2data->r2context, r2conf.logdir);
+ snprintf(r2data->logdir, sizeof(r2data->logdir), "%s", r2conf.logdir);
+
if (r2conf.advanced_protocol_file) {
openr2_context_configure_from_advanced_file(r2data->r2context, r2conf.advanced_protocol_file);
}
@@ -1084,7 +1370,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span)
}
for (i = 1; (i <= span->chan_count) && (i <= FTDM_MAX_CHANNELS_SPAN); i++) {
- r2chan = openr2_chan_new_from_fd(r2data->r2context, span->channels[i], span->channels[i]->physical_chan_id);
+ r2chan = openr2_chan_new_from_fd(r2data->r2context, span->channels[i], span->channels[i]->chan_id);
if (!r2chan) {
snprintf(span->last_error, sizeof(span->last_error), "Cannot create all openr2 channels for span.");
goto fail;
@@ -1092,11 +1378,6 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span)
openr2_chan_set_log_level(r2chan, r2conf.loglevel);
if (r2conf.call_files) {
openr2_chan_enable_call_files(r2chan);
-#if 0
- if (r2conf.mf_files) {
- openr2_chan_enable_mf_files(r2chan);
- }
-#endif
}
r2call = ftdm_malloc(sizeof(*r2call));
@@ -1113,8 +1394,9 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span)
/* value and key are the same so just free one of them */
snprintf(r2call->name, sizeof(r2call->name), "chancall%d", i);
hashtable_insert(spanpvt->r2calls, (void *)r2call->name, r2call, HASHTABLE_FLAG_FREE_VALUE);
-
}
+ r2data->mf_dump_size = r2conf.mf_dump_size;
+ r2data->category = r2conf.category;
r2data->flags = 0;
spanpvt->r2context = r2data->r2context;
@@ -1123,13 +1405,27 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span)
span->start = ftdm_r2_start;
span->stop = ftdm_r2_stop;
- span->sig_read = ftdm_r2_sig_read;
+ span->sig_read = NULL;
+ span->sig_write = NULL;
+
+ /* let the core set the states, we just read them */
+ span->get_channel_sig_status = ftdm_r2_get_channel_sig_status;
span->signal_cb = sig_cb;
span->signal_type = FTDM_SIGTYPE_R2;
span->signal_data = r2data;
span->outgoing_call = r2_outgoing_call;
+ span->state_map = &r2_state_map;
+
+ /* use signals queue */
+ ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE);
+
+ /* setup the scheduler */
+ snprintf(schedname, sizeof(schedname), "ftmod_r2_%s", span->name);
+ ftdm_assert(ftdm_sched_create(&r2data->sched, schedname) == FTDM_SUCCESS, "Failed to create schedule!\n");
+ spanpvt->sched = r2data->sched;
+
return FTDM_SUCCESS;
fail:
@@ -1151,7 +1447,9 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan)
{
ftdm_sigmsg_t sigev;
int ret;
- openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan;
+ ftdm_r2_call_t *r2call = R2CALL(ftdmchan);
+ openr2_chan_t *r2chan = r2call->r2chan;
+ ftdm_r2_data_t *r2data = ftdmchan->span->signal_data;
memset(&sigev, 0, sizeof(sigev));
sigev.chan_id = ftdmchan->chan_id;
@@ -1160,25 +1458,27 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan)
ret = 0;
- if (R2CALL(ftdmchan)->state_ack_pending) {
- ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE);
- ftdm_channel_complete_state(ftdmchan);
- R2CALL(ftdmchan)->state_ack_pending = 0;
- }
-
- if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE) && (R2CALL(ftdmchan)->chanstate != ftdmchan->state)) {
+ /* because we do not always acknowledge the state change (clearing the FTDM_CHANNEL_STATE_CHANGE flag) due to the accept
+ * procedure described below, we need the chanstate member to NOT process some states twice, so is valid entering this
+ * function with the FTDM_CHANNEL_STATE_CHANGE flag set but with a state that was already processed and is just waiting
+ * to complete (the processing is media-bound)
+ * */
+ if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)
+ && (r2call->chanstate != ftdmchan->state)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Executing state handler for %s\n", ftdm_channel_state2str(ftdmchan->state));
- R2CALL(ftdmchan)->chanstate = ftdmchan->state;
+ r2call->chanstate = ftdmchan->state;
- if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) && !R2CALL(ftdmchan)->accepted &&
- (ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS ||
- ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA ||
- ftdmchan->state == FTDM_CHANNEL_STATE_UP) ) {
- /* if an accept ack will be required we should not acknowledge the state change just yet,
- it will be done below after processing the MF signals, otherwise we have a race condition between freetdm calling
- openr2_chan_answer_call and openr2 accepting the call first, if freetdm calls openr2_chan_answer_call before the accept cycle
- completes, openr2 will fail to answer the call */
+ if (IS_ACCEPTING_PENDING(ftdmchan)) {
+ /*
+ Moving to PROGRESS, PROGRESS_MEDIA or UP means that we must accept the call first, and accepting
+ the call in R2 means sending a tone, then waiting for the acknowledge from the other end,
+ since all of that requires sending and detecting tones, it takes a few milliseconds (I'd say around 100)
+ which means during that time the user should not try to perform any operations like answer, hangup or anything
+ else, therefore we DO NOT clear the FTDM_CHANNEL_STATE_CHANGE flag here, we rely on ftdm_io.c to block
+ the user thread until we're done with the accept (see on_call_accepted callback) and then we clear the state change flag,
+ otherwise we have a race condition between freetdm calling openr2_chan_answer_call and openr2 accepting the call first,
+ if freetdm calls openr2_chan_answer_call before the accept cycle completes, openr2 will fail to answer the call */
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "State ack for state %s will have to wait a bit\n", ftdm_channel_state2str(ftdmchan->state));
} else if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN){
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE);
@@ -1194,6 +1494,7 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan)
ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_INTERVAL, &interval);
ftdm_assert(interval != 0, "Invalid interval!");
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Starting processing of incoming call with interval %d\n", interval);
+ openr2_chan_enable_read(r2chan);
}
break;
@@ -1205,6 +1506,7 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan)
ftdm_assert(interval != 0, "Invalid interval!");
ftdm_log_chan(ftdmchan,
FTDM_LOG_DEBUG, "Starting processing of outgoing call in channel with interval %d\n", interval);
+ openr2_chan_enable_read(r2chan);
}
break;
@@ -1214,13 +1516,8 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan)
/* notify the user about the new call */
sigev.event_id = FTDM_SIGEVENT_START;
- if (ftdm_span_send_signal(ftdmchan->span, &sigev) != FTDM_SUCCESS) {
- ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Failed to handle call offered\n");
- openr2_chan_disconnect_call(r2chan, OR2_CAUSE_OUT_OF_ORDER);
- ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
- break;
- }
- R2CALL(ftdmchan)->ftdm_started = 1;
+ ftdm_span_send_signal(ftdmchan->span, &sigev);
+ r2call->ftdm_call_started = 1;
break;
@@ -1229,16 +1526,17 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan)
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
{
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
- if (!R2CALL(ftdmchan)->accepted) {
+ if (!r2call->accepted) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Accepting call\n");
ft_r2_accept_call(ftdmchan);
}
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Notifying progress\n");
+ sigev.event_id = FTDM_SIGEVENT_PROCEED;
+ ftdm_span_send_signal(ftdmchan->span, &sigev);
+
sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA;
- if (ftdm_span_send_signal(ftdmchan->span, &sigev) != FTDM_SUCCESS) {
- ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
- }
+ ftdm_span_send_signal(ftdmchan->span, &sigev);
}
}
break;
@@ -1248,60 +1546,72 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan)
{
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call was answered\n");
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
- if (!R2CALL(ftdmchan)->accepted) {
+ if (!r2call->accepted) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call has not been accepted, need to accept first\n");
// the answering will be done in the on_call_accepted handler
ft_r2_accept_call(ftdmchan);
- R2CALL(ftdmchan)->answer_pending = 1;
+ r2call->answer_pending = 1;
} else {
ft_r2_answer_call(ftdmchan);
}
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Notifying of call answered\n");
sigev.event_id = FTDM_SIGEVENT_UP;
- if (ftdm_span_send_signal(ftdmchan->span, &sigev) != FTDM_SUCCESS) {
- ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
- }
+ ftdm_span_send_signal(ftdmchan->span, &sigev);
}
}
break;
/* just got hangup */
- case FTDM_CHANNEL_STATE_HANGUP:
+ case FTDM_CHANNEL_STATE_HANGUP:
{
- openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan);
- ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Clearing call, cause = %s\n", openr2_proto_get_disconnect_string(disconnect_cause));
- openr2_chan_enable_read(r2chan);
- if (!R2CALL(ftdmchan)->disconnect_rcvd) {
+ if (!r2call->disconnect_rcvd) {
+ openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan);
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Clearing call, cause = %s\n", openr2_proto_get_disconnect_string(disconnect_cause));
/* this will disconnect the call, but need to wait for the call end before moving to DOWN */
openr2_chan_disconnect_call(r2chan, disconnect_cause);
- } else {
+ } else if (!r2call->protocol_error) {
/* just ack the hangup, on_call_end will be called by openr2 right after */
- openr2_chan_disconnect_call(r2chan, disconnect_cause);
+ openr2_chan_disconnect_call(r2chan, OR2_CAUSE_NORMAL_CLEARING);
+ } else {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Clearing call due to protocol error\n");
+ /* do not set to down yet, give some time for recovery */
+ ftdm_sched_timer(r2data->sched, "protocolerr_recover", 100,
+ ftdm_r2_recover_from_protocol_error, r2chan, &r2call->protocol_error_recovery_timer);
}
}
break;
- /* just got hangup from the freetdm side due to abnormal failure */
- case FTDM_CHANNEL_STATE_CANCEL:
+ case FTDM_CHANNEL_STATE_TERMINATING:
{
- ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Unable to receive call\n");
- openr2_chan_enable_read(r2chan);
- openr2_chan_disconnect_call(r2chan, OR2_CAUSE_OUT_OF_ORDER);
+ /* if the call has not been started yet we must go to HANGUP right here */
+ if (!r2call->ftdm_call_started) {
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
+ } else {
+ openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan);
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Clearing call, cause = %s\n", openr2_proto_get_disconnect_string(disconnect_cause));
+ /* notify the user of the call terminating and we wait for the user to move us to hangup */
+ sigev.event_id = FTDM_SIGEVENT_STOP;
+ ftdm_span_send_signal(ftdmchan->span, &sigev);
+ }
}
break;
/* finished call for good */
case FTDM_CHANNEL_STATE_DOWN:
{
- ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call is down\n");
- if (R2CALL(ftdmchan)->txdrops) {
- ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "dropped %d tx packets\n", R2CALL(ftdmchan)->txdrops);
- }
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "R2 Call is down\n");
ret = 1;
}
break;
+ /* INDICATE_RINGING doesn't apply to MFC/R2. maybe we could generate a tone */
+ case FTDM_CHANNEL_STATE_RINGING:
+ {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "RINGING indicated, ignoring it as it doesn't apply to MFC/R2\n");
+ }
+ break;
+
default:
{
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Unhandled channel state change: %s\n", ftdm_channel_state2str(ftdmchan->state));
@@ -1320,19 +1630,37 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan)
return ret;
}
+/* the channel must be locked when calling this function */
+static void ftdm_r2_state_advance_all(ftdm_channel_t *ftdmchan)
+{
+ /* because we do not always acknowledge the state change (clearing the FTDM_CHANNEL_STATE_CHANGE flag) due to the accept
+ * procedure described below, we need the chanstate member to NOT process some states twice, so is valid entering this
+ * function with the FTDM_CHANNEL_STATE_CHANGE flag set but with a state that was already processed and is just waiting
+ * to complete (the processing is media-bound)
+ * */
+ while (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)
+ && (R2CALL(ftdmchan)->chanstate != ftdmchan->state)) {
+ ftdm_r2_state_advance(ftdmchan);
+ }
+}
+
static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
{
- openr2_chan_t *r2chan;
- ftdm_r2_call_t *r2call = NULL;
+ openr2_chan_t *r2chan = NULL;
ftdm_channel_t *ftdmchan = NULL;
+ ftdm_r2_call_t *call = NULL;
ftdm_status_t status;
ftdm_span_t *span = (ftdm_span_t *) obj;
ftdm_r2_data_t *r2data = span->signal_data;
int waitms = 20;
- int i, res;
- int ms;
+ unsigned int i;
+ int res, ms;
+ int index = 0;
struct timeval start, end;
- short *poll_events = ftdm_malloc(sizeof(short)*span->chan_count);
+ ftdm_iterator_t *chaniter = NULL;
+ ftdm_iterator_t *citer = NULL;
+ uint32_t txqueue_size = 4;
+ short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count);
#ifdef __linux__
r2data->monitor_thread_id = syscall(SYS_gettid);
@@ -1340,33 +1668,63 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
ftdm_log(FTDM_LOG_DEBUG, "OpenR2 monitor thread %lu started.\n", r2data->monitor_thread_id);
r2chan = NULL;
- for (i = 1; i <= span->chan_count; i++) {
- r2chan = R2CALL(span->channels[i])->r2chan;
+ chaniter = ftdm_span_get_chan_iterator(span, NULL);
+ if (!chaniter) {
+ ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
+ goto done;
+ }
+ for (i = 1, citer = chaniter; citer; citer = ftdm_iterator_next(citer), i++) {
+ ftdmchan = ftdm_iterator_current(citer);
+ r2chan = R2CALL(ftdmchan)->r2chan;
+ openr2_chan_set_span_id(r2chan, span->span_id);
openr2_chan_set_idle(r2chan);
openr2_chan_process_cas_signaling(r2chan);
+ ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_TX_QUEUE_SIZE, &txqueue_size);
}
memset(&start, 0, sizeof(start));
memset(&end, 0, sizeof(end));
while (ftdm_running() && ftdm_test_flag(r2data, FTDM_R2_RUNNING)) {
- r2data->loops++;
res = gettimeofday(&end, NULL);
+ if (res) {
+ ftdm_log(FTDM_LOG_CRIT, "Failure gettimeofday [%s]\n", strerror(errno));
+ }
if (start.tv_sec) {
ms = ((end.tv_sec - start.tv_sec) * 1000)
+ ((( 1000000 + end.tv_usec - start.tv_usec) / 1000) - 1000);
+ if (ms < 0) {
+ ms = 0;
+ }
if (ms > r2data->jobmax) {
r2data->jobmax = ms;
}
+ index = (ms / 10);
+ index = (index > 10) ? 10 : index;
+ r2data->loops[index]++;
+ r2data->total_loops++;
}
+ /* run any span timers */
+ ftdm_sched_run(r2data->sched);
+
+ /* deliver the actual channel events to the user now without any channel locking */
+ ftdm_span_trigger_signals(span);
#ifndef WIN32
/* figure out what event to poll each channel for. POLLPRI when the channel is down,
* POLLPRI|POLLIN|POLLOUT otherwise */
memset(poll_events, 0, sizeof(short)*span->chan_count);
- for (i = 0; i < span->chan_count; i++) {
- r2chan = R2CALL(span->channels[(i+1)])->r2chan;
- ftdmchan = openr2_chan_get_client_data(r2chan);
- poll_events[i] = ftdmchan->state == FTDM_CHANNEL_STATE_DOWN ? POLLPRI : (POLLPRI | POLLIN | POLLOUT);
+ citer = ftdm_span_get_chan_iterator(span, chaniter);
+ if (!citer) {
+ ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
+ goto done;
+ }
+ for (i = 0; citer; citer = ftdm_iterator_next(citer), i++) {
+ ftdmchan = ftdm_iterator_current(citer);
+ r2chan = R2CALL(ftdmchan)->r2chan;
+ poll_events[i] = POLLPRI;
+ if (openr2_chan_get_read_enabled(r2chan)) {
+ poll_events[i] |= POLLIN;
+ }
}
status = ftdm_span_poll_event(span, waitms, poll_events);
@@ -1374,6 +1732,9 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
status = ftdm_span_poll_event(span, waitms, NULL);
#endif
+ /* run any span timers */
+ ftdm_sched_run(r2data->sched);
+
res = gettimeofday(&start, NULL);
if (res) {
ftdm_log(FTDM_LOG_CRIT, "Failure gettimeofday [%s]\n", strerror(errno));
@@ -1384,69 +1745,62 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
continue;
}
- if (FTDM_SUCCESS == status) {
- ftdm_event_t *event;
- while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) {
- if (event->enum_id == FTDM_OOB_CAS_BITS_CHANGE) {
- r2call = R2CALL(event->channel);
- r2chan = r2call->r2chan;
-
- ftdm_log(FTDM_LOG_DEBUG, "Handling CAS on channel %d.\n", openr2_chan_get_number(r2chan));
- // we only expect CAS and other OOB events on this thread/loop, once a call is started
- // the MF events (in-band signaling) are handled in the call thread
- openr2_chan_process_cas_signaling(r2chan);
- } else {
- ftdm_log(FTDM_LOG_DEBUG, "Ignoring event %d on channel %d.\n", event->enum_id, openr2_chan_get_number(r2chan));
- // XXX TODO: handle alarms here XXX
- }
- }
-
- /* XXX
- * when ftdm_span_poll_event() returns FTDM_SUCCESS, means there are events pending on the span.
- * is it possible to know on which channels those events are pending, without traversing the span?
- * XXX */
- for (i = 1; i <= span->chan_count; i++) {
- r2chan = R2CALL(span->channels[i])->r2chan;
- ftdmchan = openr2_chan_get_client_data(r2chan);
- r2call = R2CALL(ftdmchan);
-
- ftdm_mutex_lock(ftdmchan->mutex);
- ftdm_set_flag(r2call, FTDM_R2_PROCESSING);
-
- if (ftdm_r2_state_advance(ftdmchan)) {
- ftdm_clear_flag(r2call, FTDM_R2_PROCESSING);
- ftdm_mutex_unlock(ftdmchan->mutex);
- continue;
- }
-
- /* handle timeout events first if any */
- openr2_chan_run_schedule(r2chan);
-
- /* process mf tones, if any */
- if (openr2_chan_get_read_enabled(r2chan)) {
- openr2_chan_process_mf_signaling(r2chan);
- }
-
- if (ftdm_r2_state_advance(ftdmchan)) {
- ftdm_clear_flag(r2call, FTDM_R2_PROCESSING);
- ftdm_mutex_unlock(ftdmchan->mutex);
- continue;
- }
-
- ftdm_clear_flag(r2call, FTDM_R2_PROCESSING);
- ftdm_mutex_unlock(ftdmchan->mutex);
- }
- } else if (status != FTDM_TIMEOUT) {
- ftdm_log(FTDM_LOG_ERROR, "ftdm_span_poll_event returned %d.\n", status);
+ ms = ((start.tv_sec - end.tv_sec) * 1000)
+ + ((( 1000000 + start.tv_usec - end.tv_usec) / 1000) - 1000);
+ if (ms < 0) {
+ ms = 0;
+ }
+ if (ms > r2data->sleepmax) {
+ r2data->sleepmax = ms;
+ }
+ index = (ms / 15);
+ index = (index > 10) ? 10 : index;
+ r2data->sleeps[index]++;
+ r2data->total_sleeps++;
+
+ /* this main loop takes care of MF and CAS signaling during call setup and tear down
+ * for every single channel in the span, do not perform blocking operations here! */
+ citer = ftdm_span_get_chan_iterator(span, chaniter);
+ for ( ; citer; citer = ftdm_iterator_next(citer)) {
+ ftdmchan = ftdm_iterator_current(citer);
+
+ ftdm_mutex_lock(ftdmchan->mutex);
+
+ call = R2CALL(ftdmchan);
+
+ /* This let knows the core and io signaling hooks know that
+ * read/writes come from us and should be allowed */
+ ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED);
+ ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_TX_DISABLED);
+
+ ftdm_r2_state_advance_all(ftdmchan);
+
+ r2chan = call->r2chan;
+ openr2_chan_process_signaling(r2chan);
+
+ ftdm_r2_state_advance_all(ftdmchan);
+
+ if (!call->accepted) {
+ /* if the call is not accepted we do not want users reading */
+ ftdm_set_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED);
+ ftdm_set_flag(ftdmchan, FTDM_CHANNEL_TX_DISABLED);
+ }
+
+ ftdm_mutex_unlock(ftdmchan->mutex);
}
- ftdm_sleep(20);
}
- for (i = 1; i <= span->chan_count; i++) {
- r2chan = R2CALL(span->channels[i])->r2chan;
+done:
+ citer = ftdm_span_get_chan_iterator(span, chaniter);
+ for ( ; citer; citer = ftdm_iterator_next(citer)) {
+ ftdmchan = ftdm_iterator_current(citer);
+ r2chan = R2CALL(ftdmchan)->r2chan;
openr2_chan_set_blocked(r2chan);
}
+ ftdm_iterator_free(chaniter);
+ ftdm_safe_free(poll_events);
+
ftdm_clear_flag(r2data, FTDM_R2_RUNNING);
ftdm_log(FTDM_LOG_DEBUG, "R2 thread ending.\n");
@@ -1502,8 +1856,8 @@ static FIO_API_FUNCTION(ftdm_r2_api)
char *mycmd = NULL, *argv[10] = { 0 };
int argc = 0;
int span_id = 0;
- int chan_id = 0;
- int i = 0;
+ unsigned int chan_id = 0;
+ unsigned int i = 0;
ftdm_r2_data_t *r2data = NULL;
openr2_chan_t *r2chan = NULL;
openr2_context_t *r2context = NULL;
@@ -1586,7 +1940,7 @@ static FIO_API_FUNCTION(ftdm_r2_api)
goto done;
}
if (!(r2data = span->signal_data)) {
- stream->write_function(stream, "-ERR invalid span. No R2 singal data in span.\n");
+ stream->write_function(stream, "-ERR invalid span. No R2 signal data in span.\n");
goto done;
}
r2context = r2data->r2context;
@@ -1597,19 +1951,17 @@ static FIO_API_FUNCTION(ftdm_r2_api)
"Max DNIS: %d\n"
"ANI First: %s\n"
"Immediate Accept: %s\n"
- "Side: %s\n"
+ "Job Thread: %lu\n"
"Job Max ms: %d\n"
- "Job Loops: %lu\n"
- "Monitor Thread: %lu\n",
+ "Job Loops: %lu\n",
openr2_proto_get_variant_string(r2variant),
openr2_context_get_max_ani(r2context),
openr2_context_get_max_dnis(r2context),
openr2_context_get_ani_first(r2context) ? "Yes" : "No",
openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
- "no side",
+ r2data->monitor_thread_id,
r2data->jobmax,
- r2data->loops,
- r2data->monitor_thread_id);
+ r2data->total_loops);
stream->write_function(stream, "\n");
stream->write_function(stream, "%4s %-12.12s %-12.12s\n", "Channel", "Tx CAS", "Rx CAS");
for (i = 1; i <= span->chan_count; i++) {
@@ -1628,6 +1980,56 @@ static FIO_API_FUNCTION(ftdm_r2_api)
}
}
+ if (!strcasecmp(argv[0], "loopstats")) {
+ int range;
+ float pct;
+ span_id = atoi(argv[1]);
+
+ if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) {
+ if (span->start != ftdm_r2_start) {
+ stream->write_function(stream, "-ERR not an R2 span.\n");
+ goto done;
+ }
+ if (!(r2data = span->signal_data)) {
+ stream->write_function(stream, "-ERR invalid span. No R2 signal data in span.\n");
+ goto done;
+ }
+ stream->write_function(stream, "-- Working --\n");
+ stream->write_function(stream, "Total loops: %llu\n", r2data->total_loops);
+ range = 0;
+ for (i = 0; i < ftdm_array_len(r2data->loops); i++) {
+ pct = 100*(float)r2data->loops[i]/r2data->total_loops;
+ if ((i + 1) == ftdm_array_len(r2data->loops)) {
+ stream->write_function(stream, ">= %dms: %llu - %.03lf%%\n", range, r2data->loops[i], pct);
+ } else {
+ stream->write_function(stream, "%d-%dms: %llu - %.03lf%%\n", range, range + 9, r2data->loops[i], pct);
+ }
+ range += 10;
+ }
+ stream->write_function(stream, "\n");
+
+ stream->write_function(stream, "-- Sleeping --\n");
+ stream->write_function(stream, "Total sleeps: %llu\n", r2data->total_sleeps);
+ range = 0;
+ for (i = 0; i < ftdm_array_len(r2data->sleeps); i++) {
+ pct = 100*(float)r2data->sleeps[i]/r2data->total_sleeps;
+ if ((i + 1) == ftdm_array_len(r2data->sleeps)) {
+ stream->write_function(stream, ">= %dms: %llu - %.03lf%%\n", range, r2data->sleeps[i], pct);
+ } else {
+ stream->write_function(stream, "%d-%dms: %llu - %.03lf%%\n", range, range + 14, r2data->sleeps[i], pct);
+ }
+ range += 15;
+ }
+ stream->write_function(stream, "\n");
+
+ stream->write_function(stream, "+OK.\n");
+ goto done;
+ } else {
+ stream->write_function(stream, "-ERR invalid span.\n");
+ goto done;
+ }
+ }
+
}
if (argc == 1) {
@@ -1709,6 +2111,7 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_r2_destroy)
spanpvt = val;
openr2_context_delete(spanpvt->r2context);
hashtable_destroy(spanpvt->r2calls);
+ ftdm_sched_destroy(&spanpvt->sched);
}
}
hashtable_destroy(g_mod_data_hash);
@@ -1717,12 +2120,13 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_r2_destroy)
}
EX_DECLARE_DATA ftdm_module_t ftdm_module = {
- "r2",
- ftdm_r2_io_init,
- NULL,
- ftdm_r2_init,
- ftdm_r2_configure_span,
- ftdm_r2_destroy
+ /* .name */ "r2",
+ /* .io_load */ ftdm_r2_io_init,
+ /* .io_unload */ NULL,
+ /* .sig_load */ ftdm_r2_init,
+ /* .sig_configure */ NULL,
+ /* .sig_unload */ ftdm_r2_destroy,
+ /* .configure_span_signaling */ ftdm_r2_configure_span_signaling
};
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftdm_sangoma_boost.h b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftdm_sangoma_boost.h
index 5a3ca76c56..6fbf272d07 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftdm_sangoma_boost.h
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftdm_sangoma_boost.h
@@ -58,7 +58,7 @@ typedef struct ftdm_sangoma_boost_trunkgroup {
ftdm_size_t size; /* Number of b-channels in group */
unsigned int last_used_index; /* index of last b-channel used */
ftdm_channel_t* ftdmchans[MAX_CHANS_PER_TRUNKGROUP];
- //DAVIDY need to merge congestion timeouts to this struct
+ //TODO need to merge congestion timeouts to this struct
} ftdm_sangoma_boost_trunkgroup_t;
#endif
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2008.vcproj b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2008.vcproj
index e7fc1d6549..73e421818f 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2008.vcproj
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2008.vcproj
@@ -95,83 +95,6 @@
Name="VCPostBuildEventTool"
/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj
new file mode 100644
index 0000000000..78689c36db
--- /dev/null
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj
@@ -0,0 +1,206 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ ftmod_sangoma_boost
+ {D021EF2A-460D-4827-A0F7-41FDECF46F1B}
+ ftmod_sangoma_boost
+ Win32Proj
+
+
+
+ DynamicLibrary
+ Unicode
+ true
+
+
+ DynamicLibrary
+ Unicode
+
+
+ DynamicLibrary
+ Unicode
+ true
+
+
+ DynamicLibrary
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ $(SolutionDir)$(Configuration)\
+ $(Configuration)\
+ true
+ $(SolutionDir)$(Configuration)\
+ $(Configuration)\
+ false
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ false
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+
+
+
+ Disabled
+ ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_SANGOMA_BOOST_EXPORTS;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level4
+ true
+ EditAndContinue
+ 4100;%(DisableSpecificWarnings)
+
+
+ freetdm.lib;%(AdditionalDependencies)
+ $(OutDir);%(AdditionalLibraryDirectories)
+ true
+ Windows
+ MachineX86
+
+
+
+
+ MaxSpeed
+ true
+ ..\..\include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_SANGOMA_BOOST_EXPORTS;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ true
+
+
+ Level4
+ true
+ ProgramDatabase
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Windows
+ true
+ true
+ MachineX86
+
+
+
+
+ X64
+
+
+ Disabled
+ ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_SANGOMA_BOOST_EXPORTS;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level4
+ true
+ ProgramDatabase
+ 4100;%(DisableSpecificWarnings)
+
+
+ freetdm.lib;%(AdditionalDependencies)
+ $(OutDir);%(AdditionalLibraryDirectories)
+ true
+ Windows
+ MachineX64
+
+
+
+
+ X64
+
+
+ MaxSpeed
+ true
+ ..\..\include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_SANGOMA_BOOST_EXPORTS;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ true
+
+
+ Level4
+ false
+ ProgramDatabase
+ 4100;%(DisableSpecificWarnings)
+
+
+ true
+ Windows
+ true
+ true
+ MachineX64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {93b8812c-3ec4-4f78-8970-ffbfc99e167d}
+ false
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj.filters
new file mode 100644
index 0000000000..2aeed155cd
--- /dev/null
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj.filters
@@ -0,0 +1,35 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c
index a975204b62..50a01cc0ec 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c
@@ -55,7 +55,7 @@ ftdm_mutex_t *g_boost_modules_mutex = NULL;
ftdm_hash_t *g_boost_modules_hash = NULL;
#define MAX_TRUNK_GROUPS 64
-//DAVIDY need to merge congestion_timeouts with ftdm_sangoma_boost_trunkgroups
+//TODO need to merge congestion_timeouts with ftdm_sangoma_boost_trunkgroups
static time_t congestion_timeouts[MAX_TRUNK_GROUPS];
static ftdm_sangoma_boost_trunkgroup_t *g_trunkgroups[MAX_TRUNK_GROUPS];
@@ -1557,11 +1557,11 @@ static __inline__ ftdm_status_t state_advance(ftdm_channel_t *ftdmchan)
ftdm_set_string(event.calling_name, ftdmchan->caller_data.cid_name);
ftdm_set_string(event.rdnis.digits, ftdmchan->caller_data.rdnis.digits);
if (strlen(ftdmchan->caller_data.rdnis.digits)) {
- event.rdnis.digits_count = (uint8_t)strlen(ftdmchan->caller_data.rdnis.digits)+1;
- event.rdnis.ton = ftdmchan->caller_data.rdnis.type;
- event.rdnis.npi = ftdmchan->caller_data.rdnis.plan;
+ event.rdnis.digits_count = (uint8_t)strlen(ftdmchan->caller_data.rdnis.digits)+1;
+ event.rdnis.ton = ftdmchan->caller_data.rdnis.type;
+ event.rdnis.npi = ftdmchan->caller_data.rdnis.plan;
}
-
+
event.calling.screening_ind = ftdmchan->caller_data.screen;
event.calling.presentation_ind = ftdmchan->caller_data.pres;
@@ -2582,17 +2582,17 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_boost_configure_span)
} else if (!strcasecmp(var, "remote_port")) {
remote_port = atoi(val);
} else if (!strcasecmp(var, "outbound-called-ton")) {
- ftdm_span_set_ton(val, &span->default_caller_data.dnis.type);
+ ftdm_set_ton(val, &span->default_caller_data.dnis.type);
} else if (!strcasecmp(var, "outbound-called-npi")) {
- ftdm_span_set_npi(val, &span->default_caller_data.dnis.plan);
+ ftdm_set_npi(val, &span->default_caller_data.dnis.plan);
} else if (!strcasecmp(var, "outbound-calling-ton")) {
- ftdm_span_set_ton(val, &span->default_caller_data.cid_num.type);
+ ftdm_set_ton(val, &span->default_caller_data.cid_num.type);
} else if (!strcasecmp(var, "outbound-calling-npi")) {
- ftdm_span_set_npi(val, &span->default_caller_data.cid_num.plan);
+ ftdm_set_npi(val, &span->default_caller_data.cid_num.plan);
} else if (!strcasecmp(var, "outbound-rdnis-ton")) {
- ftdm_span_set_ton(val, &span->default_caller_data.rdnis.type);
+ ftdm_set_ton(val, &span->default_caller_data.rdnis.type);
} else if (!strcasecmp(var, "outbound-rdnis-npi")) {
- ftdm_span_set_npi(val, &span->default_caller_data.rdnis.plan);
+ ftdm_set_npi(val, &span->default_caller_data.rdnis.plan);
} else if (!sigmod) {
snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var);
FAIL_CONFIG_RETURN(FTDM_FAIL);
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj
new file mode 100644
index 0000000000..b0a51786f5
--- /dev/null
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj
@@ -0,0 +1,194 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ ftmod_sangoma_isdn
+ {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}
+ ftmod_sangoma_isdn
+ Win32Proj
+
+
+
+ DynamicLibrary
+ true
+
+
+ DynamicLibrary
+ true
+
+
+ DynamicLibrary
+
+
+ DynamicLibrary
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ true
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ $(Configuration)\
+ true
+ true
+ AllRules.ruleset
+ AllRules.ruleset
+
+
+
+
+ AllRules.ruleset
+ AllRules.ruleset
+
+
+
+
+
+
+
+ Disabled
+ C:\Program Files\libsng_isdn\include;C:\Program Files\libsng_isdn\include\sng_isdn;../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ EnableFastChecks
+
+
+ Level3
+ EditAndContinue
+
+
+ freetdm.lib;libsng_isdn.lib;%(AdditionalDependencies)
+ $(OutDir);C:\Program Files\libsng_isdn\lib;C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories)
+ true
+ Console
+ false
+
+
+ MachineX86
+
+
+
+
+ Disabled
+ C:\Program Files\libsng_isdn\include;C:\Program Files\libsng_isdn\include\sng_isdn;../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+
+
+ EnableFastChecks
+
+
+ Level3
+ ProgramDatabase
+
+
+ freetdm.lib;libsng_isdn.lib;%(AdditionalDependencies)
+ $(OutDir);C:\Program Files\libsng_isdn\lib;C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories)
+ true
+ Console
+ false
+
+
+
+
+
+
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level3
+ ProgramDatabase
+
+
+ true
+ Windows
+ true
+ true
+ MachineX86
+
+
+
+
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level3
+ ProgramDatabase
+
+
+ true
+ Windows
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {93b8812c-3ec4-4f78-8970-ffbfc99e167d}
+ false
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj.filters
new file mode 100644
index 0000000000..5f592fa9ef
--- /dev/null
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj.filters
@@ -0,0 +1,57 @@
+
+
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
\ No newline at end of file
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 583d5c1729..e20d3ae7e0 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
@@ -40,22 +40,24 @@
#include
#endif
-static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj);
+static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj);
static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span);
static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span);
ftdm_channel_t* ftdm_sangoma_isdn_process_event_states(ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event);
static void ftdm_sangoma_isdn_advance_chan_states(ftdm_channel_t *ftdmchan);
static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span);
-
+static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_event_t event);
static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan);
static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event);
+static void ftdm_sangoma_isdn_wakeup_phy(ftdm_channel_t *dchan);
+static void ftdm_sangoma_isdn_dchan_set_queue_size(ftdm_channel_t *ftdmchan);
-static ftdm_io_interface_t g_sngisdn_io_interface;
-static sng_isdn_event_interface_t g_sngisdn_event_interface;
+static ftdm_io_interface_t g_sngisdn_io_interface;
+static sng_isdn_event_interface_t g_sngisdn_event_interface;
-ftdm_sngisdn_data_t g_sngisdn_data;
+ftdm_sngisdn_data_t g_sngisdn_data;
ftdm_state_map_t sangoma_isdn_state_map = {
{
@@ -113,7 +115,20 @@ ftdm_state_map_t sangoma_isdn_state_map = {
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_RING, FTDM_END},
- {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_END}
+ {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_END}
+ },
+ {
+ ZSD_INBOUND,
+ ZSM_UNACCEPTABLE,
+ {FTDM_CHANNEL_STATE_PROCEED, FTDM_END},
+ {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA,
+ FTDM_CHANNEL_STATE_UP, FTDM_END}
+ },
+ {
+ ZSD_INBOUND,
+ ZSM_UNACCEPTABLE,
+ {FTDM_CHANNEL_STATE_RINGING, FTDM_END},
+ {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
},
{
ZSD_INBOUND,
@@ -187,9 +202,17 @@ ftdm_state_map_t sangoma_isdn_state_map = {
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_DIALING, FTDM_END},
- {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS,
- FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_DOWN, FTDM_END}
+ {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
+ FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP,
+ FTDM_CHANNEL_STATE_DOWN, FTDM_END}
},
+ {
+ ZSD_OUTBOUND,
+ ZSM_UNACCEPTABLE,
+ {FTDM_CHANNEL_STATE_PROCEED, FTDM_END},
+ {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
+ FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
+ },
{
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
@@ -236,39 +259,51 @@ static __inline__ void ftdm_sangoma_isdn_advance_chan_states(ftdm_channel_t *ftd
}
}
+static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_event_t event)
+{
+ sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
+ sngisdn_snd_event(signal_data->dchan, event);
+
+ switch (event) {
+ /* Check if the span woke up from power-saving mode */
+ case FTDM_OOB_ALARM_CLEAR:
+ if (FTDM_SPAN_IS_BRI(span)) {
+ ftdm_channel_t *ftdmchan;
+ sngisdn_chan_data_t *sngisdn_info;
+ ftdm_iterator_t *chaniter = NULL;
+ ftdm_iterator_t *curr = NULL;
+
+ chaniter = ftdm_span_get_chan_iterator(span, NULL);
+ for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
+ ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
+ sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data;
+
+ if (ftdm_test_flag(sngisdn_info, FLAG_ACTIVATING)) {
+ ftdm_clear_flag(sngisdn_info, FLAG_ACTIVATING);
+
+ ftdm_sched_timer(signal_data->sched, "delayed_setup", 1000, sngisdn_delayed_setup, (void*) ftdmchan->call_data, NULL);
+ }
+ }
+ ftdm_iterator_free(chaniter);
+ }
+ break;
+ default:
+ /* Ignore other events for now */
+ break;
+ }
+}
+
static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span)
{
- ftdm_status_t ret_status;
- ftdm_channel_t *ftdmchan;
- ftdm_iterator_t *chaniter = NULL;
- ftdm_iterator_t *curr = NULL;
-
+ ftdm_status_t ret_status;
+
ret_status = ftdm_span_poll_event(span, 0, NULL);
switch(ret_status) {
case FTDM_SUCCESS:
{
ftdm_event_t *event;
while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) {
-
- if (FTDM_SPAN_IS_BRI(span)) {
- switch (event->enum_id) {
- /* Check if the span woke up from power-saving mode */
- case FTDM_OOB_ALARM_CLEAR:
- {
- chaniter = ftdm_span_get_chan_iterator(span, NULL);
- for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
- ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
- sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
-
- if (ftdm_test_flag(sngisdn_info, FLAG_ACTIVATING)) {
- ftdm_clear_flag(sngisdn_info, FLAG_ACTIVATING);
- sngisdn_snd_setup((ftdm_channel_t*)ftdmchan);
- }
- }
- ftdm_iterator_free(chaniter);
- }
- }
- }
+ ftdm_sangoma_isdn_process_phy_events(span, event->enum_id);
}
}
break;
@@ -280,9 +315,83 @@ static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span)
}
}
+static void ftdm_sangoma_isdn_dchan_set_queue_size(ftdm_channel_t *dchan)
+{
+ ftdm_status_t ret_status;
+ uint32_t queue_size;
+
+ queue_size = SNGISDN_DCHAN_QUEUE_LEN;
+ ret_status = ftdm_channel_command(dchan, FTDM_COMMAND_SET_RX_QUEUE_SIZE, &queue_size);
+ ftdm_assert(ret_status == FTDM_SUCCESS, "Failed to set Rx Queue size");
+
+ queue_size = SNGISDN_DCHAN_QUEUE_LEN;
+ ret_status = ftdm_channel_command(dchan, FTDM_COMMAND_SET_TX_QUEUE_SIZE, &queue_size);
+ ftdm_assert(ret_status == FTDM_SUCCESS, "Failed to set Tx Queue size");
+
+ RETVOID;
+}
+
+static void ftdm_sangoma_isdn_wakeup_phy(ftdm_channel_t *dchan)
+{
+ ftdm_status_t ret_status;
+ ftdm_channel_hw_link_status_t status = FTDM_HW_LINK_CONNECTED;
+ ret_status = ftdm_channel_command(dchan, FTDM_COMMAND_SET_LINK_STATUS, &status);
+ if (ret_status != FTDM_SUCCESS) {
+ ftdm_log_chan_msg(dchan, FTDM_LOG_WARNING, "Failed to wake-up link\n");
+ }
+ return;
+}
+
+static void *ftdm_sangoma_isdn_dchan_run(ftdm_thread_t *me, void *obj)
+{
+ uint8_t data[1000];
+ ftdm_status_t status = FTDM_SUCCESS;
+ ftdm_wait_flag_t wflags = FTDM_READ;
+ ftdm_span_t *span = (ftdm_span_t*) obj;
+ ftdm_channel_t *dchan = ((sngisdn_span_data_t*)span->signal_data)->dchan;
+ ftdm_size_t len = 0;
+
+ ftdm_channel_set_feature(dchan, FTDM_CHANNEL_FEATURE_IO_STATS);
+ ftdm_sangoma_isdn_dchan_set_queue_size(dchan);
+
+ ftdm_assert(dchan, "Span does not have a dchannel");
+ ftdm_channel_open_chan(dchan);
+
+ while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) {
+ wflags = FTDM_READ;
+ status = ftdm_channel_wait(dchan, &wflags, 10000);
+ switch(status) {
+ case FTDM_FAIL:
+ ftdm_log_chan_msg(dchan, FTDM_LOG_CRIT, "Failed to wait for d-channel\n");
+ break;
+ case FTDM_TIMEOUT:
+ break;
+ case FTDM_SUCCESS:
+ if ((wflags & FTDM_READ)) {
+ len = 1000;
+ status = ftdm_channel_read(dchan, data, &len);
+ if (status == FTDM_SUCCESS) {
+ sngisdn_snd_data(dchan, data, len);
+ } else {
+ ftdm_log_chan_msg(dchan, FTDM_LOG_WARNING, "Failed to read from channel \n");
+ }
+#ifndef WIN32 /* It is valid on WIN32 for poll to return without errors, but no flags set */
+ } else {
+ ftdm_log_chan_msg(dchan, FTDM_LOG_CRIT, "Failed to poll for d-channel\n");
+#endif
+ }
+ break;
+ default:
+ ftdm_log_chan_msg(dchan, FTDM_LOG_CRIT, "Unhandled IO event\n");
+ }
+ }
+ ftdm_channel_close(&dchan);
+ return NULL;
+}
+
static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
{
- ftdm_interrupt_t *ftdm_sangoma_isdn_int[2];
+ ftdm_interrupt_t *ftdm_sangoma_isdn_int[3];
ftdm_status_t ret_status;
ftdm_span_t *span = (ftdm_span_t *) obj;
ftdm_channel_t *ftdmchan = NULL;
@@ -300,8 +409,13 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a ftdm_interrupt for span = %s!\n", span->name);
goto ftdm_sangoma_isdn_run_exit;
}
+
+ if (ftdm_queue_get_interrupt(span->pendingsignals, &ftdm_sangoma_isdn_int[1]) != FTDM_SUCCESS) {
+ ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a signal interrupt for span = %s!\n", span->name);
+ goto ftdm_sangoma_isdn_run_exit;
+ }
- if (ftdm_queue_get_interrupt(signal_data->event_queue, &ftdm_sangoma_isdn_int[1]) != FTDM_SUCCESS) {
+ if (ftdm_queue_get_interrupt(signal_data->event_queue, &ftdm_sangoma_isdn_int[2]) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a event interrupt for span = %s!\n", span->name);
goto ftdm_sangoma_isdn_run_exit;
}
@@ -310,8 +424,14 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
/* Check if there are any timers to process */
ftdm_sched_run(signal_data->sched);
+ ftdm_span_trigger_signals(span);
- ret_status = ftdm_interrupt_multiple_wait(ftdm_sangoma_isdn_int, 2, sleep);
+ if (ftdm_sched_get_time_to_next_timer(signal_data->sched, &sleep) == FTDM_SUCCESS) {
+ if (sleep < 0 || sleep > SNGISDN_EVENT_POLL_RATE) {
+ sleep = SNGISDN_EVENT_POLL_RATE;
+ }
+ }
+ ret_status = ftdm_interrupt_multiple_wait(ftdm_sangoma_isdn_int, 3, sleep);
/* find out why we returned from the interrupt queue */
switch (ret_status) {
case FTDM_SUCCESS: /* there was a state change on the span */
@@ -327,7 +447,6 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
ftdm_sangoma_isdn_process_stack_event(span, sngisdn_event);
ftdm_safe_free(sngisdn_event);
}
- ftdm_span_trigger_signals(span);
break;
case FTDM_TIMEOUT:
/* twiddle */
@@ -343,12 +462,6 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
/* Poll for events, e.g HW DTMF */
ftdm_sangoma_isdn_poll_events(span);
-
- if (ftdm_sched_get_time_to_next_timer(signal_data->sched, &sleep) == FTDM_SUCCESS) {
- if (sleep < 0 || sleep > SNGISDN_EVENT_POLL_RATE) {
- sleep = SNGISDN_EVENT_POLL_RATE;
- }
- }
}
/* clear the IN_THREAD flag so that we know the thread is done */
@@ -512,13 +625,18 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
break;
case FTDM_CHANNEL_STATE_GET_CALLERID:
{
- sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
- sngisdn_snd_proceed(ftdmchan);
+ 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);
+ }
/* Wait in this state until we get FACILITY msg */
}
break;
case FTDM_CHANNEL_STATE_RING: /* incoming call request */
- {
+ {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending incoming call from %s to %s to FTDM core\n", ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.dnis.digits);
/* we have enough information to inform FTDM of the call*/
@@ -535,14 +653,37 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Requesting Line activation\n");
- sngisdn_set_flag(sngisdn_info, FLAG_ACTIVATING);
- sng_isdn_wake_up_phy(ftdmchan->span);
+ sngisdn_set_flag(sngisdn_info, FLAG_ACTIVATING);
+ ftdm_sangoma_isdn_wakeup_phy(ftdmchan);
ftdm_sched_timer(signal_data->sched, "timer_t3", signal_data->timer_t3*1000, sngisdn_t3_timeout, (void*) sngisdn_info, NULL);
} else {
sngisdn_snd_setup(ftdmchan);
}
}
break;
+ case FTDM_CHANNEL_STATE_PROCEED:
+ {
+ if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
+ /*OUTBOUND...so we were told by the line of this so noifiy the user*/
+ sigev.event_id = FTDM_SIGEVENT_PROCEED;
+ ftdm_span_send_signal(ftdmchan->span, &sigev);
+ } else {
+ 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);
+ }
+ }
+ }
+ break;
+ case FTDM_CHANNEL_STATE_RINGING:
+ {
+ ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
+ sngisdn_snd_alert(ftdmchan, prog_ind);
+ }
+ break;
case FTDM_CHANNEL_STATE_PROGRESS:
{
/*check if the channel is inbound or outbound*/
@@ -550,9 +691,13 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
/*OUTBOUND...so we were told by the line of this so noifiy the user*/
sigev.event_id = FTDM_SIGEVENT_PROGRESS;
ftdm_span_send_signal(ftdmchan->span, &sigev);
- } else if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
- sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
- sngisdn_snd_proceed(ftdmchan);
+ } else {
+ /* If we already sent a PROCEED before, do not send a PROGRESS as there is nothing to indicate to the remote switch */
+ if (ftdmchan->last_state != FTDM_CHANNEL_STATE_PROCEED) {
+ /* Send a progress message, indicating: Call is not end-to-end ISDN, further call progress may be available */
+ ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
+ sngisdn_snd_progress(ftdmchan, prog_ind);
+ }
}
}
break;
@@ -562,7 +707,9 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA;
ftdm_span_send_signal(ftdmchan->span, &sigev);
} else {
- sngisdn_snd_progress(ftdmchan);
+ /* Send a progress message, indicating: In-band information/pattern available */
+ ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_IB_AVAIL};
+ sngisdn_snd_progress(ftdmchan, prog_ind);
}
}
break;
@@ -633,7 +780,7 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
sngisdn_snd_release(ftdmchan, 0);
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
- sng_isdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
+ sngisdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
}
} else {
sngisdn_snd_disconnect(ftdmchan);
@@ -658,9 +805,7 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
break;
case FTDM_CHANNEL_STATE_DOWN: /* the call is finished and removed */
{
- uint8_t glare = 0;
-
- glare = sngisdn_test_flag(sngisdn_info, FLAG_GLARE);
+ uint8_t glare = sngisdn_test_flag(sngisdn_info, FLAG_GLARE);
/* clear all of the call specific data store in the channel structure */
clear_call_data(sngisdn_info);
@@ -712,6 +857,26 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
return;
}
+static FIO_CHANNEL_SEND_MSG_FUNCTION(ftdm_sangoma_isdn_send_msg)
+{
+ ftdm_status_t status = FTDM_FAIL;
+
+ switch (sigmsg->event_id) {
+ case FTDM_SIGEVENT_RESTART:
+ /* TODO: Send a channel restart here */
+ /* Implement me */
+ break;
+ case FTDM_SIGEVENT_FACILITY:
+ sngisdn_snd_fac_req(ftdmchan);
+ break;
+ default:
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Unsupported signalling msg requested\n");
+ status = FTDM_BREAK;
+ }
+ ftdm_call_clear_data(&ftdmchan->caller_data);
+ return status;
+}
+
static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_isdn_outgoing_call)
{
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
@@ -788,7 +953,7 @@ static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_set_span_sig_status)
static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
{
ftdm_log(FTDM_LOG_INFO,"Starting span %s:%u.\n",span->name,span->span_id);
- if (sng_isdn_stack_start(span) != FTDM_SUCCESS) {
+ if (sngisdn_stack_start(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed to start span %s\n", span->name);
return FTDM_FAIL;
}
@@ -802,6 +967,12 @@ static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
return FTDM_FAIL;
}
+ /*start the dchan monitor thread*/
+ if (ftdm_thread_create_detached(ftdm_sangoma_isdn_dchan_run, span) != FTDM_SUCCESS) {
+ ftdm_log(FTDM_LOG_CRIT,"Failed to start Sangoma ISDN d-channel Monitor Thread!\n");
+ return FTDM_FAIL;
+ }
+
ftdm_log(FTDM_LOG_DEBUG,"Finished starting span %s\n", span->name);
return FTDM_SUCCESS;
}
@@ -823,7 +994,7 @@ static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span)
ftdm_sleep(10);
}
- if (sng_isdn_stack_stop(span) != FTDM_SUCCESS) {
+ if (sngisdn_stack_stop(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed to stop span %s\n", span->name);
}
@@ -875,7 +1046,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
return FTDM_FAIL;
}
- if (sng_isdn_stack_cfg(span) != FTDM_SUCCESS) {
+ if (sngisdn_stack_cfg(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Sangoma ISDN Stack configuration failed\n");
return FTDM_FAIL;
}
@@ -885,6 +1056,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
span->stop = ftdm_sangoma_isdn_stop;
span->signal_type = FTDM_SIGTYPE_ISDN;
span->outgoing_call = ftdm_sangoma_isdn_outgoing_call;
+ span->send_msg = ftdm_sangoma_isdn_send_msg;
span->channel_request = NULL;
span->signal_cb = sig_cb;
span->get_channel_sig_status = ftdm_sangoma_isdn_get_chan_sig_status;
@@ -894,11 +1066,13 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
span->state_map = &sangoma_isdn_state_map;
ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE);
ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE);
+ ftdm_set_flag(span, FTDM_SPAN_USE_PROCEED_STATE);
+ ftdm_set_flag(span, FTDM_SPAN_USE_SKIP_STATES);
if (span->trunk_type == FTDM_TRUNK_BRI_PTMP ||
span->trunk_type == FTDM_TRUNK_BRI) {
- sng_isdn_set_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING);
+ sngisdn_set_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING);
}
/* Initialize scheduling context */
@@ -917,7 +1091,7 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init)
ftdm_log(FTDM_LOG_INFO, "Loading ftmod_sangoma_isdn...\n");
memset(&g_sngisdn_data, 0, sizeof(g_sngisdn_data));
-
+ memset(&g_sngisdn_event_interface, 0, sizeof(g_sngisdn_event_interface));
/* set callbacks */
g_sngisdn_event_interface.cc.sng_con_ind = sngisdn_rcv_con_ind;
g_sngisdn_event_interface.cc.sng_con_cfm = sngisdn_rcv_con_cfm;
@@ -946,8 +1120,11 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init)
g_sngisdn_event_interface.sta.sng_q921_trc_ind = sngisdn_rcv_q921_trace;
g_sngisdn_event_interface.sta.sng_q931_sta_ind = sngisdn_rcv_q931_ind;
g_sngisdn_event_interface.sta.sng_q931_trc_ind = sngisdn_rcv_q931_trace;
- g_sngisdn_event_interface.sta.sng_cc_sta_ind = sngisdn_rcv_cc_ind;
+ g_sngisdn_event_interface.sta.sng_cc_sta_ind = sngisdn_rcv_cc_ind;
+ g_sngisdn_event_interface.io.sng_l1_data_req = sngisdn_rcv_l1_data_req;
+ g_sngisdn_event_interface.io.sng_l1_cmd_req = sngisdn_rcv_l1_cmd_req;
+
for(i=1;i<=MAX_VARIANTS;i++) {
ftdm_mutex_create(&g_sngisdn_data.ccs[i].mutex);
}
@@ -1008,11 +1185,11 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
goto done;
}
if (!strcasecmp(trace_opt, "q921")) {
- sng_isdn_activate_trace(span, SNGISDN_TRACE_Q921);
+ sngisdn_activate_trace(span, SNGISDN_TRACE_Q921);
} else if (!strcasecmp(trace_opt, "q931")) {
- sng_isdn_activate_trace(span, SNGISDN_TRACE_Q931);
+ sngisdn_activate_trace(span, SNGISDN_TRACE_Q931);
} else if (!strcasecmp(trace_opt, "disable")) {
- sng_isdn_activate_trace(span, SNGISDN_TRACE_DISABLE);
+ sngisdn_activate_trace(span, SNGISDN_TRACE_DISABLE);
} else {
stream->write_function(stream, "-ERR invalid trace option \n");
}
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
index 2a65a82985..f15eff9200 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
@@ -60,9 +60,37 @@
#define SNGISDN_EVENT_QUEUE_SIZE 100
#define SNGISDN_EVENT_POLL_RATE 100
#define SNGISDN_NUM_LOCAL_NUMBERS 8
+#define SNGISDN_DCHAN_QUEUE_LEN 200
/* TODO: rename all *_cc_* to *_an_* */
+#define SNGISDN_ENUM_NAMES(_NAME, _STRINGS) static const char * _NAME [] = { _STRINGS , NULL };
+#define SNGISDN_STR2ENUM_P(_FUNC1, _FUNC2, _TYPE) _TYPE _FUNC1 (const char *name); const char * _FUNC2 (_TYPE type);
+#define SNGISDN_STR2ENUM(_FUNC1, _FUNC2, _TYPE, _STRINGS, _MAX) \
+ _TYPE _FUNC1 (const char *name) \
+{ \
+ int i; \
+ _TYPE t = _MAX ; \
+ \
+ for (i = 0; i < _MAX ; i++) { \
+ if (!strcasecmp(name, _STRINGS[i])) { \
+ t = (_TYPE) i; \
+ break; \
+} \
+} \
+ \
+ return t; \
+} \
+ const char * _FUNC2 (_TYPE type) \
+{ \
+ if (type > _MAX) { \
+ type = _MAX; \
+} \
+ return _STRINGS[(int)type]; \
+} \
+
+
+
typedef enum {
FLAG_RESET_RX = (1 << 0),
FLAG_RESET_TX = (1 << 1),
@@ -74,7 +102,8 @@ typedef enum {
FLAG_DELAYED_REL = (1 << 7),
FLAG_SENT_PROCEED = (1 << 8),
FLAG_SEND_DISC = (1 << 9),
- FLAG_ACTIVATING = (1 << 10), /* Used for BRI only, flag is set after we request line CONNECTED */
+ /* Used for BRI only, flag is set after we request line CONNECTED */
+ FLAG_ACTIVATING = (1 << 10),
} sngisdn_flag_t;
@@ -134,6 +163,51 @@ typedef enum {
SNGISDN_EVENT_RST_IND,
} ftdm_sngisdn_event_id_t;
+typedef enum {
+ /* Call is not end-to-end ISDN */
+ SNGISDN_PROGIND_DESCR_NETE_ISDN,
+ /* Destination address is non-ISDN */
+ SNGISDN_PROGIND_DESCR_DEST_NISDN,
+ /* Origination address is non-ISDN */
+ SNGISDN_PROGIND_DESCR_ORIG_NISDN,
+ /* Call has returned to the ISDN */
+ SNGISDN_PROGIND_DESCR_RET_ISDN,
+ /* Interworking as occured and has resulted in a telecommunication service change */
+ SNGISDN_PROGIND_DESCR_SERV_CHANGE,
+ /* In-band information or an appropriate pattern is now available */
+ SNGISDN_PROGIND_DESCR_IB_AVAIL,
+ /* Invalid */
+ SNGISDN_PROGIND_DESCR_INVALID,
+} ftdm_sngisdn_progind_descr_t;
+#define SNGISDN_PROGIND_DESCR_STRINGS "not-end-to-end-isdn", "destination-is-non-isdn", "origination-is-non-isdn", "call-returned-to-isdn", "service-change", "inband-info-available", "invalid"
+SNGISDN_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr2str, ftdm_sngisdn_progind_descr_t);
+
+typedef enum {
+ /* User */
+ SNGISDN_PROGIND_LOC_USER,
+ /* Private network serving the local user */
+ SNGISDN_PROGIND_LOC_PRIV_NET_LOCAL_USR,
+ /* Public network serving the local user */
+ SNGISDN_PROGIND_LOC_PUB_NET_LOCAL_USR,
+ /* Transit network */
+ SNGISDN_PROGIND_LOC_TRANSIT_NET,
+ /* Public network serving remote user */
+ SNGISDN_PROGIND_LOC_PUB_NET_REMOTE_USR,
+ /* Private network serving remote user */
+ SNGISDN_PROGIND_LOC_PRIV_NET_REMOTE_USR,
+ /* Network beyond the interworking point */
+ SNGISDN_PROGIND_LOC_NET_BEYOND_INTRW,
+ /* Invalid */
+ SNGISDN_PROGIND_LOC_INVALID,
+} ftdm_sngisdn_progind_loc_t;
+#define SNGISDN_PROGIND_LOC_STRINGS "user", "private-net-local-user", "public-net-local-user", "transit-network", "public-net-remote-user", "private-net-remote-user", "beyond-interworking", "invalid"
+SNGISDN_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t);
+
+typedef struct ftdm_sngisdn_prog_ind {
+ ftdm_sngisdn_progind_loc_t loc; /* location */
+ ftdm_sngisdn_progind_descr_t descr; /* description */
+} ftdm_sngisdn_progind_t;
+
/* Only timers that can be cancelled are listed here */
#define SNGISDN_NUM_TIMERS 1
/* Increase NUM_TIMERS as number of ftdm_sngisdn_timer_t increases */
@@ -168,6 +242,7 @@ typedef struct sngisdn_chan_data {
/* Span specific data */
typedef struct sngisdn_span_data {
ftdm_span_t *ftdm_span;
+ ftdm_channel_t *dchan;
uint8_t link_id;
uint8_t switchtype;
uint8_t signalling; /* SNGISDN_SIGNALING_CPE or SNGISDN_SIGNALING_NET */
@@ -179,10 +254,13 @@ typedef struct sngisdn_span_data {
uint8_t trace_flags; /* TODO: change to flags, so we can use ftdm_test_flag etc.. */
uint8_t overlap_dial;
uint8_t setup_arb;
+ uint8_t facility_ie_decode;
uint8_t facility;
int8_t facility_timeout;
uint8_t num_local_numbers;
+ uint8_t ignore_cause_value;
uint8_t timer_t3;
+ uint8_t restart_opt;
char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS];
ftdm_sched_t *sched;
ftdm_queue_t *event_queue;
@@ -268,60 +346,58 @@ extern ftdm_sngisdn_data_t g_sngisdn_data;
ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *span);
/* Support functions */
-FT_DECLARE(uint32_t) get_unique_suInstId(int16_t cc_id);
-FT_DECLARE(void) clear_call_data(sngisdn_chan_data_t *sngisdn_info);
-FT_DECLARE(void) clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info);
+uint32_t get_unique_suInstId(int16_t cc_id);
+void clear_call_data(sngisdn_chan_data_t *sngisdn_info);
+void clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info);
+ftdm_status_t get_ftdmchan_by_suInstId(int16_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data);
+ftdm_status_t get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data);
+
+
+ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail);
+ftdm_status_t sngisdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt);
void stack_hdr_init(Header *hdr);
void stack_pst_init(Pst *pst);
-FT_DECLARE(ftdm_status_t) get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data);
-FT_DECLARE(ftdm_status_t) get_ftdmchan_by_suInstId(int16_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data);
-FT_DECLARE(ftdm_status_t) sng_isdn_set_avail_rate(ftdm_span_t *ftdmspan, sngisdn_avail_t avail);
-
-FT_DECLARE(ftdm_status_t) cpy_calling_num_from_stack(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb);
-FT_DECLARE(ftdm_status_t) cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb);
-FT_DECLARE(ftdm_status_t) cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb);
-FT_DECLARE(ftdm_status_t) cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *display);
-
-FT_DECLARE(ftdm_status_t) cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm);
-FT_DECLARE(ftdm_status_t) cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm);
-FT_DECLARE(ftdm_status_t) cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm);
-FT_DECLARE(ftdm_status_t) cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan);
-
/* Outbound Call Control functions */
void sngisdn_snd_setup(ftdm_channel_t *ftdmchan);
void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan);
-void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan);
-void sngisdn_snd_progress(ftdm_channel_t *ftdmchan);
-void sngisdn_snd_alert(ftdm_channel_t *ftdmchan);
+void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
+void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
+void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
void sngisdn_snd_connect(ftdm_channel_t *ftdmchan);
void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan);
void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare);
void sngisdn_snd_reset(ftdm_channel_t *ftdmchan);
void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan);
+void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan);
void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan);
void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan);
+void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len);
+void sngisdn_snd_event(ftdm_channel_t *dchan, ftdm_oob_event_t event);
/* Inbound Call Control functions */
-void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces);
-void sngisdn_rcv_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, int16_t dChan, uint8_t ces);
-void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, int16_t dChan, uint8_t ces);
-void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt);
-void sngisdn_rcv_rel_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt);
-void sngisdn_rcv_dat_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, InfoEvnt *infoEvnt);
-void sngisdn_rcv_sshl_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action);
-void sngisdn_rcv_sshl_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action);
-void sngisdn_rcv_rmrt_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action);
-void sngisdn_rcv_rmrt_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action);
-void sngisdn_rcv_flc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt);
-void sngisdn_rcv_fac_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, FacEvnt *facEvnt, uint8_t evntType, int16_t dChan, uint8_t ces);
-void sngisdn_rcv_sta_cfm ( int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt);
-void sngisdn_rcv_srv_ind ( int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces);
-void sngisdn_rcv_srv_cfm ( int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces);
-void sngisdn_rcv_rst_cfm ( int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType);
-void sngisdn_rcv_rst_ind ( int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType);
+void sngisdn_rcv_con_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces);
+void sngisdn_rcv_con_cfm(int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, int16_t dChan, uint8_t ces);
+void sngisdn_rcv_cnst_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, int16_t dChan, uint8_t ces);
+void sngisdn_rcv_disc_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt);
+void sngisdn_rcv_rel_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt);
+void sngisdn_rcv_dat_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, InfoEvnt *infoEvnt);
+void sngisdn_rcv_sshl_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action);
+void sngisdn_rcv_sshl_cfm(int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action);
+void sngisdn_rcv_rmrt_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action);
+void sngisdn_rcv_rmrt_cfm(int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action);
+void sngisdn_rcv_flc_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt);
+void sngisdn_rcv_fac_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, FacEvnt *facEvnt, uint8_t evntType, int16_t dChan, uint8_t ces);
+void sngisdn_rcv_sta_cfm(int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt);
+void sngisdn_rcv_srv_ind(int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces);
+void sngisdn_rcv_srv_cfm(int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces);
+void sngisdn_rcv_rst_cfm(int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType);
+void sngisdn_rcv_rst_ind(int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType);
+int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_l1_frame_t *l1_frame);
+int16_t sngisdn_rcv_l1_cmd_req(uint16_t spId, sng_l1_cmd_t *l1_cmd);
+
void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event);
void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event);
@@ -359,6 +435,28 @@ void sngisdn_rcv_cc_ind(CcMngmt *status);
void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...);
void sngisdn_rcv_sng_assert(char *message);
+ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
+ftdm_status_t get_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
+ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb);
+ftdm_status_t get_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb);
+ftdm_status_t get_calling_name_from_display(ftdm_channel_t *ftdmchan, Display *display);
+ftdm_status_t get_calling_name_from_usr_usr(ftdm_channel_t *ftdmchan, UsrUsr *usrUsr);
+ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad);
+ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd);
+ftdm_status_t get_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr);
+ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t data_len);
+
+ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
+ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
+ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb);
+ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb);
+ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt);
+ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad);
+ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind);
+ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr);
+ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t *data_len);
+
+
uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability);
uint8_t sngisdn_get_usrInfoLyr1Prot_from_stack(ftdm_user_layer1_prot_t layer1_prot);
ftdm_bearer_cap_t sngisdn_get_infoTranCap_from_user(uint8_t bearer_capability);
@@ -385,6 +483,7 @@ static __inline__ void sngisdn_set_flag(sngisdn_chan_data_t *sngisdn_info, sngis
void handle_sng_log(uint8_t level, char *fmt,...);
void sngisdn_set_span_sig_status(ftdm_span_t *ftdmspan, ftdm_signaling_status_t status);
+void sngisdn_delayed_setup(void* p_sngisdn_info);
void sngisdn_delayed_release(void* p_sngisdn_info);
void sngisdn_delayed_connect(void* p_sngisdn_info);
void sngisdn_delayed_disconnect(void* p_sngisdn_info);
@@ -392,10 +491,10 @@ void sngisdn_facility_timeout(void* p_sngisdn_info);
void sngisdn_t3_timeout(void* p_sngisdn_info);
/* Stack management functions */
-ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span);
-ftdm_status_t sng_isdn_stack_start(ftdm_span_t *span);
-ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span);
-ftdm_status_t sng_isdn_wake_up_phy(ftdm_span_t *span);
+ftdm_status_t sngisdn_stack_cfg(ftdm_span_t *span);
+ftdm_status_t sngisdn_stack_start(ftdm_span_t *span);
+ftdm_status_t sngisdn_stack_stop(ftdm_span_t *span);
+ftdm_status_t sngisdn_wake_up_phy(ftdm_span_t *span);
void sngisdn_print_phy_stats(ftdm_stream_handle_t *stream, ftdm_span_t *span);
void sngisdn_print_spans(ftdm_stream_handle_t *stream);
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 18ca9c38dd..cce10cc1dd 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
@@ -34,13 +34,24 @@
#include "ftmod_sangoma_isdn.h"
-ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span);
-ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span);
-ftdm_status_t add_local_number(const char* val, ftdm_span_t *span);
+static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span);
+static ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span);
+static ftdm_status_t add_local_number(const char* val, ftdm_span_t *span);
+static ftdm_status_t parse_yesno(const char* var, const char* val, uint8_t *target);
extern ftdm_sngisdn_data_t g_sngisdn_data;
-ftdm_status_t add_local_number(const char* val, ftdm_span_t *span)
+static ftdm_status_t parse_yesno(const char* var, const char* val, uint8_t *target)
+{
+ if (ftdm_true(val)) {
+ *target = SNGISDN_OPT_TRUE;
+ } else {
+ *target = SNGISDN_OPT_FALSE;
+ }
+ return FTDM_SUCCESS;
+}
+
+static ftdm_status_t add_local_number(const char* val, ftdm_span_t *span)
{
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
@@ -53,12 +64,14 @@ ftdm_status_t add_local_number(const char* val, ftdm_span_t *span)
return FTDM_SUCCESS;
}
-ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span)
+static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span)
{
unsigned i;
-
+ ftdm_iterator_t *chaniter = NULL;
+ ftdm_iterator_t *curr = NULL;
sngisdn_dchan_data_t *dchan_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
+
switch(span->trunk_type) {
case FTDM_TRUNK_T1:
if (!strcasecmp(switch_name, "ni2") ||
@@ -124,9 +137,9 @@ ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span)
/* add this span to its ent_cc */
signal_data->cc_id = i;
- /* create a new dchan */ /* for NFAS - no-dchan on b-channels only links */
+ /* create a new dchan */ /* for NFAS - no-dchan on b-channels-only links */
g_sngisdn_data.num_dchan++;
- signal_data->dchan_id = g_sngisdn_data.num_dchan;
+ signal_data->dchan_id = g_sngisdn_data.num_dchan;
dchan_data = &g_sngisdn_data.dchans[signal_data->dchan_id];
dchan_data->num_spans++;
@@ -138,20 +151,27 @@ ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span)
ftdm_log(FTDM_LOG_DEBUG, "%s: cc_id:%d dchan_id:%d span_id:%d\n", span->name, signal_data->cc_id, signal_data->dchan_id, signal_data->span_id);
- /* Add the channels to the span */
- for (i=1;i<=span->chan_count;i++) {
- unsigned chan_id;
- ftdm_channel_t *ftdmchan = span->channels[i];
- /* NFAS is not supported on E1, so span_id will always be 1 for E1 so this will work for E1 as well */
- chan_id = ((signal_data->span_id-1)*NUM_T1_CHANNELS_PER_SPAN)+ftdmchan->physical_chan_id;
- dchan_data->channels[chan_id] = (sngisdn_chan_data_t*)ftdmchan->call_data;
- dchan_data->num_chans++;
+
+ chaniter = ftdm_span_get_chan_iterator(span, NULL);
+ for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
+ int32_t chan_id;
+ ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
+ if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) {
+ /* set the d-channel */
+ signal_data->dchan = ftdmchan;
+ } else {
+ /* Add the channels to the span */
+ /* NFAS is not supported on E1, so span_id will always be 1 for E1 so this will work for E1 as well */
+ chan_id = ((signal_data->span_id-1)*NUM_T1_CHANNELS_PER_SPAN)+ftdmchan->physical_chan_id;
+ dchan_data->channels[chan_id] = (sngisdn_chan_data_t*)ftdmchan->call_data;
+ dchan_data->num_chans++;
+ }
}
-
+ ftdm_iterator_free(chaniter);
return FTDM_SUCCESS;
}
-ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span)
+static ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span)
{
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
if (!strcasecmp(signalling, "net") ||
@@ -181,7 +201,10 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
signal_data->min_digits = 8;
signal_data->overlap_dial = SNGISDN_OPT_DEFAULT;
signal_data->setup_arb = SNGISDN_OPT_DEFAULT;
+ signal_data->facility_ie_decode = SNGISDN_OPT_DEFAULT;
+ signal_data->ignore_cause_value = SNGISDN_OPT_DEFAULT;
signal_data->timer_t3 = 8;
+ signal_data->restart_opt = SNGISDN_OPT_DEFAULT;
signal_data->link_id = span->span_id;
span->default_caller_data.bearer_capability = IN_ITC_SPEECH;
@@ -192,20 +215,19 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
if (span->trunk_type == FTDM_TRUNK_BRI ||
span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
-
- ftdm_span_set_npi("unknown", &span->default_caller_data.dnis.plan);
- ftdm_span_set_ton("unknown", &span->default_caller_data.dnis.type);
- ftdm_span_set_npi("unknown", &span->default_caller_data.cid_num.plan);
- ftdm_span_set_ton("unknown", &span->default_caller_data.cid_num.type);
- ftdm_span_set_npi("unknown", &span->default_caller_data.rdnis.plan);
- ftdm_span_set_ton("unknown", &span->default_caller_data.rdnis.type);
+ ftdm_set_npi("unknown", &span->default_caller_data.dnis.plan);
+ ftdm_set_ton("unknown", &span->default_caller_data.dnis.type);
+ ftdm_set_npi("unknown", &span->default_caller_data.cid_num.plan);
+ ftdm_set_ton("unknown", &span->default_caller_data.cid_num.type);
+ ftdm_set_npi("unknown", &span->default_caller_data.rdnis.plan);
+ ftdm_set_ton("unknown", &span->default_caller_data.rdnis.type);
} else {
- ftdm_span_set_npi("e164", &span->default_caller_data.dnis.plan);
- ftdm_span_set_ton("national", &span->default_caller_data.dnis.type);
- ftdm_span_set_npi("e164", &span->default_caller_data.cid_num.plan);
- ftdm_span_set_ton("national", &span->default_caller_data.cid_num.type);
- ftdm_span_set_npi("e164", &span->default_caller_data.rdnis.plan);
- ftdm_span_set_ton("national", &span->default_caller_data.rdnis.type);
+ ftdm_set_npi("isdn", &span->default_caller_data.dnis.plan);
+ ftdm_set_ton("national", &span->default_caller_data.dnis.type);
+ ftdm_set_npi("isdn", &span->default_caller_data.cid_num.plan);
+ ftdm_set_ton("national", &span->default_caller_data.cid_num.type);
+ ftdm_set_npi("isdn", &span->default_caller_data.rdnis.plan);
+ ftdm_set_ton("national", &span->default_caller_data.rdnis.type);
}
for (paramindex = 0; ftdm_parameters[paramindex].var; paramindex++) {
@@ -237,40 +259,30 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
} else {
ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val);
}
- } else if (!strcasecmp(var, "setup arbitration")) {
- if (!strcasecmp(val, "yes")) {
- signal_data->setup_arb = SNGISDN_OPT_TRUE;
- } else if (!strcasecmp(val, "no")) {
- signal_data->setup_arb = SNGISDN_OPT_FALSE;
- } else {
- ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val);
- }
+ } else if (!strcasecmp(var, "setup-arbitration")) {
+ parse_yesno(var, val, &signal_data->setup_arb);
} else if (!strcasecmp(var, "facility")) {
- if (!strcasecmp(val, "yes")) {
- signal_data->facility = SNGISDN_OPT_TRUE;
- } else if (!strcasecmp(val, "no")) {
- signal_data->facility = SNGISDN_OPT_FALSE;
- } else {
- ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val);
- }
+ parse_yesno(var, val, &signal_data->facility);
} else if (!strcasecmp(var, "min_digits")) {
signal_data->min_digits = atoi(val);
} else if (!strcasecmp(var, "outbound-called-ton")) {
- ftdm_span_set_ton(val, &span->default_caller_data.dnis.type);
+ ftdm_set_ton(val, &span->default_caller_data.dnis.type);
} else if (!strcasecmp(var, "outbound-called-npi")) {
- ftdm_span_set_npi(val, &span->default_caller_data.dnis.plan);
+ ftdm_set_npi(val, &span->default_caller_data.dnis.plan);
} else if (!strcasecmp(var, "outbound-calling-ton")) {
- ftdm_span_set_ton(val, &span->default_caller_data.cid_num.type);
+ ftdm_set_ton(val, &span->default_caller_data.cid_num.type);
} else if (!strcasecmp(var, "outbound-calling-npi")) {
- ftdm_span_set_npi(val, &span->default_caller_data.cid_num.plan);
+ ftdm_set_npi(val, &span->default_caller_data.cid_num.plan);
} else if (!strcasecmp(var, "outbound-rdnis-ton")) {
- ftdm_span_set_ton(val, &span->default_caller_data.rdnis.type);
+ ftdm_set_ton(val, &span->default_caller_data.rdnis.type);
} else if (!strcasecmp(var, "outbound-rdnis-npi")) {
- ftdm_span_set_npi(val, &span->default_caller_data.rdnis.plan);
+ ftdm_set_npi(val, &span->default_caller_data.rdnis.plan);
} else if (!strcasecmp(var, "outbound-bearer_cap")) {
- ftdm_span_set_bearer_capability(val, &span->default_caller_data.bearer_capability);
+ ftdm_set_bearer_capability(val, (uint8_t*)&span->default_caller_data.bearer_capability);
} else if (!strcasecmp(var, "outbound-bearer_layer1")) {
- ftdm_span_set_bearer_layer1(val, &span->default_caller_data.bearer_layer1);
+ ftdm_set_bearer_layer1(val, (uint8_t*)&span->default_caller_data.bearer_layer1);
+ } else if (!strcasecmp(var, "channel-restart-on-link-up")) {
+ parse_yesno(var, val, &signal_data->restart_opt);
} else if (!strcasecmp(var, "local-number")) {
if (add_local_number(val, span) != FTDM_SUCCESS) {
return FTDM_FAIL;
@@ -280,6 +292,10 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
if (signal_data->facility_timeout < 0) {
signal_data->facility_timeout = 0;
}
+ } else if (!strcasecmp(var, "facility-ie-decode")) {
+ parse_yesno(var, val, &signal_data->facility_ie_decode);
+ } else if (!strcasecmp(var, "ignore-cause-value")) {
+ parse_yesno(var, val, &signal_data->ignore_cause_value);
} else {
ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var);
}
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 bb46fb7fba..de10a9fac0 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
@@ -38,52 +38,52 @@ extern ftdm_sngisdn_data_t g_sngisdn_data;
uint8_t sng_isdn_stack_switchtype(sngisdn_switchtype_t switchtype);
-ftdm_status_t sng_isdn_cfg_phy(ftdm_span_t *span);
-ftdm_status_t sng_isdn_cfg_q921(ftdm_span_t *span);
-ftdm_status_t sng_isdn_cfg_q931(ftdm_span_t *span);
-ftdm_status_t sng_isdn_cfg_cc(ftdm_span_t *span);
+ftdm_status_t sngisdn_cfg_phy(ftdm_span_t *span);
+ftdm_status_t sngisdn_cfg_q921(ftdm_span_t *span);
+ftdm_status_t sngisdn_cfg_q931(ftdm_span_t *span);
+ftdm_status_t sngisdn_cfg_cc(ftdm_span_t *span);
-ftdm_status_t sng_isdn_stack_cfg_phy_gen(void);
-ftdm_status_t sng_isdn_stack_cfg_q921_gen(void);
-ftdm_status_t sng_isdn_stack_cfg_q931_gen(void);
-ftdm_status_t sng_isdn_stack_cfg_cc_gen(void);
+ftdm_status_t sngisdn_stack_cfg_phy_gen(void);
+ftdm_status_t sngisdn_stack_cfg_q921_gen(void);
+ftdm_status_t sngisdn_stack_cfg_q931_gen(void);
+ftdm_status_t sngisdn_stack_cfg_cc_gen(void);
-ftdm_status_t sng_isdn_stack_cfg_phy_psap(ftdm_span_t *span);
-ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span);
-ftdm_status_t sng_isdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t management);
-ftdm_status_t sng_isdn_stack_cfg_q931_tsap(ftdm_span_t *span);
-ftdm_status_t sng_isdn_stack_cfg_q931_dlsap(ftdm_span_t *span);
-ftdm_status_t sng_isdn_stack_cfg_q931_lce(ftdm_span_t *span);
+ftdm_status_t sngisdn_stack_cfg_phy_psap(ftdm_span_t *span);
+ftdm_status_t sngisdn_stack_cfg_q921_msap(ftdm_span_t *span);
+ftdm_status_t sngisdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t management);
+ftdm_status_t sngisdn_stack_cfg_q931_tsap(ftdm_span_t *span);
+ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span);
+ftdm_status_t sngisdn_stack_cfg_q931_lce(ftdm_span_t *span);
-ftdm_status_t sng_isdn_stack_cfg_cc_sap(ftdm_span_t *span);
+ftdm_status_t sngisdn_stack_cfg_cc_sap(ftdm_span_t *span);
-ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span)
+ftdm_status_t sngisdn_stack_cfg(ftdm_span_t *span)
{
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
if (!g_sngisdn_data.gen_config_done) {
g_sngisdn_data.gen_config_done = 1;
ftdm_log(FTDM_LOG_DEBUG, "Starting general stack configuration\n");
- if(sng_isdn_stack_cfg_phy_gen()!= FTDM_SUCCESS) {
+ if(sngisdn_stack_cfg_phy_gen()!= FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed general physical configuration\n");
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_DEBUG, "General stack physical done\n");
- if(sng_isdn_stack_cfg_q921_gen()!= FTDM_SUCCESS) {
+ if(sngisdn_stack_cfg_q921_gen()!= FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed general q921 configuration\n");
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_DEBUG, "General stack q921 done\n");
- if(sng_isdn_stack_cfg_q931_gen()!= FTDM_SUCCESS) {
+ if(sngisdn_stack_cfg_q931_gen()!= FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed general q921 configuration\n");
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_DEBUG, "General stack q931 done\n");
- if(sng_isdn_stack_cfg_cc_gen()!= FTDM_SUCCESS) {
+ if(sngisdn_stack_cfg_cc_gen()!= FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed general CC configuration\n");
return FTDM_FAIL;
}
@@ -92,26 +92,26 @@ ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span)
}
/* TODO: for NFAS, should only call these function for spans with d-chans */
- if (sng_isdn_stack_cfg_phy_psap(span) != FTDM_SUCCESS) {
+ if (sngisdn_stack_cfg_phy_psap(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "%s:phy_psap configuration failed\n", span->name);
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_DEBUG, "%s:phy_psap configuration done\n", span->name);
- if (sng_isdn_stack_cfg_q921_msap(span) != FTDM_SUCCESS) {
+ if (sngisdn_stack_cfg_q921_msap(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "%s:q921_msap configuration failed\n", span->name);
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_DEBUG, "%s:q921_msap configuration done\n", span->name);
- if (sng_isdn_stack_cfg_q921_dlsap(span, 0) != FTDM_SUCCESS) {
+ if (sngisdn_stack_cfg_q921_dlsap(span, 0) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "%s:q921_dlsap configuration failed\n", span->name);
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_DEBUG, "%s:q921_dlsap configuration done\n", span->name);
if (span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
- if (sng_isdn_stack_cfg_q921_dlsap(span, 1) != FTDM_SUCCESS) {
+ if (sngisdn_stack_cfg_q921_dlsap(span, 1) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "%s:q921_dlsap management configuration failed\n", span->name);
return FTDM_FAIL;
}
@@ -119,13 +119,13 @@ ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span)
}
- if (sng_isdn_stack_cfg_q931_dlsap(span) != FTDM_SUCCESS) {
+ if (sngisdn_stack_cfg_q931_dlsap(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "%s:q931_dlsap configuration failed\n", span->name);
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_DEBUG, "%s:q931_dlsap configuration done\n", span->name);
- if (sng_isdn_stack_cfg_q931_lce(span) != FTDM_SUCCESS) {
+ if (sngisdn_stack_cfg_q931_lce(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "%s:q931_lce configuration failed\n", span->name);
return FTDM_FAIL;
}
@@ -134,13 +134,13 @@ ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span)
if (!g_sngisdn_data.ccs[signal_data->cc_id].config_done) {
g_sngisdn_data.ccs[signal_data->cc_id].config_done = 1;
/* if BRI, need to configure dlsap_mgmt */
- if (sng_isdn_stack_cfg_q931_tsap(span) != FTDM_SUCCESS) {
+ if (sngisdn_stack_cfg_q931_tsap(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "%s:q931_tsap configuration failed\n", span->name);
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_DEBUG, "%s:q931_tsap configuration done\n", span->name);
- if (sng_isdn_stack_cfg_cc_sap(span) != FTDM_SUCCESS) {
+ if (sngisdn_stack_cfg_cc_sap(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "%s:cc_sap configuration failed\n", span->name);
return FTDM_FAIL;
}
@@ -153,37 +153,37 @@ ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span)
-ftdm_status_t sng_isdn_stack_cfg_phy_gen(void)
+ftdm_status_t sngisdn_stack_cfg_phy_gen(void)
{
/*local variables*/
- L1Mngmt cfg; /*configuration structure*/
- Pst pst; /*post structure*/
+ L1Mngmt cfg; /*configuration structure*/
+ Pst pst; /*post structure*/
- /* initalize the post structure */
- stack_pst_init(&pst);
+ /* initalize the post structure */
+ stack_pst_init(&pst);
- /* insert the destination Entity */
- pst.dstEnt = ENTL1;
+ /* insert the destination Entity */
+ pst.dstEnt = ENTL1;
- /*clear the configuration structure*/
+ /*clear the configuration structure*/
memset(&cfg, 0, sizeof(cfg));
- /*fill in some general sections of the header*/
- stack_hdr_init(&cfg.hdr);
+ /*fill in some general sections of the header*/
+ stack_hdr_init(&cfg.hdr);
- /*fill in the specific fields of the header*/
- cfg.hdr.msgType = TCFG;
- cfg.hdr.entId.ent = ENTL1;
- cfg.hdr.entId.inst = S_INST;
- cfg.hdr.elmId.elmnt = STGEN;
+ /*fill in the specific fields of the header*/
+ cfg.hdr.msgType = TCFG;
+ cfg.hdr.entId.ent = ENTL1;
+ cfg.hdr.entId.inst = S_INST;
+ cfg.hdr.elmId.elmnt = STGEN;
- stack_pst_init(&cfg.t.cfg.s.l1Gen.sm );
- cfg.t.cfg.s.l1Gen.sm.srcEnt = ENTL1;
- cfg.t.cfg.s.l1Gen.sm.dstEnt = ENTSM;
+ stack_pst_init(&cfg.t.cfg.s.l1Gen.sm );
+ cfg.t.cfg.s.l1Gen.sm.srcEnt = ENTL1;
+ cfg.t.cfg.s.l1Gen.sm.dstEnt = ENTSM;
- cfg.t.cfg.s.l1Gen.nmbLnks = MAX_L1_LINKS+1;
- cfg.t.cfg.s.l1Gen.poolTrUpper = POOL_UP_TR; /* upper pool threshold */
- cfg.t.cfg.s.l1Gen.poolTrLower = POOL_LW_TR; /* lower pool threshold */
+ cfg.t.cfg.s.l1Gen.nmbLnks = MAX_L1_LINKS;
+ cfg.t.cfg.s.l1Gen.poolTrUpper = POOL_UP_TR; /* upper pool threshold */
+ cfg.t.cfg.s.l1Gen.poolTrLower = POOL_LW_TR; /* lower pool threshold */
if (sng_isdn_phy_config(&pst, &cfg)) {
return FTDM_FAIL;
@@ -191,55 +191,40 @@ ftdm_status_t sng_isdn_stack_cfg_phy_gen(void)
return FTDM_SUCCESS;
}
-ftdm_status_t sng_isdn_stack_cfg_phy_psap(ftdm_span_t *span)
-{
- ftdm_iterator_t *chaniter;
- ftdm_iterator_t *curr;
- L1Mngmt cfg;
- Pst pst;
+ftdm_status_t sngisdn_stack_cfg_phy_psap(ftdm_span_t *span)
+{
+ L1Mngmt cfg;
+ Pst pst;
- int32_t d_channel_fd = -1;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
- /* initalize the post structure */
- stack_pst_init(&pst);
+ /* initalize the post structure */
+ stack_pst_init(&pst);
- /* insert the destination Entity */
- pst.dstEnt = ENTL1;
+ /* insert the destination Entity */
+ pst.dstEnt = ENTL1;
- /*clear the configuration structure*/
+ /*clear the configuration structure*/
memset(&cfg, 0, sizeof(cfg));
- /*fill in some general sections of the header*/
- stack_hdr_init(&cfg.hdr);
+ /*fill in some general sections of the header*/
+ stack_hdr_init(&cfg.hdr);
- /*fill in the specific fields of the header*/
- cfg.hdr.msgType = TCFG;
- cfg.hdr.entId.ent = ENTL1;
- cfg.hdr.entId.inst = S_INST;
- cfg.hdr.elmId.elmnt = STPSAP;
+ /*fill in the specific fields of the header*/
+ cfg.hdr.msgType = TCFG;
+ cfg.hdr.entId.ent = ENTL1;
+ cfg.hdr.entId.inst = S_INST;
+ cfg.hdr.elmId.elmnt = STPSAP;
cfg.hdr.elmId.elmntInst1 = signal_data->link_id;
-
- /* Find the d-channel */
- chaniter = ftdm_span_get_chan_iterator(span, NULL);
- for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
- ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
- if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) {
- d_channel_fd = (int32_t)ftdmchan->sockfd;
- break;
- }
- }
- ftdm_iterator_free(chaniter);
-
- if(d_channel_fd < 0) {
+ if (!signal_data->dchan) {
ftdm_log(FTDM_LOG_ERROR, "%s:No d-channels specified\n", span->name);
return FTDM_FAIL;
}
-
- cfg.t.cfg.s.l1PSAP.sockfd = d_channel_fd;
-
+
+ cfg.t.cfg.s.l1PSAP.sockfd = (int32_t)signal_data->dchan->sockfd;
+
switch(span->trunk_type) {
case FTDM_TRUNK_E1:
cfg.t.cfg.s.l1PSAP.type = SNG_L1_TYPE_PRI;
@@ -255,8 +240,8 @@ ftdm_status_t sng_isdn_stack_cfg_phy_psap(ftdm_span_t *span)
default:
ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported trunk type %d\n", span->name, span->trunk_type);
return FTDM_FAIL;
- }
- cfg.t.cfg.s.l1PSAP.spId = signal_data->link_id;
+ }
+ cfg.t.cfg.s.l1PSAP.spId = signal_data->link_id;
if (sng_isdn_phy_config(&pst, &cfg)) {
return FTDM_FAIL;
@@ -265,28 +250,28 @@ ftdm_status_t sng_isdn_stack_cfg_phy_psap(ftdm_span_t *span)
}
-ftdm_status_t sng_isdn_stack_cfg_q921_gen(void)
+ftdm_status_t sngisdn_stack_cfg_q921_gen(void)
{
BdMngmt cfg;
- Pst pst;
+ Pst pst;
- /* initalize the post structure */
- stack_pst_init(&pst);
+ /* initalize the post structure */
+ stack_pst_init(&pst);
/* insert the destination Entity */
- pst.dstEnt = ENTLD;
+ pst.dstEnt = ENTLD;
- /*clear the configuration structure*/
- memset(&cfg, 0, sizeof(cfg));
+ /*clear the configuration structure*/
+ memset(&cfg, 0, sizeof(cfg));
/*fill in some general sections of the header*/
- stack_hdr_init(&cfg.hdr);
-
- cfg.hdr.msgType = TCFG;
- cfg.hdr.entId.ent = ENTLD;
- cfg.hdr.entId.inst = S_INST;
- cfg.hdr.elmId.elmnt = STGEN;
- /* fill in the Gen Conf structures internal pst struct */
+ stack_hdr_init(&cfg.hdr);
- stack_pst_init(&cfg.t.cfg.s.bdGen.sm);
+ cfg.hdr.msgType = TCFG;
+ cfg.hdr.entId.ent = ENTLD;
+ cfg.hdr.entId.inst = S_INST;
+ cfg.hdr.elmId.elmnt = STGEN;
+ /* fill in the Gen Conf structures internal pst struct */
+
+ stack_pst_init(&cfg.t.cfg.s.bdGen.sm);
cfg.t.cfg.s.bdGen.sm.dstEnt = ENTSM; /* entity */
@@ -299,8 +284,8 @@ ftdm_status_t sng_isdn_stack_cfg_q921_gen(void)
#ifdef LAPD_3_4
cfg.t.cfg.s.bdGen.timeRes = 100; /* timer resolution = 1 sec */
#endif
- cfg.t.cfg.s.bdGen.poolTrUpper = 2; /* upper pool threshold */
- cfg.t.cfg.s.bdGen.poolTrLower = 1; /* lower pool threshold */
+ cfg.t.cfg.s.bdGen.poolTrUpper = 2; /* upper pool threshold */
+ cfg.t.cfg.s.bdGen.poolTrLower = 1; /* lower pool threshold */
if (sng_isdn_q921_config(&pst, &cfg)) {
return FTDM_FAIL;
@@ -308,30 +293,30 @@ ftdm_status_t sng_isdn_stack_cfg_q921_gen(void)
return FTDM_SUCCESS;
}
-ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span)
+ftdm_status_t sngisdn_stack_cfg_q921_msap(ftdm_span_t *span)
{
BdMngmt cfg;
- Pst pst;
+ Pst pst;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
- /* initalize the post structure */
- stack_pst_init(&pst);
+ /* initalize the post structure */
+ stack_pst_init(&pst);
/* insert the destination Entity */
- pst.dstEnt = ENTLD;
+ pst.dstEnt = ENTLD;
- /*clear the configuration structure*/
- memset(&cfg, 0, sizeof(cfg));
+ /*clear the configuration structure*/
+ memset(&cfg, 0, sizeof(cfg));
/*fill in some general sections of the header*/
- stack_hdr_init(&cfg.hdr);
+ stack_hdr_init(&cfg.hdr);
cfg.hdr.msgType = TCFG;
- cfg.hdr.entId.ent = ENTLD;
- cfg.hdr.entId.inst = S_INST;
- cfg.hdr.elmId.elmnt = STMSAP;
+ cfg.hdr.entId.ent = ENTLD;
+ cfg.hdr.entId.inst = S_INST;
+ cfg.hdr.elmId.elmnt = STMSAP;
cfg.t.cfg.s.bdMSAP.lnkNmb = signal_data->link_id;
-
+
cfg.t.cfg.s.bdMSAP.maxOutsFrms = 24; /* MAC window */
cfg.t.cfg.s.bdMSAP.tQUpperTrs = 32; /* Tx Queue Upper Threshold */
cfg.t.cfg.s.bdMSAP.tQLowerTrs = 24; /* Tx Queue Lower Threshold */
@@ -343,7 +328,7 @@ ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span)
cfg.t.cfg.s.bdMSAP.route = RTESPEC; /* Route */
cfg.t.cfg.s.bdMSAP.dstProcId = SFndProcId(); /* destination proc id */
cfg.t.cfg.s.bdMSAP.dstEnt = ENTL1; /* entity */
- cfg.t.cfg.s.bdMSAP.dstInst = S_INST; /* instance */
+ cfg.t.cfg.s.bdMSAP.dstInst = S_INST; /* instance */
cfg.t.cfg.s.bdMSAP.t201Tmr = 1; /* T201 - should be equal to t200Tmr */
cfg.t.cfg.s.bdMSAP.t202Tmr = 2; /* T202 */
cfg.t.cfg.s.bdMSAP.bndRetryCnt = 2; /* bind retry counter */
@@ -392,7 +377,7 @@ ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span)
if (signal_data->setup_arb == SNGISDN_OPT_TRUE) {
cfg.t.cfg.s.bdMSAP.setUpArb = ACTIVE;
} else if (signal_data->setup_arb == SNGISDN_OPT_FALSE) {
- cfg.t.cfg.s.bdMSAP.setUpArb = PASSIVE;
+ cfg.t.cfg.s.bdMSAP.setUpArb = PASSIVE;
}
if (sng_isdn_q921_config(&pst, &cfg)) {
@@ -401,27 +386,27 @@ ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span)
return FTDM_SUCCESS;
}
-ftdm_status_t sng_isdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t management)
+ftdm_status_t sngisdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t management)
{
BdMngmt cfg;
- Pst pst;
+ Pst pst;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
- /* initalize the post structure */
- stack_pst_init(&pst);
+ /* initalize the post structure */
+ stack_pst_init(&pst);
/* insert the destination Entity */
- pst.dstEnt = ENTLD;
+ pst.dstEnt = ENTLD;
- /*clear the configuration structure*/
- memset(&cfg, 0, sizeof(cfg));
+ /*clear the configuration structure*/
+ memset(&cfg, 0, sizeof(cfg));
/*fill in some general sections of the header*/
- stack_hdr_init(&cfg.hdr);
+ stack_hdr_init(&cfg.hdr);
/*fill in the specific fields of the header*/
- cfg.hdr.msgType = TCFG;
- cfg.hdr.entId.ent = ENTLD;
- cfg.hdr.entId.inst = S_INST;
- cfg.hdr.elmId.elmnt = STDLSAP;
+ cfg.hdr.msgType = TCFG;
+ cfg.hdr.entId.ent = ENTLD;
+ cfg.hdr.entId.inst = S_INST;
+ cfg.hdr.elmId.elmnt = STDLSAP;
cfg.t.cfg.s.bdDLSAP.lnkNmb = signal_data->link_id;
@@ -433,10 +418,10 @@ ftdm_status_t sng_isdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t managemen
} else {
cfg.t.cfg.s.bdDLSAP.k = 7; /* k */
}
-
+
cfg.t.cfg.s.bdDLSAP.n200 = 3; /* n200 */
cfg.t.cfg.s.bdDLSAP.congTmr = 300; /* congestion timer */
- cfg.t.cfg.s.bdDLSAP.t200Tmr = 1; /* t1 changed from 25 */
+ cfg.t.cfg.s.bdDLSAP.t200Tmr = 1; /* t1 changed from 25 */
cfg.t.cfg.s.bdDLSAP.t203Tmr = 10; /* t3 changed from 50 */
cfg.t.cfg.s.bdDLSAP.mod = 128; /* modulo */
cfg.t.cfg.s.bdDLSAP.selector = 0; /* Selector 0 */
@@ -483,31 +468,31 @@ ftdm_status_t sng_isdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t managemen
return FTDM_SUCCESS;
}
-ftdm_status_t sng_isdn_stack_cfg_q931_gen(void)
+ftdm_status_t sngisdn_stack_cfg_q931_gen(void)
{
InMngmt cfg;
- Pst pst;
+ Pst pst;
- /* initalize the post structure */
- stack_pst_init(&pst);
+ /* initalize the post structure */
+ stack_pst_init(&pst);
- /* insert the destination Entity */
- pst.dstEnt = ENTIN;
+ /* insert the destination Entity */
+ pst.dstEnt = ENTIN;
- /*clear the configuration structure*/
+ /*clear the configuration structure*/
memset(&cfg, 0, sizeof(cfg));
- /*fill in some general sections of the header*/
- stack_hdr_init(&cfg.hdr);
+ /*fill in some general sections of the header*/
+ stack_hdr_init(&cfg.hdr);
- /*fill in the specific fields of the header*/
- cfg.hdr.msgType = TCFG;
- cfg.hdr.entId.ent = ENTIN;
- cfg.hdr.entId.inst = S_INST;
- cfg.hdr.elmId.elmnt = STGEN;
+ /*fill in the specific fields of the header*/
+ cfg.hdr.msgType = TCFG;
+ cfg.hdr.entId.ent = ENTIN;
+ cfg.hdr.entId.inst = S_INST;
+ cfg.hdr.elmId.elmnt = STGEN;
- /* fill in the Gen Conf structures internal pst struct */
- stack_pst_init(&cfg.t.cfg.s.inGen.sm);
+ /* fill in the Gen Conf structures internal pst struct */
+ stack_pst_init(&cfg.t.cfg.s.inGen.sm);
cfg.t.cfg.s.inGen.nmbSaps = MAX_VARIANTS+1; /* Total number of variants supported */
@@ -538,29 +523,29 @@ ftdm_status_t sng_isdn_stack_cfg_q931_gen(void)
}
/* Link between CC and q931 */
-ftdm_status_t sng_isdn_stack_cfg_q931_tsap(ftdm_span_t *span)
+ftdm_status_t sngisdn_stack_cfg_q931_tsap(ftdm_span_t *span)
{
InMngmt cfg;
- Pst pst;
+ Pst pst;
unsigned i;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
- /* initalize the post structure */
- stack_pst_init(&pst);
+ /* initalize the post structure */
+ stack_pst_init(&pst);
- /* insert the destination Entity */
- pst.dstEnt = ENTIN;
+ /* insert the destination Entity */
+ pst.dstEnt = ENTIN;
- /*clear the configuration structure*/
+ /*clear the configuration structure*/
memset(&cfg, 0, sizeof(cfg));
- /*fill in some general sections of the header*/
- stack_hdr_init(&cfg.hdr);
+ /*fill in some general sections of the header*/
+ stack_hdr_init(&cfg.hdr);
- /*fill in the specific fields of the header*/
- cfg.hdr.msgType = TCFG;
- cfg.hdr.entId.ent = ENTIN;
- cfg.hdr.entId.inst = S_INST;
- cfg.hdr.elmId.elmnt = STTSAP;
+ /*fill in the specific fields of the header*/
+ cfg.hdr.msgType = TCFG;
+ cfg.hdr.entId.ent = ENTIN;
+ cfg.hdr.entId.inst = S_INST;
+ cfg.hdr.elmId.elmnt = STTSAP;
cfg.t.cfg.s.inTSAP.sapId = signal_data->cc_id;
@@ -601,34 +586,34 @@ ftdm_status_t sng_isdn_stack_cfg_q931_tsap(ftdm_span_t *span)
return FTDM_SUCCESS;
}
-ftdm_status_t sng_isdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
+ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
{
InMngmt cfg;
- Pst pst;
+ Pst pst;
unsigned i;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
- /* initalize the post structure */
- stack_pst_init(&pst);
+ /* initalize the post structure */
+ stack_pst_init(&pst);
- /* insert the destination Entity */
- pst.dstEnt = ENTIN;
+ /* insert the destination Entity */
+ pst.dstEnt = ENTIN;
- /*clear the configuration structure*/
+ /*clear the configuration structure*/
memset(&cfg, 0, sizeof(cfg));
- /*fill in some general sections of the header*/
- stack_hdr_init(&cfg.hdr);
+ /*fill in some general sections of the header*/
+ stack_hdr_init(&cfg.hdr);
+
+ /*fill in the specific fields of the header*/
+ cfg.hdr.msgType = TCFG;
+ cfg.hdr.entId.ent = ENTIN;
+ cfg.hdr.entId.inst = S_INST;
+ cfg.hdr.elmId.elmnt = STDLSAP;
- /*fill in the specific fields of the header*/
- cfg.hdr.msgType = TCFG;
- cfg.hdr.entId.ent = ENTIN;
- cfg.hdr.entId.inst = S_INST;
- cfg.hdr.elmId.elmnt = STDLSAP;
-
cfg.hdr.response.selector=0;
-
+
cfg.t.cfg.s.inDLSAP.sapId = signal_data->link_id;
cfg.t.cfg.s.inDLSAP.spId = signal_data->link_id;
cfg.t.cfg.s.inDLSAP.swtch = sng_isdn_stack_switchtype(signal_data->switchtype);
@@ -674,7 +659,7 @@ ftdm_status_t sng_isdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
cfg.t.cfg.s.inDLSAP.ctldInt[1] = 1;
}
- cfg.t.cfg.s.inDLSAP.numRstInd = 255;
+ cfg.t.cfg.s.inDLSAP.numRstInd = 255;
cfg.t.cfg.s.inDLSAP.relOpt = TRUE;
#ifdef ISDN_SRV
cfg.t.cfg.s.inDLSAP.bcas = FALSE;
@@ -701,7 +686,16 @@ ftdm_status_t sng_isdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
cfg.t.cfg.s.inDLSAP.statEnqOpt = FALSE;
cfg.t.cfg.s.inDLSAP.rstOpt = FALSE;
}
-
+
+ /* Override the restart options if user selected that option */
+ if (signal_data->restart_opt != SNGISDN_OPT_DEFAULT) {
+ if (signal_data->restart_opt == SNGISDN_OPT_TRUE) {
+ cfg.t.cfg.s.inDLSAP.rstOpt = TRUE;
+ } else {
+ cfg.t.cfg.s.inDLSAP.rstOpt = FALSE;
+ }
+ }
+
for (i = 0; i < IN_MAXBCHNL; i++)
{
cfg.t.cfg.s.inDLSAP.bProf[i].profNmb = 0;
@@ -851,39 +845,39 @@ ftdm_status_t sng_isdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
return FTDM_SUCCESS;
}
-ftdm_status_t sng_isdn_stack_cfg_q931_lce(ftdm_span_t *span)
+ftdm_status_t sngisdn_stack_cfg_q931_lce(ftdm_span_t *span)
{
InMngmt cfg;
- Pst pst;
+ Pst pst;
uint8_t i;
- uint8_t numCes=1;
+ uint8_t numCes=1;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
if (span->trunk_type == FTDM_TRUNK_BRI_PTMP && signal_data->signalling == SNGISDN_SIGNALING_NET) {
numCes = 8;
}
- /* initalize the post structure */
- stack_pst_init(&pst);
+ /* initalize the post structure */
+ stack_pst_init(&pst);
- /* insert the destination Entity */
- pst.dstEnt = ENTIN;
+ /* insert the destination Entity */
+ pst.dstEnt = ENTIN;
- /*clear the configuration structure*/
+ /*clear the configuration structure*/
memset(&cfg, 0, sizeof(cfg));
- /*fill in some general sections of the header*/
- stack_hdr_init(&cfg.hdr);
+ /*fill in some general sections of the header*/
+ stack_hdr_init(&cfg.hdr);
- /*fill in the specific fields of the header*/
- cfg.hdr.msgType = TCFG;
- cfg.hdr.entId.ent = ENTIN;
- cfg.hdr.entId.inst = S_INST;
- cfg.hdr.elmId.elmnt = STDLC;
+ /*fill in the specific fields of the header*/
+ cfg.hdr.msgType = TCFG;
+ cfg.hdr.entId.ent = ENTIN;
+ cfg.hdr.entId.inst = S_INST;
+ cfg.hdr.elmId.elmnt = STDLC;
cfg.hdr.response.selector=0;
cfg.t.cfg.s.inLCe.sapId = signal_data->link_id;
-
+
cfg.t.cfg.s.inLCe.lnkUpDwnInd = TRUE;
cfg.t.cfg.s.inLCe.tCon.enb = TRUE;
@@ -892,7 +886,7 @@ ftdm_status_t sng_isdn_stack_cfg_q931_lce(ftdm_span_t *span)
cfg.t.cfg.s.inLCe.tDisc.val = 35;
cfg.t.cfg.s.inLCe.t314.enb = FALSE; /* if segmentation enabled, set to TRUE */
cfg.t.cfg.s.inLCe.t314.val = 35;
-
+
cfg.t.cfg.s.inLCe.t332i.enb = FALSE; /* set to TRUE for NFAS */
#ifdef NFAS
@@ -912,7 +906,6 @@ ftdm_status_t sng_isdn_stack_cfg_q931_lce(ftdm_span_t *span)
cfg.t.cfg.s.inLCe.tRstAck.enb = TRUE;
cfg.t.cfg.s.inLCe.tRstAck.val = 10;
-
cfg.t.cfg.s.inLCe.usid = 0;
cfg.t.cfg.s.inLCe.tid = 0;
@@ -927,7 +920,7 @@ ftdm_status_t sng_isdn_stack_cfg_q931_lce(ftdm_span_t *span)
}
-ftdm_status_t sng_isdn_stack_cfg_cc_gen(void)
+ftdm_status_t sngisdn_stack_cfg_cc_gen(void)
{
CcMngmt cfg;
Pst pst;
@@ -966,7 +959,7 @@ ftdm_status_t sng_isdn_stack_cfg_cc_gen(void)
}
-ftdm_status_t sng_isdn_stack_cfg_cc_sap(ftdm_span_t *span)
+ftdm_status_t sngisdn_stack_cfg_cc_sap(ftdm_span_t *span)
{
CcMngmt cfg;
Pst pst;
@@ -998,11 +991,11 @@ ftdm_status_t sng_isdn_stack_cfg_cc_sap(ftdm_span_t *span)
cfg.t.cfg.s.ccISAP.pst.dstInst = S_INST;
cfg.t.cfg.s.ccISAP.pst.dstProcId = SFndProcId();
- cfg.t.cfg.s.ccISAP.pst.prior = PRIOR0;
- cfg.t.cfg.s.ccISAP.pst.route = RTESPEC;
- cfg.t.cfg.s.ccISAP.pst.region = S_REG;
- cfg.t.cfg.s.ccISAP.pst.pool = S_POOL;
- cfg.t.cfg.s.ccISAP.pst.selector = 0;
+ cfg.t.cfg.s.ccISAP.pst.prior = PRIOR0;
+ cfg.t.cfg.s.ccISAP.pst.route = RTESPEC;
+ cfg.t.cfg.s.ccISAP.pst.region = S_REG;
+ cfg.t.cfg.s.ccISAP.pst.pool = S_POOL;
+ cfg.t.cfg.s.ccISAP.pst.selector = 0;
cfg.t.cfg.s.ccISAP.suId = signal_data->cc_id;
cfg.t.cfg.s.ccISAP.spId = signal_data->cc_id;
@@ -1020,19 +1013,19 @@ ftdm_status_t sng_isdn_stack_cfg_cc_sap(ftdm_span_t *span)
void stack_pst_init(Pst *pst)
{
memset(pst, 0, sizeof(Pst));
- /*fill in the post structure*/
- pst->dstProcId = SFndProcId();
- pst->dstInst = S_INST;
+ /*fill in the post structure*/
+ pst->dstProcId = SFndProcId();
+ pst->dstInst = S_INST;
- pst->srcProcId = SFndProcId();
- pst->srcEnt = ENTSM;
- pst->srcInst = S_INST;
+ pst->srcProcId = SFndProcId();
+ pst->srcEnt = ENTSM;
+ pst->srcInst = S_INST;
- pst->prior = PRIOR0;
- pst->route = RTESPEC;
- pst->region = S_REG;
- pst->pool = S_POOL;
- pst->selector = 0;
+ pst->prior = PRIOR0;
+ pst->route = RTESPEC;
+ pst->region = S_REG;
+ pst->pool = S_POOL;
+ pst->selector = 0;
return;
}
@@ -1041,21 +1034,21 @@ void stack_pst_init(Pst *pst)
void stack_hdr_init(Header *hdr)
{
hdr->msgType = 0;
- hdr->msgLen = 0;
- hdr->entId.ent = 0;
- hdr->entId.inst = 0;
- hdr->elmId.elmnt = 0;
- hdr->elmId.elmntInst1 = 0;
- hdr->elmId.elmntInst2 = 0;
- hdr->elmId.elmntInst3 = 0;
- hdr->seqNmb = 0;
- hdr->version = 0;
- hdr->response.prior = PRIOR0;
- hdr->response.route = RTESPEC;
- hdr->response.mem.region = S_REG;
- hdr->response.mem.pool = S_POOL;
- hdr->transId = 0;
- hdr->response.selector = 0;
+ hdr->msgLen = 0;
+ hdr->entId.ent = 0;
+ hdr->entId.inst = 0;
+ hdr->elmId.elmnt = 0;
+ hdr->elmId.elmntInst1 = 0;
+ hdr->elmId.elmntInst2 = 0;
+ hdr->elmId.elmntInst3 = 0;
+ hdr->seqNmb = 0;
+ hdr->version = 0;
+ hdr->response.prior = PRIOR0;
+ hdr->response.route = RTESPEC;
+ hdr->response.mem.region = S_REG;
+ hdr->response.mem.pool = S_POOL;
+ hdr->transId = 0;
+ hdr->response.selector = 0;
return;
}
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c
index bfc00d07ba..225244f57e 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c
@@ -37,27 +37,26 @@
void stack_resp_hdr_init(Header *hdr);
-ftdm_status_t sng_isdn_activate_phy(ftdm_span_t *span);
-ftdm_status_t sng_isdn_deactivate_phy(ftdm_span_t *span);
+ftdm_status_t sngisdn_activate_phy(ftdm_span_t *span);
+ftdm_status_t sngisdn_deactivate_phy(ftdm_span_t *span);
-ftdm_status_t sng_isdn_activate_cc(ftdm_span_t *span);
-ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt);
+ftdm_status_t sngisdn_activate_cc(ftdm_span_t *span);
-ftdm_status_t sng_isdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t subaction);
-ftdm_status_t sng_isdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t subaction);
+ftdm_status_t sngisdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t subaction);
+ftdm_status_t sngisdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t subaction);
extern ftdm_sngisdn_data_t g_sngisdn_data;
-ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span);
+ftdm_status_t sngisdn_stack_stop(ftdm_span_t *span);
-ftdm_status_t sng_isdn_stack_start(ftdm_span_t *span)
+ftdm_status_t sngisdn_stack_start(ftdm_span_t *span)
{
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
- if (sng_isdn_cntrl_q921(span, ABND_ENA, NOTUSED) != FTDM_SUCCESS) {
+ if (sngisdn_cntrl_q921(span, ABND_ENA, NOTUSED) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack q921\n", span->name);
return FTDM_FAIL;
}
@@ -72,7 +71,7 @@ ftdm_status_t sng_isdn_stack_start(ftdm_span_t *span)
ftdm_log(FTDM_LOG_DEBUG, "%s:Stack q921 activated\n", span->name);
if (!g_sngisdn_data.ccs[signal_data->cc_id].activation_done) {
g_sngisdn_data.ccs[signal_data->cc_id].activation_done = 1;
- if (sng_isdn_activate_cc(span) != FTDM_SUCCESS) {
+ if (sngisdn_activate_cc(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack CC\n", span->name);
return FTDM_FAIL;
}
@@ -80,7 +79,7 @@ ftdm_status_t sng_isdn_stack_start(ftdm_span_t *span)
}
- if (sng_isdn_cntrl_q931(span, ABND_ENA, SAELMNT) != FTDM_SUCCESS) {
+ if (sngisdn_cntrl_q931(span, ABND_ENA, SAELMNT) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack q931\n", span->name);
return FTDM_FAIL;
}
@@ -90,20 +89,20 @@ ftdm_status_t sng_isdn_stack_start(ftdm_span_t *span)
return FTDM_SUCCESS;
}
-ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span)
+ftdm_status_t sngisdn_stack_stop(ftdm_span_t *span)
{
/* Stop L1 first, so we do not receive any more frames */
- if (sng_isdn_deactivate_phy(span) != FTDM_SUCCESS) {
+ if (sngisdn_deactivate_phy(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to deactivate stack phy\n", span->name);
return FTDM_FAIL;
}
- if (sng_isdn_cntrl_q931(span, AUBND_DIS, SAELMNT) != FTDM_SUCCESS) {
+ if (sngisdn_cntrl_q931(span, AUBND_DIS, SAELMNT) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to deactivate stack q931\n", span->name);
return FTDM_FAIL;
}
- if (sng_isdn_cntrl_q921(span, AUBND_DIS, SAELMNT) != FTDM_SUCCESS) {
+ if (sngisdn_cntrl_q921(span, AUBND_DIS, SAELMNT) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to deactivate stack q921\n", span->name);
return FTDM_FAIL;
}
@@ -113,41 +112,7 @@ ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span)
}
-ftdm_status_t sng_isdn_wake_up_phy(ftdm_span_t *span)
-{
- L1Mngmt cntrl;
- Pst pst;
-
- sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
-
- /* initalize the post structure */
- stack_pst_init(&pst);
-
- /* insert the destination Entity */
- pst.dstEnt = ENTL1;
-
- /* initalize the control structure */
- memset(&cntrl, 0, sizeof(cntrl));
-
- /* initalize the control header */
- stack_hdr_init(&cntrl.hdr);
-
- cntrl.hdr.msgType = TCNTRL; /* configuration */
- cntrl.hdr.entId.ent = ENTL1; /* entity */
- cntrl.hdr.entId.inst = S_INST; /* instance */
- cntrl.hdr.elmId.elmnt = STTSAP; /* SAP Specific cntrl */
-
- cntrl.t.cntrl.action = AENA;
- cntrl.t.cntrl.subAction = SAELMNT;
- cntrl.t.cntrl.sapId = signal_data->link_id;
-
- if (sng_isdn_phy_cntrl(&pst, &cntrl)) {
- return FTDM_FAIL;
- }
- return FTDM_SUCCESS;
-}
-
-ftdm_status_t sng_isdn_activate_phy(ftdm_span_t *span)
+ftdm_status_t sngisdn_activate_phy(ftdm_span_t *span)
{
/* There is no need to start phy, as it will Q921 will send a activate request to phy when it starts */
@@ -155,7 +120,7 @@ ftdm_status_t sng_isdn_activate_phy(ftdm_span_t *span)
return FTDM_SUCCESS;
}
-ftdm_status_t sng_isdn_deactivate_phy(ftdm_span_t *span)
+ftdm_status_t sngisdn_deactivate_phy(ftdm_span_t *span)
{
L1Mngmt cntrl;
Pst pst;
@@ -189,8 +154,41 @@ ftdm_status_t sng_isdn_deactivate_phy(ftdm_span_t *span)
return FTDM_SUCCESS;
}
+ftdm_status_t sngisdn_wake_up_phy(ftdm_span_t *span)
+{
+ L1Mngmt cntrl;
+ Pst pst;
-ftdm_status_t sng_isdn_activate_cc(ftdm_span_t *span)
+ sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
+
+ /* initalize the post structure */
+ stack_pst_init(&pst);
+
+ /* insert the destination Entity */
+ pst.dstEnt = ENTL1;
+
+ /* initalize the control structure */
+ memset(&cntrl, 0, sizeof(cntrl));
+
+ /* initalize the control header */
+ stack_hdr_init(&cntrl.hdr);
+
+ cntrl.hdr.msgType = TCNTRL; /* configuration */
+ cntrl.hdr.entId.ent = ENTL1; /* entity */
+ cntrl.hdr.entId.inst = S_INST; /* instance */
+ cntrl.hdr.elmId.elmnt = STTSAP; /* SAP Specific cntrl */
+
+ cntrl.t.cntrl.action = AENA;
+ cntrl.t.cntrl.subAction = SAELMNT;
+ cntrl.t.cntrl.sapId = signal_data->link_id;
+
+ if (sng_isdn_phy_cntrl(&pst, &cntrl)) {
+ return FTDM_FAIL;
+ }
+ return FTDM_SUCCESS;
+}
+
+ftdm_status_t sngisdn_activate_cc(ftdm_span_t *span)
{
CcMngmt cntrl;
Pst pst;
@@ -224,7 +222,7 @@ ftdm_status_t sng_isdn_activate_cc(ftdm_span_t *span)
return FTDM_SUCCESS;
}
-ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt)
+ftdm_status_t sngisdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt)
{
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
switch (trace_opt) {
@@ -233,7 +231,7 @@ ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t tra
ftdm_log(FTDM_LOG_INFO, "s%d Disabling q921 trace\n", signal_data->link_id);
sngisdn_clear_trace_flag(signal_data, SNGISDN_TRACE_Q921);
- if (sng_isdn_cntrl_q921(span, ADISIMM, SATRC) != FTDM_SUCCESS) {
+ if (sngisdn_cntrl_q921(span, ADISIMM, SATRC) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "s%d Failed to disable q921 trace\n");
}
}
@@ -241,7 +239,7 @@ ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t tra
ftdm_log(FTDM_LOG_INFO, "s%d Disabling q931 trace\n", signal_data->link_id);
sngisdn_clear_trace_flag(signal_data, SNGISDN_TRACE_Q931);
- if (sng_isdn_cntrl_q931(span, ADISIMM, SATRC) != FTDM_SUCCESS) {
+ if (sngisdn_cntrl_q931(span, ADISIMM, SATRC) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "s%d Failed to disable q931 trace\n");
}
}
@@ -251,7 +249,7 @@ ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t tra
ftdm_log(FTDM_LOG_INFO, "s%d Enabling q921 trace\n", signal_data->link_id);
sngisdn_set_trace_flag(signal_data, SNGISDN_TRACE_Q921);
- if (sng_isdn_cntrl_q921(span, AENA, SATRC) != FTDM_SUCCESS) {
+ if (sngisdn_cntrl_q921(span, AENA, SATRC) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "s%d Failed to enable q921 trace\n");
}
}
@@ -261,7 +259,7 @@ ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t tra
ftdm_log(FTDM_LOG_INFO, "s%d Enabling q931 trace\n", signal_data->link_id);
sngisdn_set_trace_flag(signal_data, SNGISDN_TRACE_Q931);
- if (sng_isdn_cntrl_q931(span, AENA, SATRC) != FTDM_SUCCESS) {
+ if (sngisdn_cntrl_q931(span, AENA, SATRC) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "s%d Failed to enable q931 trace\n");
}
}
@@ -271,7 +269,7 @@ ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t tra
}
-ftdm_status_t sng_isdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t subaction)
+ftdm_status_t sngisdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t subaction)
{
InMngmt cntrl;
Pst pst;
@@ -310,7 +308,7 @@ ftdm_status_t sng_isdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t sub
}
-ftdm_status_t sng_isdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t subaction)
+ftdm_status_t sngisdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t subaction)
{
BdMngmt cntrl;
Pst pst;
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 8408c673ef..fb65d20cab 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
@@ -33,6 +33,7 @@
*/
#include "ftmod_sangoma_isdn.h"
+ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn);
/* Remote side transmit a SETUP */
void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
@@ -122,15 +123,20 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
break;
}
-#if 0
- /* Export ftdmchan variables here if we need to */
- ftdm_channel_add_var(ftdmchan, "isdn_specific_var", "1");
-#endif
/* Fill in call information */
- cpy_calling_num_from_stack(&ftdmchan->caller_data, &conEvnt->cgPtyNmb);
- cpy_called_num_from_stack(&ftdmchan->caller_data, &conEvnt->cdPtyNmb);
- cpy_calling_name_from_stack(&ftdmchan->caller_data, &conEvnt->display);
- cpy_redir_num_from_stack(&ftdmchan->caller_data, &conEvnt->redirNmb);
+ get_calling_num(ftdmchan, &conEvnt->cgPtyNmb);
+ get_calling_num2(ftdmchan, &conEvnt->cgPtyNmb2);
+ get_called_num(ftdmchan, &conEvnt->cdPtyNmb);
+ get_redir_num(ftdmchan, &conEvnt->redirNmb);
+ get_calling_subaddr(ftdmchan, &conEvnt->cgPtySad);
+ get_prog_ind_ie(ftdmchan, &conEvnt->progInd);
+ get_facility_ie(ftdmchan, &conEvnt->facilityStr);
+
+ if (get_calling_name_from_display(ftdmchan, &conEvnt->display) != FTDM_SUCCESS) {
+ get_calling_name_from_usr_usr(ftdmchan, &conEvnt->usrUsr);
+ }
+
+
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Incoming call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits);
if (conEvnt->bearCap[0].eh.pres) {
@@ -138,41 +144,41 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
ftdmchan->caller_data.bearer_capability = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].infoTranCap.val);
}
- if (signal_data->switchtype == SNGISDN_SWITCH_NI2) {
- if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) {
- if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) {
- snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]);
- }
- }
-
- if (signal_data->facility == SNGISDN_OPT_TRUE && conEvnt->facilityStr.eh.pres) {
- /* Verify whether the Caller Name will come in a subsequent FACILITY message */
- uint16_t ret_val;
- char retrieved_str[255];
-
- ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str);
- /*
- return values for "sng_isdn_retrieve_facility_information_following":
- If there will be no information following, or fails to decode IE, returns -1
- If there will be no information following, but current FACILITY IE contains a caller name, returns 0
- If there will be information following, returns 1
- */
-
- if (ret_val == 1) {
- ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n");
- ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID);
- /* Launch timer in case we never get a FACILITY msg */
- if (signal_data->facility_timeout) {
- ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout,
- sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]);
- }
- break;
- } else if (ret_val == 0) {
- strcpy(ftdmchan->caller_data.cid_name, retrieved_str);
- }
+
+ if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) {
+ if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) {
+ snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]);
}
}
+ /* this should be in get_facility_ie function, fix this later */
+ if (signal_data->facility == SNGISDN_OPT_TRUE && conEvnt->facilityStr.eh.pres) {
+ /* Verify whether the Caller Name will come in a subsequent FACILITY message */
+ uint16_t ret_val;
+ char retrieved_str[255];
+
+ ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str);
+ /*
+ return values for "sng_isdn_retrieve_facility_information_following":
+ If there will be no information following, or fails to decode IE, returns -1
+ If there will be no information following, but current FACILITY IE contains a caller name, returns 0
+ If there will be information following, returns 1
+ */
+
+ if (ret_val == 1) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n");
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID);
+ /* Launch timer in case we never get a FACILITY msg */
+ if (signal_data->facility_timeout) {
+ ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout,
+ sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]);
+ }
+ break;
+ } else if (ret_val == 0) {
+ strcpy(ftdmchan->caller_data.cid_name, retrieved_str);
+ }
+ }
+
if (signal_data->overlap_dial == SNGISDN_OPT_TRUE && !conEvnt->sndCmplt.eh.pres) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT);
} else {
@@ -243,11 +249,9 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
uint8_t ces = sngisdn_event->ces;
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
-
- ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+ CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt;
- /* Function does not require any info from conStEvnt struct for now */
- /* CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt; */
+ ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
@@ -269,9 +273,12 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
switch(ftdmchan->state) {
+ case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_DIALING:
+ get_prog_ind_ie(ftdmchan, &cnStEvnt->progInd);
+ get_facility_ie(ftdmchan, &cnStEvnt->facilityStr);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP);
break;
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
@@ -318,8 +325,6 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
- sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
-
CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt;
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
@@ -335,49 +340,34 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
suId, suInstId, spInstId, ces);
switch(evntType) {
+ case MI_CALLPROC:
case MI_PROGRESS:
- if (signal_data->switchtype == SNGISDN_SWITCH_NI2 &&
- cnStEvnt->causeDgn[0].eh.pres && cnStEvnt->causeDgn[0].causeVal.pres) {
-
- switch(cnStEvnt->causeDgn[0].causeVal.val) {
- case 17: /* User Busy */
- case 18: /* No User responding */
- case 19: /* User alerting, no answer */
- case 21: /* Call rejected, the called party does not with to accept this call */
- case 27: /* Destination out of order */
- case 31: /* Normal, unspecified */
- case 34: /* Circuit/Channel congestion */
- case 41: /* Temporary failure */
- case 42: /* Switching equipment is experiencing a period of high traffic */
- case 47: /* Resource unavailable */
- case 58: /* Bearer Capability not available */
- case 63: /* Service or option not available */
- case 65: /* Bearer Cap not implemented, not supported */
- case 79: /* Service or option not implemented, unspecified */
- ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Cause requires disconnect (cause:%d)\n", cnStEvnt->causeDgn[0].causeVal.val);
- ftdmchan->caller_data.hangup_cause = cnStEvnt->causeDgn[0].causeVal.val;
-
- sngisdn_set_flag(sngisdn_info, FLAG_SEND_DISC);
- ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
- goto sngisdn_process_cnst_ind_end;
- }
- }
- /* fall-through */
case MI_ALERTING:
- case MI_CALLPROC:
-
+ get_prog_ind_ie(ftdmchan, &cnStEvnt->progInd);
+ get_facility_ie(ftdmchan, &cnStEvnt->facilityStr);
+
+ if (sngisdn_cause_val_requires_disconnect(ftdmchan, &cnStEvnt->causeDgn[0]) == FTDM_SUCCESS) {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Cause requires disconnect (cause:%d)\n", cnStEvnt->causeDgn[0].causeVal.val);
+ ftdmchan->caller_data.hangup_cause = cnStEvnt->causeDgn[0].causeVal.val;
+
+ sngisdn_set_flag(sngisdn_info, FLAG_SEND_DISC);
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+ goto sngisdn_process_cnst_ind_end;
+ }
+
switch(ftdmchan->state) {
- case FTDM_CHANNEL_STATE_DIALING:
- if (evntType == MI_PROGRESS ||
- (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL)) {
+ case FTDM_CHANNEL_STATE_DIALING:
+ case FTDM_CHANNEL_STATE_PROCEED:
+ if (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
+ } else if (evntType == MI_CALLPROC) {
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROCEED);
} else {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
}
break;
case FTDM_CHANNEL_STATE_PROGRESS:
- if (evntType == MI_PROGRESS ||
- (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL)) {
+ if (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
}
break;
@@ -406,7 +396,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
ftdm_size_t min_digits = ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->min_digits;
ftdm_size_t num_digits;
- cpy_called_num_from_stack(&ftdmchan->caller_data, &cnStEvnt->cdPtyNmb);
+ get_called_num(ftdmchan, &cnStEvnt->cdPtyNmb);
num_digits = strlen(ftdmchan->caller_data.dnis.digits);
if (cnStEvnt->sndCmplt.eh.pres || num_digits >= min_digits) {
@@ -417,6 +407,8 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
}
break;
case FTDM_CHANNEL_STATE_RING:
+ case FTDM_CHANNEL_STATE_RINGING:
+ case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_UP:
@@ -454,12 +446,16 @@ void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event)
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing DISCONNECT (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
- switch (ftdmchan->state) {
+ switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_RING:
+ case FTDM_CHANNEL_STATE_RINGING:
case FTDM_CHANNEL_STATE_DIALING:
+ case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_UP:
+ get_facility_ie(ftdmchan, &discEvnt->facilityStr);
+
if (discEvnt->causeDgn[0].eh.pres && discEvnt->causeDgn[0].causeVal.pres) {
ftdmchan->caller_data.hangup_cause = discEvnt->causeDgn[0].causeVal.val;
} else {
@@ -535,18 +531,23 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
case FTDM_CHANNEL_STATE_DIALING:
/* Remote side rejected our SETUP message on outbound call */
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
- sng_isdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
+ sngisdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
}
/* fall-through */
+ case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_UP:
case FTDM_CHANNEL_STATE_RING:
+ case FTDM_CHANNEL_STATE_RINGING:
/* If we previously had a glare on this channel,
this RELEASE could be for the previous call. Confirm whether call_data has
not changed while we were waiting for ftdmchan->mutex by comparing suInstId's */
if (((sngisdn_chan_data_t*)ftdmchan->call_data)->suInstId == suInstId ||
((sngisdn_chan_data_t*)ftdmchan->call_data)->spInstId == spInstId) {
+
+ get_facility_ie(ftdmchan, &relEvnt->facilityStr);
+
if (relEvnt->causeDgn[0].eh.pres && relEvnt->causeDgn[0].causeVal.pres) {
ftdmchan->caller_data.hangup_cause = relEvnt->causeDgn[0].causeVal.val;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "cause:%d\n", ftdmchan->caller_data.hangup_cause);
@@ -725,15 +726,16 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event)
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_GET_CALLERID:
/* Update the caller ID Name */
+
if (facEvnt->facElmt.facStr.pres) {
char retrieved_str[255];
-
+
/* return values for "sng_isdn_retrieve_facility_information_following":
If there will be no information following, or fails to decode IE, returns -1
If there will be no information following, but current FACILITY IE contains a caller name, returns 0
If there will be information following, returns 1
*/
-
+
if (sng_isdn_retrieve_facility_caller_name(&facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len, retrieved_str) == 0) {
strcpy(ftdmchan->caller_data.cid_name, retrieved_str);
} else {
@@ -751,6 +753,21 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event)
/* We received the caller ID Name in FACILITY, but its too late, facility-timeout already occurred */
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "FACILITY received, but we already proceeded with call\n");
break;
+ case FTDM_CHANNEL_STATE_UP:
+ {
+ 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);
+ }
+ break;
default:
/* We do not support other FACILITY types for now, so do nothing */
break;
@@ -865,7 +882,9 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "T302 Timer expired, proceeding with call\n");
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
break;
+ case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
+ case FTDM_CHANNEL_STATE_RINGING:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Remote switch expecting OVERLAP receive, but we are already PROCEEDING\n");
sngisdn_snd_disconnect(ftdmchan);
@@ -882,7 +901,9 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
break;
case 3:
switch (ftdmchan->state) {
+ case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
+ case FTDM_CHANNEL_STATE_RINGING:
/* T310 timer has expired */
ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val;
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "T310 Timer expired, hanging up call\n");
@@ -919,6 +940,7 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
break;
case 9: /* Remote switch is in "Incoming call proceeding" state */
switch (ftdmchan->state) {
+ case FTDM_CHANNEL_STATE_RINGING:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_GET_CALLERID:
@@ -1062,8 +1084,44 @@ void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event)
(evntType == IN_LNK_DWN)?"LNK_DOWN":
(evntType == IN_LNK_UP)?"LNK_UP":
(evntType == IN_INDCHAN)?"b-channel":
- (evntType == IN_LNK_DWN_DM_RLS)?"Nfas service procedures":
+ (evntType == IN_LNK_DWN_DM_RLS)?"NFAS service procedures":
(evntType == IN_SWCHD_BU_DCHAN)?"NFAS switchover to backup":"Unknown");
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
+
+ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn)
+{
+ sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
+
+ if (signal_data->ignore_cause_value == SNGISDN_OPT_TRUE) {
+ return FTDM_FAIL;
+ }
+
+ /* By default, we only evaluate cause value on 5ESS switches */
+ if (signal_data->ignore_cause_value == SNGISDN_OPT_DEFAULT &&
+ signal_data->switchtype != SNGISDN_SWITCH_5ESS) {
+
+ return FTDM_FAIL;
+ }
+
+ /* ignore_cause_value = SNGISDN_OPT_FALSE or switchtype == 5ESS */
+ switch(causeDgn->causeVal.val) {
+ case 17: /* User Busy */
+ case 18: /* No User responding */
+ case 19: /* User alerting, no answer */
+ case 21: /* Call rejected, the called party does not with to accept this call */
+ case 27: /* Destination out of order */
+ case 31: /* Normal, unspecified */
+ case 34: /* Circuit/Channel congestion */
+ case 41: /* Temporary failure */
+ case 42: /* Switching equipment is experiencing a period of high traffic */
+ case 47: /* Resource unavailable */
+ case 58: /* Bearer Capability not available */
+ case 63: /* Service or option not available */
+ case 65: /* Bearer Cap not implemented, not supported */
+ case 79: /* Service or option not implemented, unspecified */
+ return FTDM_SUCCESS;
+ }
+ return FTDM_FAIL;
+}
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c
index cb508a54b4..297c59c3b7 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c
@@ -34,18 +34,12 @@
#include "ftmod_sangoma_isdn.h"
-void sngisdn_snd_setup(ftdm_channel_t *ftdmchan);
-void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan);
-void sngisdn_snd_progress(ftdm_channel_t *ftdmchan);
-void sngisdn_snd_connect(ftdm_channel_t *ftdmchan);
-void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan);
-void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare);
-
void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
{
- ConEvnt conEvnt;
+ ConEvnt conEvnt;
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
- sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
+ sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
+ ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
ftdm_assert((!sngisdn_info->suInstId && !sngisdn_info->spInstId), "Trying to call out, but call data was not cleared\n");
@@ -123,14 +117,6 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
conEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
}
- conEvnt.progInd.eh.pres = PRSNT_NODEF;
- conEvnt.progInd.location.pres = PRSNT_NODEF;
- conEvnt.progInd.location.val = IN_LOC_USER;
- conEvnt.progInd.codeStand0.pres = PRSNT_NODEF;
- conEvnt.progInd.codeStand0.val = IN_CSTD_CCITT;
- conEvnt.progInd.progDesc.pres = PRSNT_NODEF;
- conEvnt.progInd.progDesc.val = IN_PD_NOTETEISDN; /* Not end-to-end ISDN */
-
if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) {
conEvnt.sndCmplt.eh.pres = PRSNT_NODEF;
}
@@ -140,10 +126,14 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
}
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Outgoing call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits);
- cpy_called_num_from_user(&conEvnt.cdPtyNmb, &ftdmchan->caller_data);
- cpy_calling_num_from_user(&conEvnt.cgPtyNmb, &ftdmchan->caller_data);
- cpy_redir_num_from_user(&conEvnt.redirNmb, &ftdmchan->caller_data);
- cpy_calling_name_from_user(&conEvnt, ftdmchan);
+ set_called_num(ftdmchan, &conEvnt.cdPtyNmb);
+ set_calling_num(ftdmchan, &conEvnt.cgPtyNmb);
+ set_calling_num2(ftdmchan, &conEvnt.cgPtyNmb2);
+ set_calling_subaddr(ftdmchan, &conEvnt.cgPtySad);
+ set_redir_num(ftdmchan, &conEvnt.redirNmb);
+ set_calling_name(ftdmchan, &conEvnt);
+ set_facility_ie(ftdmchan, &conEvnt.facilityStr);
+ set_prog_ind_ie(ftdmchan, &conEvnt.progInd, prog_ind);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
@@ -273,10 +263,9 @@ void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan)
}
-void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan)
+void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind)
{
CnStEvnt cnStEvnt;
-
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
@@ -321,6 +310,9 @@ void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan)
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
}
+ set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
+ set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
+ ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROCEED (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
@@ -330,14 +322,14 @@ void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan)
return;
}
-void sngisdn_snd_progress(ftdm_channel_t *ftdmchan)
+void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind)
{
CnStEvnt cnStEvnt;
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
- if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
+ if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending PROGRESS, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
@@ -351,14 +343,9 @@ void sngisdn_snd_progress(ftdm_channel_t *ftdmchan)
}
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
-
- cnStEvnt.progInd.eh.pres = PRSNT_NODEF;
- cnStEvnt.progInd.location.pres = PRSNT_NODEF;
- cnStEvnt.progInd.location.val = IN_LOC_USER;
- cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF;
- cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT;
- cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF;
- cnStEvnt.progInd.progDesc.val = IN_PD_IBAVAIL;
+ set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
+ set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
+ ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROGRESS (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_PROGRESS, signal_data->dchan_id, sngisdn_info->ces)) {
@@ -367,14 +354,14 @@ void sngisdn_snd_progress(ftdm_channel_t *ftdmchan)
return;
}
-void sngisdn_snd_alert(ftdm_channel_t *ftdmchan)
+void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind)
{
CnStEvnt cnStEvnt;
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
- if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
+ if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending ALERT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
@@ -383,13 +370,9 @@ void sngisdn_snd_alert(ftdm_channel_t *ftdmchan)
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
- cnStEvnt.progInd.eh.pres = PRSNT_NODEF;
- cnStEvnt.progInd.location.pres = PRSNT_NODEF;
- cnStEvnt.progInd.location.val = IN_LOC_USER;
- cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF;
- cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT;
- cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF;
- cnStEvnt.progInd.progDesc.val = IN_PD_NOTETEISDN;
+ set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
+ set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
+ ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending ALERT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
@@ -401,10 +384,10 @@ void sngisdn_snd_alert(ftdm_channel_t *ftdmchan)
void sngisdn_snd_connect(ftdm_channel_t *ftdmchan)
{
- CnStEvnt cnStEvnt;
-
+ CnStEvnt cnStEvnt;
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
+ ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending CONNECT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
@@ -415,7 +398,6 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan)
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
-
cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
@@ -447,14 +429,10 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan)
cnStEvnt.chanId.chanNmbSlotMap.len = 1;
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
}
-
- cnStEvnt.progInd.eh.pres = PRSNT_NODEF;
- cnStEvnt.progInd.location.pres = PRSNT_NODEF;
- cnStEvnt.progInd.location.val = IN_LOC_USER;
- cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF;
- cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT;
- cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF;
- cnStEvnt.progInd.progDesc.val = IN_PD_NOTETEISDN; /* Not end-to-end ISDN */
+
+ set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
+ set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
+ ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if (sng_isdn_con_response(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, signal_data->dchan_id, sngisdn_info->ces)) {
@@ -463,6 +441,39 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan)
return;
}
+void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan)
+{
+ FacEvnt facEvnt;
+
+ sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
+ sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
+
+ if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending FACILITY, but no call data, ignoring (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
+ return;
+ }
+
+ memset(&facEvnt, 0, sizeof(facEvnt));
+
+ if (set_facility_ie_str(ftdmchan, &facEvnt.facElmt.facStr.val[2], (uint8_t*)&facEvnt.facElmt.facStr.len) != FTDM_SUCCESS) {
+ /* No point in sending a FACILITY message if there is no Facility IE to transmit */
+ return;
+ }
+ ftdm_call_clear_data(&ftdmchan->caller_data);
+
+ facEvnt.facElmt.eh.pres = PRSNT_NODEF;
+ facEvnt.facElmt.facStr.pres = PRSNT_NODEF;
+ facEvnt.facElmt.facStr.val[0] = 0x1C;
+ facEvnt.facElmt.facStr.val[1] = (uint8_t)facEvnt.facElmt.facStr.len;
+ facEvnt.facElmt.facStr.len +=2; /* Need to include the size of identifier + len */
+
+ ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending FACILITY (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
+
+ if (sng_isdn_facility_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &facEvnt, MI_FACIL, signal_data->dchan_id, sngisdn_info->ces)) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused FACILITY request\n");
+ }
+ return;
+}
void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan)
{
@@ -482,6 +493,8 @@ void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan)
//ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending INFO REQ\n");
+ ftdm_call_clear_data(&ftdmchan->caller_data);
+
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending INFO REQ (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, signal_data->dchan_id, sngisdn_info->ces);
if (sng_isdn_con_status(signal_data->cc_id, 0, 0, &cnStEvnt, MI_INFO, signal_data->dchan_id, sngisdn_info->ces)) {
@@ -502,6 +515,8 @@ void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan)
memset(&staEvnt, 0, sizeof(StaEvnt));
+ ftdm_call_clear_data(&ftdmchan->caller_data);
+
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending Status ENQ on suId:%d suInstId:%u spInstId:%d dchan:%d ces:%d\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if (sng_isdn_status_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &staEvnt, MI_STATENQ)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused Status ENQ request\n");
@@ -517,7 +532,7 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan)
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
- if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
+ if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending DISCONNECT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
@@ -527,7 +542,8 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan)
memset(&discEvnt, 0, sizeof(discEvnt));
- /* Fill discEvnt here */
+ /* Fill discEvnt here */
+ /* TODO move this to set_cause_ie function */
discEvnt.causeDgn[0].eh.pres = PRSNT_NODEF;
discEvnt.causeDgn[0].location.pres = PRSNT_NODEF;
discEvnt.causeDgn[0].location.val = IN_LOC_PRIVNETLU;
@@ -538,6 +554,9 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan)
discEvnt.causeDgn[0].recommend.pres = NOTPRSNT;
discEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT;
+ set_facility_ie(ftdmchan, &discEvnt.facilityStr);
+ ftdm_call_clear_data(&ftdmchan->caller_data);
+
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
if (sng_isdn_disc_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &discEvnt)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused DISCONNECT request\n");
@@ -562,7 +581,7 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
memset(&relEvnt, 0, sizeof(relEvnt));
- /* Fill discEvnt here */
+ /* Fill relEvnt here */
relEvnt.causeDgn[0].eh.pres = PRSNT_NODEF;
relEvnt.causeDgn[0].location.pres = PRSNT_NODEF;
relEvnt.causeDgn[0].location.val = IN_LOC_PRIVNETLU;
@@ -582,6 +601,9 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
spInstId = sngisdn_info->spInstId;
}
+ set_facility_ie(ftdmchan, &relEvnt.facilityStr);
+ ftdm_call_clear_data(&ftdmchan->caller_data);
+
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RELEASE/RELEASE COMPLETE (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, suInstId, spInstId);
if (glare) {
@@ -597,6 +619,74 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
}
+/* We received an incoming frame on the d-channel, send data to the stack */
+void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len)
+{
+ sng_l1_frame_t l1_frame;
+ sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) dchan->span->signal_data;
+
+ memset(&l1_frame, 0, sizeof(l1_frame));
+ l1_frame.len = len;
+
+ memcpy(&l1_frame.data, data, len);
+
+ if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC)) {
+ l1_frame.flags |= SNG_L1FRAME_ERROR_CRC;
+ }
+
+ if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME)) {
+ l1_frame.flags |= SNG_L1FRAME_ERROR_FRAME;
+ }
+
+ if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT)) {
+ l1_frame.flags |= SNG_L1FRAME_ERROR_ABORT;
+ }
+
+ if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO)) {
+ l1_frame.flags |= SNG_L1FRAME_ERROR_FIFO;
+ }
+
+ if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA)) {
+ l1_frame.flags |= SNG_L1FRAME_ERROR_DMA;
+ }
+
+ if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)) {
+ /* Should we trigger congestion here? */
+ l1_frame.flags |= SNG_L1FRAME_QUEUE_THRES;
+ }
+
+ if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)) {
+ /* Should we trigger congestion here? */
+ l1_frame.flags |= SNG_L1FRAME_QUEUE_FULL;
+ }
+
+ sng_isdn_data_ind(signal_data->link_id, &l1_frame);
+}
+
+void sngisdn_snd_event(ftdm_channel_t *dchan, ftdm_oob_event_t event)
+{
+ sng_l1_event_t l1_event;
+ sngisdn_span_data_t *signal_data = NULL;
+ memset(&l1_event, 0, sizeof(l1_event));
+
+
+ signal_data = (sngisdn_span_data_t*) dchan->span->signal_data;
+ switch(event) {
+ case FTDM_OOB_ALARM_CLEAR:
+ l1_event.type = SNG_L1EVENT_ALARM_OFF;
+ sng_isdn_event_ind(signal_data->link_id, &l1_event);
+ break;
+ case FTDM_OOB_ALARM_TRAP:
+ l1_event.type = SNG_L1EVENT_ALARM_ON;
+ sng_isdn_event_ind(signal_data->link_id, &l1_event);
+ break;
+ default:
+ /* We do not care about the other OOB events for now */
+ return;
+ }
+ return;
+}
+
/* For Emacs:
* Local Variables:
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c
index 7c375f7c64..af180d1f7c 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c
@@ -732,7 +732,7 @@ void sngisdn_rcv_q931_ind(InMngmt *status)
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_UP);
- sng_isdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_UP);
+ sngisdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_UP);
} else {
ftdm_log(FTDM_LOG_WARNING, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
status->t.usta.suId,
@@ -741,7 +741,7 @@ void sngisdn_rcv_q931_ind(InMngmt *status)
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_DOWN);
- sng_isdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING);
+ sngisdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING);
}
}
break;
@@ -862,6 +862,82 @@ end_of_trace:
return;
}
+/* The stacks is wants to transmit a frame */
+int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_l1_frame_t *l1_frame)
+{
+ ftdm_status_t status;
+ ftdm_wait_flag_t flags = FTDM_WRITE;
+ sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[spId];
+ ftdm_size_t length = l1_frame->len;
+
+ ftdm_assert(signal_data, "Received Data request on unconfigured span\n");
+
+ do {
+ flags = FTDM_WRITE;
+ status = signal_data->dchan->fio->wait(signal_data->dchan, &flags, 1000);
+ if (status != FTDM_SUCCESS) {
+ ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_WARNING, "transmit timed-out\n");
+ return -1;
+ }
+
+
+ if ((flags & FTDM_WRITE)) {
+ status = signal_data->dchan->fio->write(signal_data->dchan, l1_frame->data, (ftdm_size_t*)&length);
+ if (status != FTDM_SUCCESS) {
+ ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_CRIT, "Failed to transmit frame\n");
+ return -1;
+ }
+ break;
+ /* On WIN32, it is possible for poll to return without FTDM_WRITE flag set, so we try to retransmit */
+#ifndef WIN32
+ } else {
+ ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_WARNING, "Failed to poll for d-channel\n");
+ return -1;
+#endif
+ }
+ } while(1);
+ return 0;
+}
+
+int16_t sngisdn_rcv_l1_cmd_req(uint16_t spId, sng_l1_cmd_t *l1_cmd)
+{
+ sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[spId];
+ ftdm_assert(signal_data, "Received Data request on unconfigured span\n");
+
+ switch(l1_cmd->type) {
+ case SNG_L1CMD_SET_LINK_STATUS:
+ {
+ ftdm_channel_hw_link_status_t status = FTDM_HW_LINK_CONNECTED;
+ ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_SET_LINK_STATUS, &status);
+ }
+ break;
+ case SNG_L1CMD_GET_LINK_STATUS:
+ {
+ ftdm_channel_hw_link_status_t status = 0;
+ ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_GET_LINK_STATUS, &status);
+ if (status == FTDM_HW_LINK_CONNECTED) {
+ l1_cmd->cmd.status = 1;
+ } else if (status == FTDM_HW_LINK_DISCONNECTED) {
+ l1_cmd->cmd.status = 0;
+ } else {
+ ftdm_log_chan(signal_data->dchan, FTDM_LOG_CRIT, "Invalid link status reported %d\n", status);
+ l1_cmd->cmd.status = 0;
+ }
+ }
+ break;
+ case SNG_L1CMD_FLUSH_STATS:
+ ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_FLUSH_IOSTATS, NULL);
+ break;
+ case SNG_L1CMD_FLUSH_BUFFERS:
+ ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_FLUSH_BUFFERS, NULL);
+ break;
+ default:
+ ftdm_log_chan(signal_data->dchan, FTDM_LOG_CRIT, "Unsupported channel command:%d\n", l1_cmd->type);
+ return -1;
+ }
+ return 0;
+}
+
void sngisdn_rcv_sng_assert(char *message)
{
ftdm_assert(0, message);
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c
index 7322aeddaa..76d11d6d34 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c
@@ -33,13 +33,22 @@
*/
#include "ftmod_sangoma_isdn.h"
+#define SNGISDN_Q931_FACILITY_IE_ID 0x1C
+
+/* ftmod_sangoma_isdn specific enum look-up functions */
+
+SNGISDN_ENUM_NAMES(SNGISDN_PROGIND_DESCR_NAMES, SNGISDN_PROGIND_DESCR_STRINGS)
+SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr2str, ftdm_sngisdn_progind_descr_t, SNGISDN_PROGIND_DESCR_NAMES, SNGISDN_PROGIND_DESCR_INVALID)
+
+SNGISDN_ENUM_NAMES(SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_STRINGS)
+SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t, SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_INVALID)
ftdm_status_t sngisdn_check_free_ids(void);
extern ftdm_sngisdn_data_t g_sngisdn_data;
void get_memory_info(void);
-FT_DECLARE(void) clear_call_data(sngisdn_chan_data_t *sngisdn_info)
+void clear_call_data(sngisdn_chan_data_t *sngisdn_info)
{
uint32_t cc_id = ((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->cc_id;
@@ -56,7 +65,7 @@ FT_DECLARE(void) clear_call_data(sngisdn_chan_data_t *sngisdn_info)
return;
}
-FT_DECLARE(void) clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info)
+void clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info)
{
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_DEBUG, "Clearing glare data (suId:%d suInstId:%u spInstId:%u actv-suInstId:%u actv-spInstId:%u)\n",
sngisdn_info->glare.suId,
@@ -81,7 +90,7 @@ FT_DECLARE(void) clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info)
}
-FT_DECLARE(uint32_t) get_unique_suInstId(int16_t cc_id)
+uint32_t get_unique_suInstId(int16_t cc_id)
{
uint32_t suInstId;
ftdm_assert_return((cc_id > 0 && cc_id <=MAX_VARIANTS), FTDM_FAIL, "Invalid cc_id\n");
@@ -103,7 +112,7 @@ FT_DECLARE(uint32_t) get_unique_suInstId(int16_t cc_id)
return 0;
}
-FT_DECLARE(ftdm_status_t) get_ftdmchan_by_suInstId(int16_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data)
+ftdm_status_t get_ftdmchan_by_suInstId(int16_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data)
{
ftdm_assert_return((cc_id > 0 && cc_id <=MAX_VARIANTS), FTDM_FAIL, "Invalid cc_id\n");
ftdm_assert_return(g_sngisdn_data.ccs[cc_id].activation_done, FTDM_FAIL, "Trying to find call on unconfigured CC\n");
@@ -115,7 +124,7 @@ FT_DECLARE(ftdm_status_t) get_ftdmchan_by_suInstId(int16_t cc_id, uint32_t suIns
return FTDM_SUCCESS;
}
-FT_DECLARE(ftdm_status_t) get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data)
+ftdm_status_t get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data)
{
ftdm_assert_return((cc_id > 0 && cc_id <=MAX_VARIANTS), FTDM_FAIL, "Invalid cc_id\n");
ftdm_assert_return(g_sngisdn_data.ccs[cc_id].activation_done, FTDM_FAIL, "Trying to find call on unconfigured CC\n");
@@ -127,9 +136,8 @@ FT_DECLARE(ftdm_status_t) get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spIns
return FTDM_SUCCESS;
}
-ftdm_status_t sng_isdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail)
+ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail)
{
-
if (span->trunk_type == FTDM_TRUNK_BRI ||
span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
@@ -147,77 +155,117 @@ ftdm_status_t sng_isdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail)
return FTDM_SUCCESS;
}
-FT_DECLARE(ftdm_status_t) cpy_calling_num_from_stack(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb)
+ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
{
+ ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
if (cgPtyNmb->eh.pres != PRSNT_NODEF) {
return FTDM_FAIL;
}
if (cgPtyNmb->screenInd.pres == PRSNT_NODEF) {
- ftdm->screen = cgPtyNmb->screenInd.val;
+ caller_data->screen = cgPtyNmb->screenInd.val;
}
if (cgPtyNmb->presInd0.pres == PRSNT_NODEF) {
- ftdm->pres = cgPtyNmb->presInd0.val;
+ caller_data->pres = cgPtyNmb->presInd0.val;
}
if (cgPtyNmb->nmbPlanId.pres == PRSNT_NODEF) {
- ftdm->cid_num.plan = cgPtyNmb->nmbPlanId.val;
+ caller_data->cid_num.plan = cgPtyNmb->nmbPlanId.val;
}
+
if (cgPtyNmb->typeNmb1.pres == PRSNT_NODEF) {
- ftdm->cid_num.type = cgPtyNmb->typeNmb1.val;
+ caller_data->cid_num.type = cgPtyNmb->typeNmb1.val;
}
if (cgPtyNmb->nmbDigits.pres == PRSNT_NODEF) {
- ftdm_copy_string(ftdm->cid_num.digits, (const char*)cgPtyNmb->nmbDigits.val, cgPtyNmb->nmbDigits.len+1);
+ ftdm_copy_string(caller_data->cid_num.digits, (const char*)cgPtyNmb->nmbDigits.val, cgPtyNmb->nmbDigits.len+1);
}
+ memcpy(&caller_data->ani, &caller_data->cid_num, sizeof(caller_data->ani));
return FTDM_SUCCESS;
}
-FT_DECLARE(ftdm_status_t) cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb)
+ftdm_status_t get_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
{
+ ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
+ if (cgPtyNmb->eh.pres != PRSNT_NODEF) {
+ return FTDM_FAIL;
+ }
+
+ if (cgPtyNmb->screenInd.pres == PRSNT_NODEF) {
+ ftdm_call_add_var(caller_data, "isdn.cg_pty2.screen_ind", ftdm_screening2str(cgPtyNmb->screenInd.val));
+ }
+
+ if (cgPtyNmb->presInd0.pres == PRSNT_NODEF) {
+ ftdm_call_add_var(caller_data, "isdn.cg_pty2.presentation_ind", ftdm_presentation2str(cgPtyNmb->presInd0.val));
+ }
+
+ if (cgPtyNmb->nmbPlanId.pres == PRSNT_NODEF) {
+ ftdm_call_add_var(caller_data, "isdn.cg_pty2.npi", ftdm_npi2str(cgPtyNmb->nmbPlanId.val));
+ }
+
+ if (cgPtyNmb->typeNmb1.pres == PRSNT_NODEF) {
+ ftdm_call_add_var(caller_data, "isdn.cg_pty2.ton", ftdm_ton2str(cgPtyNmb->typeNmb1.val));
+ }
+
+ if (cgPtyNmb->nmbDigits.pres == PRSNT_NODEF) {
+ char digits_string [32];
+ memcpy(digits_string, (const char*)cgPtyNmb->nmbDigits.val, cgPtyNmb->nmbDigits.len);
+ digits_string[cgPtyNmb->nmbDigits.len] = '\0';
+ ftdm_call_add_var(caller_data, "isdn.cg_pty2.digits", digits_string);
+ }
+ memcpy(&caller_data->ani, &caller_data->cid_num, sizeof(caller_data->ani));
+ return FTDM_SUCCESS;
+}
+
+ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb)
+{
+ ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
if (cdPtyNmb->eh.pres != PRSNT_NODEF) {
return FTDM_FAIL;
}
if (cdPtyNmb->nmbPlanId.pres == PRSNT_NODEF) {
- ftdm->dnis.plan = cdPtyNmb->nmbPlanId.val;
+ caller_data->dnis.plan = cdPtyNmb->nmbPlanId.val;
}
if (cdPtyNmb->typeNmb0.pres == PRSNT_NODEF) {
- ftdm->dnis.type = cdPtyNmb->typeNmb0.val;
+ caller_data->dnis.type = cdPtyNmb->typeNmb0.val;
}
if (cdPtyNmb->nmbDigits.pres == PRSNT_NODEF) {
- unsigned i = strlen(ftdm->dnis.digits);
+ /* In overlap receive mode, append the new digits to the existing dnis */
+ unsigned i = strlen(caller_data->dnis.digits);
- ftdm_copy_string(&ftdm->dnis.digits[i], (const char*)cdPtyNmb->nmbDigits.val, cdPtyNmb->nmbDigits.len+1);
+ ftdm_copy_string(&caller_data->dnis.digits[i], (const char*)cdPtyNmb->nmbDigits.val, cdPtyNmb->nmbDigits.len+1);
}
return FTDM_SUCCESS;
}
-FT_DECLARE(ftdm_status_t) cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb)
+ftdm_status_t get_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb)
{
+ ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
if (redirNmb->eh.pres != PRSNT_NODEF) {
return FTDM_FAIL;
}
if (redirNmb->nmbPlanId.pres == PRSNT_NODEF) {
- ftdm->rdnis.plan = redirNmb->nmbPlanId.val;
+ caller_data->rdnis.plan = redirNmb->nmbPlanId.val;
}
if (redirNmb->typeNmb.pres == PRSNT_NODEF) {
- ftdm->rdnis.type = redirNmb->typeNmb.val;
+ caller_data->rdnis.type = redirNmb->typeNmb.val;
}
if (redirNmb->nmbDigits.pres == PRSNT_NODEF) {
- ftdm_copy_string(ftdm->rdnis.digits, (const char*)redirNmb->nmbDigits.val, redirNmb->nmbDigits.len+1);
+ ftdm_copy_string(caller_data->rdnis.digits, (const char*)redirNmb->nmbDigits.val, redirNmb->nmbDigits.len+1);
}
return FTDM_SUCCESS;
}
-FT_DECLARE(ftdm_status_t) cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *display)
+ftdm_status_t get_calling_name_from_display(ftdm_channel_t *ftdmchan, Display *display)
{
+ ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
if (display->eh.pres != PRSNT_NODEF) {
return FTDM_FAIL;
}
@@ -225,71 +273,307 @@ FT_DECLARE(ftdm_status_t) cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm,
return FTDM_FAIL;
}
- ftdm_copy_string(ftdm->cid_name, (const char*)display->dispInfo.val, display->dispInfo.len+1);
+ ftdm_copy_string(caller_data->cid_name, (const char*)display->dispInfo.val, display->dispInfo.len+1);
return FTDM_SUCCESS;
}
-FT_DECLARE(ftdm_status_t) cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm)
+ftdm_status_t get_calling_name_from_usr_usr(ftdm_channel_t *ftdmchan, UsrUsr *usrUsr)
{
- uint8_t len = strlen(ftdm->cid_num.digits);
+ ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
+ if (usrUsr->eh.pres != PRSNT_NODEF) {
+ return FTDM_FAIL;
+ }
+
+ if (usrUsr->protocolDisc.val != PD_IA5) {
+ return FTDM_FAIL;
+ }
+
+ if (usrUsr->usrInfo.pres != PRSNT_NODEF) {
+ return FTDM_FAIL;
+ }
+
+ ftdm_copy_string(caller_data->cid_name, (const char*)usrUsr->usrInfo.val, usrUsr->usrInfo.len+1);
+ return FTDM_SUCCESS;
+}
+
+ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
+{
+ char subaddress[100];
+
+ if (cgPtySad->eh.pres != PRSNT_NODEF) {
+ return FTDM_FAIL;
+ }
+ memset(subaddress, 0, sizeof(subaddress));
+ if(cgPtySad->sadInfo.len >= sizeof(subaddress)) {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Calling Party Subaddress exceeds local size limit (len:%d max:%d)\n", cgPtySad->sadInfo.len, sizeof(subaddress));
+ cgPtySad->sadInfo.len = sizeof(subaddress)-1;
+ }
+
+ memcpy(subaddress, (char*)cgPtySad->sadInfo.val, cgPtySad->sadInfo.len);
+ subaddress[cgPtySad->sadInfo.len] = '\0';
+ ftdm_call_add_var(&ftdmchan->caller_data, "isdn.calling_subaddr", subaddress);
+ return FTDM_SUCCESS;
+}
+
+ftdm_status_t get_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr)
+{
+ if (!facilityStr->eh.pres) {
+ return FTDM_FAIL;
+ }
+
+ return get_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, facilityStr->facilityStr.len);
+}
+
+ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t data_len)
+{
+ ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
+ sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
+
+ if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) {
+ /* size of facilityStr->facilityStr.len is a uint8_t so no need to check
+ for overflow here as facilityStr->facilityStr.len will always be smaller
+ than sizeof(caller_data->raw_data) */
+
+ memset(caller_data->raw_data, 0, sizeof(caller_data->raw_data));
+ /* Always include Facility IE identifier + len so this can be used as a sanity check by the user */
+ caller_data->raw_data[0] = SNGISDN_Q931_FACILITY_IE_ID;
+ caller_data->raw_data[1] = data_len;
+
+ memcpy(&caller_data->raw_data[2], data, data_len);
+ caller_data->raw_data_len = data_len+2;
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Raw Facility IE copied available\n");
+ } else {
+ /* Call libsng_isdn to process facility IE's here */
+ }
+ return FTDM_SUCCESS;
+}
+
+ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd)
+{
+ uint8_t val;
+ if (!progInd->eh.pres) {
+ return FTDM_FAIL;
+ }
+
+ if (progInd->progDesc.pres) {
+ switch (progInd->progDesc.val) {
+ case IN_PD_NOTETEISDN:
+ val = SNGISDN_PROGIND_DESCR_NETE_ISDN;
+ break;
+ case IN_PD_DSTNOTISDN:
+ val = SNGISDN_PROGIND_DESCR_DEST_NISDN;
+ break;
+ case IN_PD_ORGNOTISDN:
+ val = SNGISDN_PROGIND_DESCR_ORIG_NISDN;
+ break;
+ case IN_PD_CALLRET:
+ val = SNGISDN_PROGIND_DESCR_RET_ISDN;
+ break;
+ case IN_PD_DELRESP:
+ val = SNGISDN_PROGIND_DESCR_SERV_CHANGE;
+ break;
+ case IN_PD_IBAVAIL:
+ val = SNGISDN_PROGIND_DESCR_IB_AVAIL;
+ break;
+ default:
+ ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unknown Progress Indicator Description (%d)\n", progInd->progDesc.val);
+ val = SNGISDN_PROGIND_DESCR_INVALID;
+ break;
+ }
+ ftdm_call_add_var(&ftdmchan->caller_data, "isdn.prog_ind.descr", ftdm_sngisdn_progind_descr2str(val));
+ }
+
+ if (progInd->location.pres) {
+ switch (progInd->location.val) {
+ case IN_LOC_USER:
+ val = SNGISDN_PROGIND_LOC_USER;
+ break;
+ case IN_LOC_PRIVNETLU:
+ val = SNGISDN_PROGIND_LOC_PRIV_NET_LOCAL_USR;
+ break;
+ case IN_LOC_PUBNETLU:
+ val = SNGISDN_PROGIND_LOC_PUB_NET_LOCAL_USR;
+ break;
+ case IN_LOC_TRANNET:
+ val = SNGISDN_PROGIND_LOC_TRANSIT_NET;
+ break;
+ case IN_LOC_PUBNETRU:
+ val = SNGISDN_PROGIND_LOC_PUB_NET_REMOTE_USR;
+ break;
+ case IN_LOC_PRIVNETRU:
+ val = SNGISDN_PROGIND_LOC_PRIV_NET_REMOTE_USR;
+ break;
+ case IN_LOC_NETINTER:
+ val = SNGISDN_PROGIND_LOC_NET_BEYOND_INTRW;
+ break;
+ default:
+ ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unknown Progress Indicator Location (%d)", progInd->location.val);
+ val = SNGISDN_PROGIND_LOC_INVALID;
+ break;
+ }
+ ftdm_call_add_var(&ftdmchan->caller_data, "isdn.prog_ind.loc", ftdm_sngisdn_progind_loc2str(val));
+ }
+ return FTDM_SUCCESS;
+}
+
+
+ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
+{
+ ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
+ uint8_t len = strlen(caller_data->cid_num.digits);
if (!len) {
return FTDM_SUCCESS;
}
cgPtyNmb->eh.pres = PRSNT_NODEF;
cgPtyNmb->screenInd.pres = PRSNT_NODEF;
- cgPtyNmb->screenInd.val = ftdm->screen;
+ cgPtyNmb->screenInd.val = caller_data->screen;
cgPtyNmb->presInd0.pres = PRSNT_NODEF;
- cgPtyNmb->presInd0.val = ftdm->pres;
-
+ cgPtyNmb->presInd0.val = caller_data->pres;
+
cgPtyNmb->nmbPlanId.pres = PRSNT_NODEF;
- cgPtyNmb->nmbPlanId.val = ftdm->cid_num.plan;
+ if (caller_data->cid_num.plan >= FTDM_NPI_INVALID) {
+ cgPtyNmb->nmbPlanId.val = FTDM_NPI_UNKNOWN;
+ } else {
+ cgPtyNmb->nmbPlanId.val = caller_data->cid_num.plan;
+ }
cgPtyNmb->typeNmb1.pres = PRSNT_NODEF;
- cgPtyNmb->typeNmb1.val = ftdm->cid_num.type;
+
+ if (caller_data->cid_num.type >= FTDM_TON_INVALID) {
+ cgPtyNmb->typeNmb1.val = FTDM_TON_UNKNOWN;
+ } else {
+ cgPtyNmb->typeNmb1.val = caller_data->cid_num.type;
+ }
cgPtyNmb->nmbDigits.pres = PRSNT_NODEF;
cgPtyNmb->nmbDigits.len = len;
- memcpy(cgPtyNmb->nmbDigits.val, ftdm->cid_num.digits, len);
+ memcpy(cgPtyNmb->nmbDigits.val, caller_data->cid_num.digits, len);
return FTDM_SUCCESS;
}
-FT_DECLARE(ftdm_status_t) cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm)
+ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
{
- uint8_t len = strlen(ftdm->dnis.digits);
+ const char* string = NULL;
+ uint8_t len,val;
+ ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
+
+ string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.digits");
+ if ((string == NULL) || !(*string)) {
+ return FTDM_FAIL;
+ }
+
+ cgPtyNmb->eh.pres = PRSNT_NODEF;
+
+ len = strlen(string);
+ cgPtyNmb->nmbDigits.len = len;
+
+ cgPtyNmb->nmbDigits.pres = PRSNT_NODEF;
+ memcpy(cgPtyNmb->nmbDigits.val, string, len);
+
+ /* Screening Indicator */
+ cgPtyNmb->screenInd.pres = PRSNT_NODEF;
+
+ val = FTDM_SCREENING_INVALID;
+ string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.screening_ind");
+ if ((string != NULL) && (*string)) {
+ val = ftdm_str2ftdm_screening(string);
+ }
+
+ /* isdn.cg_pty2.screen_ind does not exist or we could not parse its value */
+ if (val == FTDM_SCREENING_INVALID) {
+ /* default to caller data screening ind */
+ cgPtyNmb->screenInd.val = caller_data->screen;
+ } else {
+ cgPtyNmb->screenInd.val = val;
+ }
+
+ /* Presentation Indicator */
+ cgPtyNmb->presInd0.pres = PRSNT_NODEF;
+
+ val = FTDM_PRES_INVALID;
+ string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.presentation_ind");
+ if ((string != NULL) && (*string)) {
+ val = ftdm_str2ftdm_presentation(string);
+ }
+
+ if (val == FTDM_PRES_INVALID) {
+ cgPtyNmb->presInd0.val = caller_data->pres;
+ } else {
+ cgPtyNmb->presInd0.val = val;
+ }
+
+ /* Numbering Plan Indicator */
+ cgPtyNmb->nmbPlanId.pres = PRSNT_NODEF;
+
+ val = FTDM_NPI_INVALID;
+ string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.npi");
+ if ((string != NULL) && (*string)) {
+ val = ftdm_str2ftdm_npi(string);
+ }
+
+ if (val == FTDM_NPI_INVALID) {
+ cgPtyNmb->nmbPlanId.val = caller_data->cid_num.plan;
+ } else {
+ cgPtyNmb->nmbPlanId.val = val;
+ }
+
+ cgPtyNmb->typeNmb1.pres = PRSNT_NODEF;
+
+ /* Type of Number */
+ val = FTDM_TON_INVALID;
+ string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.ton");
+ if ((string != NULL) && (*string)) {
+ val = ftdm_str2ftdm_ton(string);
+ }
+
+ if (val == FTDM_TON_INVALID) {
+ cgPtyNmb->typeNmb1.val = caller_data->cid_num.type;
+ } else {
+ cgPtyNmb->typeNmb1.val = val;
+ }
+ return FTDM_SUCCESS;
+}
+
+ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb)
+{
+ ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
+ uint8_t len = strlen(caller_data->dnis.digits);
+
if (!len) {
return FTDM_SUCCESS;
}
cdPtyNmb->eh.pres = PRSNT_NODEF;
cdPtyNmb->nmbPlanId.pres = PRSNT_NODEF;
- if (ftdm->dnis.plan == FTDM_NPI_INVALID) {
+ if (caller_data->dnis.plan >= FTDM_NPI_INVALID) {
cdPtyNmb->nmbPlanId.val = FTDM_NPI_UNKNOWN;
} else {
- cdPtyNmb->nmbPlanId.val = ftdm->dnis.plan;
+ cdPtyNmb->nmbPlanId.val = caller_data->dnis.plan;
}
cdPtyNmb->typeNmb0.pres = PRSNT_NODEF;
- if (ftdm->dnis.type == FTDM_TON_INVALID) {
+ if (caller_data->dnis.type >= FTDM_TON_INVALID) {
cdPtyNmb->typeNmb0.val = FTDM_TON_UNKNOWN;
} else {
- cdPtyNmb->typeNmb0.val = ftdm->dnis.type;
+ cdPtyNmb->typeNmb0.val = caller_data->dnis.type;
}
cdPtyNmb->nmbDigits.pres = PRSNT_NODEF;
cdPtyNmb->nmbDigits.len = len;
- memcpy(cdPtyNmb->nmbDigits.val, ftdm->dnis.digits, len);
+ memcpy(cdPtyNmb->nmbDigits.val, caller_data->dnis.digits, len);
return FTDM_SUCCESS;
}
-FT_DECLARE(ftdm_status_t) cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm)
+ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb)
{
- uint8_t len = strlen(ftdm->rdnis.digits);
+ ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
+ uint8_t len = strlen(caller_data->rdnis.digits);
if (!len) {
return FTDM_SUCCESS;
}
@@ -297,36 +581,36 @@ FT_DECLARE(ftdm_status_t) cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_calle
redirNmb->eh.pres = PRSNT_NODEF;
redirNmb->nmbPlanId.pres = PRSNT_NODEF;
- if (ftdm->rdnis.plan == FTDM_NPI_INVALID) {
+ if (caller_data->rdnis.plan >= FTDM_NPI_INVALID) {
redirNmb->nmbPlanId.val = FTDM_NPI_UNKNOWN;
} else {
- redirNmb->nmbPlanId.val = ftdm->rdnis.plan;
+ redirNmb->nmbPlanId.val = caller_data->rdnis.plan;
}
redirNmb->typeNmb.pres = PRSNT_NODEF;
- if (ftdm->rdnis.type == FTDM_TON_INVALID) {
+ if (caller_data->rdnis.type >= FTDM_TON_INVALID) {
redirNmb->typeNmb.val = FTDM_TON_UNKNOWN;
} else {
- redirNmb->typeNmb.val = ftdm->rdnis.type;
+ redirNmb->typeNmb.val = caller_data->rdnis.type;
}
redirNmb->nmbDigits.pres = PRSNT_NODEF;
redirNmb->nmbDigits.len = len;
- memcpy(redirNmb->nmbDigits.val, ftdm->rdnis.digits, len);
+ memcpy(redirNmb->nmbDigits.val, caller_data->rdnis.digits, len);
return FTDM_SUCCESS;
}
-FT_DECLARE(ftdm_status_t) cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan)
+ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt)
{
uint8_t len;
- ftdm_caller_data_t *ftdm = &ftdmchan->caller_data;
+ ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
/* sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; */
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
- len = strlen(ftdm->cid_name);
+ len = strlen(caller_data->cid_name);
if (!len) {
return FTDM_SUCCESS;
}
@@ -341,7 +625,7 @@ FT_DECLARE(ftdm_status_t) cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_chan
conEvnt->usrUsr.usrInfo.len = len;
/* in sangoma_brid we used to send usr-usr info as !,
change to previous style if current one does not work */
- memcpy(conEvnt->usrUsr.usrInfo.val, ftdm->cid_name, len);
+ memcpy(conEvnt->usrUsr.usrInfo.val, caller_data->cid_name, len);
} else {
switch (signal_data->switchtype) {
case SNGISDN_SWITCH_NI2:
@@ -359,7 +643,7 @@ FT_DECLARE(ftdm_status_t) cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_chan
conEvnt->display.eh.pres = PRSNT_NODEF;
conEvnt->display.dispInfo.pres = PRSNT_NODEF;
conEvnt->display.dispInfo.len = len;
- memcpy(conEvnt->display.dispInfo.val, ftdm->cid_name, len);
+ memcpy(conEvnt->display.dispInfo.val, caller_data->cid_name, len);
break;
case SNGISDN_SWITCH_QSIG:
/* It seems like QSIG does not support Caller ID Name */
@@ -372,6 +656,140 @@ FT_DECLARE(ftdm_status_t) cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_chan
return FTDM_SUCCESS;
}
+ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
+{
+ const char* clg_subaddr = NULL;
+ clg_subaddr = ftdm_call_get_var(&ftdmchan->caller_data, "isdn.calling_subaddr");
+ if ((clg_subaddr != NULL) && (*clg_subaddr)) {
+ unsigned len = strlen (clg_subaddr);
+ cgPtySad->eh.pres = PRSNT_NODEF;
+ cgPtySad->typeSad.pres = 1;
+ cgPtySad->typeSad.val = 0; /* NSAP */
+ cgPtySad->oddEvenInd.pres = 1;
+ cgPtySad->oddEvenInd.val = 0;
+
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending Calling Party Subaddress:%s\n", clg_subaddr);
+ cgPtySad->sadInfo.pres = 1;
+ cgPtySad->sadInfo.len = len;
+ memcpy(cgPtySad->sadInfo.val, clg_subaddr, len);
+ }
+ return FTDM_SUCCESS;
+}
+
+
+ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr)
+{
+ ftdm_status_t status;
+ status = set_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, (uint8_t*)&(facilityStr->facilityStr.len));
+ if (status == FTDM_SUCCESS) {
+ facilityStr->eh.pres = PRSNT_NODEF;
+ facilityStr->facilityStr.pres = PRSNT_NODEF;
+ }
+ return status;
+}
+
+ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t *data_len)
+{
+ int len;
+ ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
+
+ if (caller_data->raw_data_len > 0 && caller_data->raw_data[0] == SNGISDN_Q931_FACILITY_IE_ID) {
+ len = caller_data->raw_data[1];
+ memcpy(data, &caller_data->raw_data[2], len);
+ *data_len = len;
+ return FTDM_SUCCESS;
+ }
+ return FTDM_FAIL;
+}
+
+ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind)
+{
+ const char *str = NULL;
+ int descr = prog_ind.descr;
+ int loc = prog_ind.loc;
+
+ str = ftdm_call_get_var(&ftdmchan->caller_data, "isdn.prog_ind.descr");
+ if (str && *str) {
+ /* User wants to override progress indicator */
+ descr = ftdm_str2ftdm_sngisdn_progind_descr(str);
+ }
+
+ if (descr == SNGISDN_PROGIND_DESCR_INVALID) {
+ /* User does not want to send progress indicator */
+ return FTDM_SUCCESS;
+ }
+
+ str = ftdm_call_get_var(&ftdmchan->caller_data, "isdn.prog_ind.loc");
+ if (str && *str) {
+ loc = ftdm_str2ftdm_sngisdn_progind_loc(str);
+ }
+ if (loc == SNGISDN_PROGIND_LOC_INVALID) {
+ loc = SNGISDN_PROGIND_LOC_USER;
+ }
+
+ progInd->eh.pres = PRSNT_NODEF;
+ progInd->codeStand0.pres = PRSNT_NODEF;
+ progInd->codeStand0.val = IN_CSTD_CCITT;
+
+ progInd->progDesc.pres = PRSNT_NODEF;
+ switch(descr) {
+ case SNGISDN_PROGIND_DESCR_NETE_ISDN:
+ progInd->progDesc.val = IN_PD_NOTETEISDN;
+ break;
+ case SNGISDN_PROGIND_DESCR_DEST_NISDN:
+ progInd->progDesc.val = IN_PD_DSTNOTISDN;
+ break;
+ case SNGISDN_PROGIND_DESCR_ORIG_NISDN:
+ progInd->progDesc.val = IN_PD_ORGNOTISDN;
+ break;
+ case SNGISDN_PROGIND_DESCR_RET_ISDN:
+ progInd->progDesc.val = IN_PD_CALLRET;
+ break;
+ case SNGISDN_PROGIND_DESCR_SERV_CHANGE:
+ /* Trillium defines do not match ITU-T Q931 Progress descriptions,
+ indicate a delayed response for now */
+ progInd->progDesc.val = IN_PD_DELRESP;
+ break;
+ case SNGISDN_PROGIND_DESCR_IB_AVAIL:
+ progInd->progDesc.val = IN_PD_IBAVAIL;
+ break;
+ default:
+ ftdm_log(FTDM_LOG_WARNING, "Invalid prog_ind description:%d\n", descr);
+ progInd->progDesc.val = IN_PD_NOTETEISDN;
+ break;
+ }
+
+ progInd->location.pres = PRSNT_NODEF;
+ switch (loc) {
+ case SNGISDN_PROGIND_LOC_USER:
+ progInd->location.val = IN_LOC_USER;
+ break;
+ case SNGISDN_PROGIND_LOC_PRIV_NET_LOCAL_USR:
+ progInd->location.val = IN_LOC_PRIVNETLU;
+ break;
+ case SNGISDN_PROGIND_LOC_PUB_NET_LOCAL_USR:
+ progInd->location.val = IN_LOC_PUBNETLU;
+ break;
+ case SNGISDN_PROGIND_LOC_TRANSIT_NET:
+ progInd->location.val = IN_LOC_TRANNET;
+ break;
+ case SNGISDN_PROGIND_LOC_PUB_NET_REMOTE_USR:
+ progInd->location.val = IN_LOC_PUBNETRU;
+ break;
+ case SNGISDN_PROGIND_LOC_PRIV_NET_REMOTE_USR:
+ progInd->location.val = IN_LOC_PRIVNETRU;
+ break;
+ case SNGISDN_PROGIND_LOC_NET_BEYOND_INTRW:
+ progInd->location.val = IN_LOC_NETINTER;
+ break;
+ default:
+ ftdm_log(FTDM_LOG_WARNING, "Invalid prog_ind location:%d\n", loc);
+ progInd->location.val = IN_PD_NOTETEISDN;
+ }
+ return FTDM_SUCCESS;
+}
+
+
void sngisdn_t3_timeout(void* p_sngisdn_info)
{
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;
@@ -394,6 +812,17 @@ void sngisdn_t3_timeout(void* p_sngisdn_info)
ftdm_mutex_unlock(ftdmchan->mutex);
}
+void sngisdn_delayed_setup(void* p_sngisdn_info)
+{
+ sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;
+ ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
+
+ ftdm_mutex_lock(ftdmchan->mutex);
+ sngisdn_snd_setup(ftdmchan);
+ ftdm_mutex_unlock(ftdmchan->mutex);
+ return;
+}
+
void sngisdn_delayed_release(void* p_sngisdn_info)
{
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;
@@ -517,13 +946,12 @@ uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability)
switch(bearer_capability) {
case FTDM_BEARER_CAP_SPEECH:
return IN_ITC_SPEECH;
-
case FTDM_BEARER_CAP_64K_UNRESTRICTED:
return IN_ITC_UNRDIG;
-
case FTDM_BEARER_CAP_3_1KHZ_AUDIO:
return IN_ITC_A31KHZ;
-
+ case FTDM_BEARER_CAP_INVALID:
+ return IN_ITC_SPEECH;
/* Do not put a default case here, so we can see compile warnings if we have unhandled cases */
}
return FTDM_BEARER_CAP_SPEECH;
@@ -534,13 +962,12 @@ uint8_t sngisdn_get_usrInfoLyr1Prot_from_stack(ftdm_user_layer1_prot_t layer1_pr
switch(layer1_prot) {
case FTDM_USER_LAYER1_PROT_V110:
return IN_UIL1_CCITTV110;
-
case FTDM_USER_LAYER1_PROT_ULAW:
return IN_UIL1_G711ULAW;
-
case FTDM_USER_LAYER1_PROT_ALAW:
return IN_UIL1_G711ALAW;
-
+ case FTDM_USER_LAYER1_PROT_INVALID:
+ return IN_UIL1_G711ULAW;
/* Do not put a default case here, so we can see compile warnings if we have unhandled cases */
}
return IN_UIL1_G711ULAW;
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c
index 624d35c147..e5167164b3 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c
@@ -613,6 +613,21 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset
return 0;
break;
case PROT_Q931_IE_CALLED_PARTY_SUBADDRESS:
+ {
+ uint8_t type;
+ uint8_t currentOct, j=0;
+ char calling_subaddr_string[82];
+ memset(calling_subaddr_string, 0, sizeof(calling_subaddr_string));
+ type = get_bits(OCTET(3),5,7);
+ currentOct = 3;
+ while(currentOct++ <= len+1) {
+ calling_subaddr_string[j++]=ia5[get_bits(OCTET(currentOct),1,4)][get_bits(OCTET(currentOct),5,8)];
+ }
+ calling_subaddr_string[j++]='\0';
+ *str_len += sprintf(&str[*str_len], "%s (l:%d) type:%s(%d) \n",
+ calling_subaddr_string, (j-1), get_code_2_str(type, dcodQ931TypeOfSubaddressTable), type);
+ }
+ break;
case PROT_Q931_IE_REDIRECTION_NUMBER:
case PROT_Q931_IE_NOTIFICATION_IND:
case PROT_Q931_IE_DATE_TIME:
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h
index d210c50db9..f054de9377 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h
@@ -544,5 +544,11 @@ struct code2str dcodQ931GenDigitsTypeTable[] = {
{-1, "Invalid"},
};
+struct code2str dcodQ931TypeOfSubaddressTable[] = {
+ { 0x00, "NSAP"},
+ { 0x02, "User-specified"},
+ { -1, "Invalid"},
+};
+
#endif /* __FTMOD_SANGOMA_ISDN_TRACE_H__ */
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 72e4bacf52..7517ee42a0 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
@@ -211,10 +211,10 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* add any special variables for the dialplan */
sprintf(nadi, "%d", siConEvnt->cgPtyNum.natAddrInd.val);
- ftdm_channel_add_var(ftdmchan, "ss7_clg_nadi", nadi);
+ ftdm_call_add_var(&ftdmchan->caller_data, "ss7_clg_nadi", nadi);
sprintf(nadi, "%d", siConEvnt->cdPtyNum.natAddrInd.val);
- ftdm_channel_add_var(ftdmchan, "ss7_cld_nadi", nadi);
+ ftdm_call_add_var(&ftdmchan->caller_data, "ss7_cld_nadi", nadi);
/* check if a COT test is requested */
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 304e9d6ce3..5c171a9f6b 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
@@ -502,6 +502,8 @@ void 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;
@@ -521,8 +523,8 @@ void 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 >= g_ftdm_sngss7_data.min_digits) {
- SS7_DEBUG_CHAN(ftdmchan, "Received %d digits (min digits = %d)\n", i, g_ftdm_sngss7_data.min_digits);
+ } else if (i >= isup_intf->min_digits) {
+ SS7_DEBUG_CHAN(ftdmchan, "Received %d digits (min digits = %d)\n", i, isup_intf->min_digits);
/*now go to the RING state */
ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING);
@@ -532,7 +534,7 @@ void 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,
- g_ftdm_sngss7_data.min_digits,
+ isup_intf->min_digits,
ftdmchan->caller_data.dnis.digits);
/* start ISUP t35 */
@@ -1520,9 +1522,6 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_ss7_init)
/* initalize the global gen_config flag */
g_ftdm_sngss7_data.gen_config = 0;
- /* min. number of digitis to wait for */
- g_ftdm_sngss7_data.min_digits = 7;
-
/* function trace initizalation */
g_ftdm_sngss7_data.function_trace = 1;
g_ftdm_sngss7_data.function_trace_level = 7;
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 378b50e0ad..fe4b6f45c4 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
@@ -50,7 +50,7 @@
/******************************************************************************/
/* DEFINES ********************************************************************/
-#define MAX_NAME_LEN 10
+#define MAX_NAME_LEN 25
#define MAX_PATH 255
#define MAX_CIC_LENGTH 5
@@ -224,6 +224,7 @@ typedef struct sng_isup_intf {
uint32_t isap;
uint32_t clg_nadi;
uint32_t cld_nadi;
+ uint32_t min_digits;
uint16_t t4;
uint32_t t10;
uint32_t t11;
@@ -326,7 +327,6 @@ typedef struct sng_ss7_cfg {
typedef struct ftdm_sngss7_data {
sng_ss7_cfg_t cfg;
int gen_config;
- int min_digits;
int function_trace;
int function_trace_level;
int message_trace;
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 008265b9a4..ec8d7df12a 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
@@ -187,7 +187,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
copy_cgPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cgPtyNum);
/* check if the user would like a custom NADI value for the calling Pty Num */
- clg_nadi = ftdm_channel_get_var(ftdmchan, "ss7_clg_nadi");
+ clg_nadi = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_clg_nadi");
if ((clg_nadi != NULL) && (*clg_nadi)) {
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Calling NADI value \"%s\"\n", clg_nadi);
iam.cgPtyNum.natAddrInd.val = atoi(clg_nadi);
@@ -196,7 +196,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
SS7_DEBUG_CHAN(ftdmchan,"No user supplied NADI value found for CLG, using \"%d\"\n", iam.cgPtyNum.natAddrInd.val);
}
- cld_nadi = ftdm_channel_get_var(ftdmchan, "ss7_cld_nadi");
+ cld_nadi = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_cld_nadi");
if ((cld_nadi != NULL) && (*cld_nadi)) {
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Called NADI value \"%s\"\n", cld_nadi);
iam.cdPtyNum.natAddrInd.val = atoi(cld_nadi);
@@ -206,7 +206,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
}
/* check if the user would like us to send a clg_sub-address */
- clg_subAddr = ftdm_channel_get_var(ftdmchan, "ss7_clg_subaddr");
+ clg_subAddr = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_clg_subaddr");
if ((clg_subAddr != NULL) && (*clg_subAddr)) {
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Calling Sub-Address value \"%s\"\n", clg_subAddr);
@@ -245,7 +245,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
}
/* check if the user would like us to send a cld_sub-address */
- cld_subAddr = ftdm_channel_get_var(ftdmchan, "ss7_cld_subaddr");
+ cld_subAddr = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_cld_subaddr");
if ((cld_subAddr != NULL) && (*cld_subAddr)) {
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Called Sub-Address value \"%s\"\n", cld_subAddr);
@@ -298,7 +298,8 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
iam.cgPtyNum.natAddrInd.val,
ftdmchan->caller_data.dnis.digits,
iam.cdPtyNum.natAddrInd.val);
-
+
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -379,7 +380,7 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
ADDRCMPLT);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ACM\n", sngss7_info->circuit->cic);
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -403,7 +404,7 @@ void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan)
5);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ANM\n", sngss7_info->circuit->cic);
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -438,7 +439,7 @@ void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan)
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx REL cause=%d \n",
sngss7_info->circuit->cic,
ftdmchan->caller_data.hangup_cause );
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -461,7 +462,7 @@ void ft_to_sngss7_rlc (ftdm_channel_t * ftdmchan)
&rlc);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RLC\n", sngss7_info->circuit->cic);
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -482,7 +483,7 @@ void ft_to_sngss7_rsc (ftdm_channel_t * ftdmchan)
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RSC\n", sngss7_info->circuit->cic);
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -503,7 +504,7 @@ void ft_to_sngss7_rsca (ftdm_channel_t * ftdmchan)
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RSC-RLC\n", sngss7_info->circuit->cic);
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -524,7 +525,7 @@ void ft_to_sngss7_blo (ftdm_channel_t * ftdmchan)
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx BLO\n", sngss7_info->circuit->cic);
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -545,7 +546,7 @@ void ft_to_sngss7_bla (ftdm_channel_t * ftdmchan)
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx BLA\n", sngss7_info->circuit->cic);
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -567,7 +568,7 @@ ft_to_sngss7_ubl (ftdm_channel_t * ftdmchan)
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx UBL\n", sngss7_info->circuit->cic);
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -588,7 +589,7 @@ void ft_to_sngss7_uba (ftdm_channel_t * ftdmchan)
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx UBA\n", sngss7_info->circuit->cic);
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -609,7 +610,7 @@ void ft_to_sngss7_lpa (ftdm_channel_t * ftdmchan)
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx LPA\n", sngss7_info->circuit->cic);
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -654,6 +655,7 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan)
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->rx_grs.range));
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -686,7 +688,8 @@ void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan)
sngss7_info->circuit->cic,
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->tx_grs.range));
-
+
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -735,7 +738,7 @@ void ft_to_sngss7_cgba(ftdm_channel_t * ftdmchan)
/* clean out the saved data */
memset(&sngss7_span->rx_cgb, 0x0, sizeof(sngss7_group_data_t));
-
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -785,6 +788,7 @@ void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan)
/* clean out the saved data */
memset(&sngss7_span->rx_cgu, 0x0, sizeof(sngss7_group_data_t));
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -835,6 +839,7 @@ void ft_to_sngss7_cgb(ftdm_channel_t * ftdmchan)
/* clean out the saved data */
memset(&sngss7_span->tx_cgb, 0x0, sizeof(sngss7_group_data_t));
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@@ -885,6 +890,7 @@ void ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan)
/* clean out the saved data */
memset(&sngss7_span->tx_cgu, 0x0, sizeof(sngss7_group_data_t));
+ ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
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 4a9c863b12..d4fd1ca9b3 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
@@ -142,7 +142,7 @@ int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *spa
if (!strcasecmp(var, "ch_map")) {
/**********************************************************************/
- strcpy(isupCkt.ch_map, val);
+ 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")) {
@@ -393,7 +393,7 @@ static int ftmod_ss7_parse_mtp_linkset(ftdm_conf_node_t *mtp_linkset)
for (i = 0; i < num_parms; i++) {
/**********************************************************************/
if (!strcasecmp(parm->var, "name")) {
- strcpy((char *)mtpLinkSet.name, parm->val);
+ 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")) {
@@ -508,7 +508,7 @@ static int ftmod_ss7_parse_mtp_link(ftdm_conf_node_t *mtp_link, sng_mtp_link_t *
/* try to match the parameter to what we expect */
/**********************************************************************/
if (!strcasecmp(parm->var, "name")) {
- strcpy((char *)mtpLink->name, parm->val);
+ 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")) {
@@ -827,7 +827,7 @@ static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route)
/* try to match the parameter to what we expect */
/**********************************************************************/
if (!strcasecmp(parm->var, "name")) {
- strcpy((char *)mtpRoute.name, parm->val);
+ strncpy((char *)mtpRoute.name, parm->val, MAX_NAME_LEN-1);
SS7_DEBUG("\tFound an \"mtp_route\" named = %s\n", mtpRoute.name);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "dpc")) {
@@ -999,7 +999,7 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
/* try to match the parameter to what we expect */
/**********************************************************************/
if (!strcasecmp(parm->var, "name")) {
- strcpy((char *)sng_isup.name, parm->val);
+ strncpy((char *)sng_isup.name, parm->val, MAX_NAME_LEN-1);
SS7_DEBUG("\tFound an \"isup_interface\" named = %s\n", sng_isup.name);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "spc")) {
@@ -1047,6 +1047,11 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
SS7_DEBUG("\tFound MTP3 Route = %s\n", parm->val);
}
/**********************************************************************/
+ } 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")) {
if (!strcasecmp(parm->val, "nat")) {
sng_isup.ssf = SSF_NAT;
@@ -1067,8 +1072,8 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
/**********************************************************************/
} else if (!strcasecmp(parm->var, "license")) {
/**********************************************************************/
- strcpy(g_ftdm_sngss7_data.cfg.license, parm->val);
- strcpy(g_ftdm_sngss7_data.cfg.signature, parm->val);
+ 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);
@@ -1304,6 +1309,13 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
sng_isup.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;
@@ -1359,7 +1371,7 @@ static int ftmod_ss7_fill_in_mtpLink(sng_mtp_link_t *mtpLink)
}
/* fill in the information */
- strcpy((char *)g_ftdm_sngss7_data.cfg.mtpLink[i].name, (char *)mtpLink->name);
+ strncpy((char *)g_ftdm_sngss7_data.cfg.mtpLink[i].name, (char *)mtpLink->name, MAX_NAME_LEN-1);
g_ftdm_sngss7_data.cfg.mtpLink[i].id = mtpLink->id;
@@ -1521,7 +1533,7 @@ static int ftmod_ss7_fill_in_mtpLinkSet(sng_link_set_t *mtpLinkSet)
{
int i = mtpLinkSet->id;
- strcpy((char *)g_ftdm_sngss7_data.cfg.mtpLinkSet[i].name, (char *)mtpLinkSet->name);
+ strncpy((char *)g_ftdm_sngss7_data.cfg.mtpLinkSet[i].name, (char *)mtpLinkSet->name, MAX_NAME_LEN-1);
g_ftdm_sngss7_data.cfg.mtpLinkSet[i].id = mtpLinkSet->id;
g_ftdm_sngss7_data.cfg.mtpLinkSet[i].apc = mtpLinkSet->apc;
@@ -1559,7 +1571,7 @@ static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route)
SS7_DEBUG("found existing mtp3_route, id is = %d\n", mtp3_route->id);
}
- strcpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[i].name, (char *)mtp3_route->name);
+ strncpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[i].name, (char *)mtp3_route->name, MAX_NAME_LEN-1);
g_ftdm_sngss7_data.cfg.mtpRoute[i].id = mtp3_route->id;
g_ftdm_sngss7_data.cfg.mtpRoute[i].dpc = mtp3_route->dpc;
@@ -1693,7 +1705,7 @@ static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup)
SS7_DEBUG("found existing isup interface, id is = %d\n", sng_isup->id);
}
- strcpy((char *)g_ftdm_sngss7_data.cfg.isupIntf[i].name, (char *)sng_isup->name);
+ strncpy((char *)g_ftdm_sngss7_data.cfg.isupIntf[i].name, (char *)sng_isup->name, MAX_NAME_LEN-1);
g_ftdm_sngss7_data.cfg.isupIntf[i].id = sng_isup->id;
g_ftdm_sngss7_data.cfg.isupIntf[i].mtpRouteId = sng_isup->mtpRouteId;
@@ -1705,6 +1717,7 @@ static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup)
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;
@@ -1976,7 +1989,7 @@ static int ftmod_ss7_fill_in_self_route(int spc, int linkType, int switchType, i
return FTDM_FAIL;
}
- strcpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[0].name, "self-route");
+ 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;
@@ -2230,7 +2243,7 @@ static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot)
int lower;
int upper;
char tmp[5]; /*KONRAD FIX ME*/
- char new_ch_map[MAX_CIC_LENGTH];
+ char new_ch_map[MAX_CIC_MAP_LENGTH];
memset(&tmp[0], '\0', sizeof(tmp));
memset(&new_ch_map[0], '\0', sizeof(new_ch_map));
@@ -2337,7 +2350,9 @@ static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot)
/* the the rest of ch_map to new_ch_map */
strncat(new_ch_map, &ch_map[x], strlen(&ch_map[x]));
+
/* set the new cic map to ch_map*/
+ memset(ch_map, '\0', sizeof(ch_map));
strcpy(ch_map, new_ch_map);
} else if (ch_map[x] == ',') {
@@ -2345,16 +2360,21 @@ static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot)
x++;
/* copy the rest of the list to new_ch_map */
+ memset(new_ch_map, '\0', sizeof(new_ch_map));
strcpy(new_ch_map, &ch_map[x]);
/* copy the new_ch_map over the old one */
+ memset(ch_map, '\0', sizeof(ch_map));
strcpy(ch_map, new_ch_map);
} else if (ch_map[x] == '\0') {
+
/* we're at the end of the string...copy the rest of the list to new_ch_map */
+ memset(new_ch_map, '\0', sizeof(new_ch_map));
strcpy(new_ch_map, &ch_map[x]);
/* set the new cic map to ch_map*/
+ memset(ch_map, '\0', sizeof(ch_map));
strcpy(ch_map, new_ch_map);
} else {
/* nothing to do */
diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj
new file mode 100644
index 0000000000..b165ac82d3
--- /dev/null
+++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj
@@ -0,0 +1,201 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ ftmod_wanpipe
+ {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}
+ ftmod_wanpipe
+ Win32Proj
+
+
+
+ DynamicLibrary
+ MultiByte
+ true
+
+
+ DynamicLibrary
+ MultiByte
+
+
+ DynamicLibrary
+ MultiByte
+ true
+
+
+ DynamicLibrary
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ $(SolutionDir)$(Configuration)\
+ $(Configuration)\
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ true
+ $(SolutionDir)$(Configuration)\
+ $(Configuration)\
+ false
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\
+ false
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+
+
+
+ Disabled
+ ../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level3
+ EditAndContinue
+
+
+ freetdm.lib;libsangoma.lib;%(AdditionalDependencies)
+ $(OutDir);C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories)
+ true
+ Console
+ false
+
+
+ MachineX86
+
+
+
+
+ X64
+
+
+ Disabled
+ ../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level3
+ ProgramDatabase
+
+
+ freetdm.lib;libsangoma.lib;%(AdditionalDependencies)
+ $(OutDir);C:\Program Files\Sangoma\api\lib\x64;%(AdditionalLibraryDirectories)
+ true
+ Console
+ false
+
+
+ MachineX64
+
+
+
+
+ ../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+
+
+ Level3
+ ProgramDatabase
+
+
+ freetdm.lib;libsangoma.lib;%(AdditionalDependencies)
+ $(OutDir);C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories)
+ true
+ Console
+ true
+ true
+ false
+
+
+ MachineX86
+
+
+
+
+ X64
+
+
+ ../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+
+
+ Level3
+ ProgramDatabase
+
+
+ freetdm.lib;libsangoma.lib;%(AdditionalDependencies)
+ $(OutDir);C:\Program Files\Sangoma\api\lib\x64;%(AdditionalLibraryDirectories)
+ true
+ Console
+ true
+ true
+ false
+
+
+ MachineX64
+
+
+
+
+
+
+
+ {93b8812c-3ec4-4f78-8970-ffbfc99e167d}
+ false
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj.filters
new file mode 100644
index 0000000000..15a8bc3d35
--- /dev/null
+++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj.filters
@@ -0,0 +1,18 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
index 8e8acc24e3..e1b6658945 100644
--- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
+++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
@@ -35,6 +35,7 @@
* Moises Silva
* David Yat Sin
* Nenad Corbic
+ * Arnaldo Pereira
*
*/
@@ -99,7 +100,8 @@ static struct {
/* a bunch of this stuff should go into the wanpipe_tdm_api_iface.h */
FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event);
-FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event);
+FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event);
+FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event);
/**
* \brief Poll for event on a wanpipe socket
@@ -115,12 +117,16 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event);
static __inline__ int tdmv_api_wait_socket(ftdm_channel_t *ftdmchan, int timeout, int *flags)
{
-#ifdef LIBSANGOMA_VERSION
+#ifdef LIBSANGOMA_VERSION
int err;
uint32_t inflags = *flags;
uint32_t outflags = 0;
sangoma_wait_obj_t *sangoma_wait_obj = ftdmchan->io_data;
+ if (timeout == -1) {
+ timeout = SANGOMA_WAIT_INFINITE;
+ }
+
err = sangoma_waitfor(sangoma_wait_obj, inflags, &outflags, timeout);
*flags = 0;
if (err == SANG_STATUS_SUCCESS) {
@@ -169,7 +175,7 @@ static __inline__ sng_fd_t tdmv_api_open_span_chan(int span, int chan)
static __inline__ sng_fd_t __tdmv_api_open_span_chan(int span, int chan)
{
return __sangoma_open_tdmapi_span_chan(span, chan);
-}
+}
#endif
static ftdm_io_interface_t wanpipe_interface;
@@ -333,8 +339,8 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
ftdm_log(FTDM_LOG_ERROR, "Failed to enable RBS/CAS events in device %d:%d fd:%d\n", chan->span_id, chan->chan_id, sockfd);
continue;
}
- /* probably done by the driver but lets write defensive code this time */
sangoma_flush_bufs(chan->sockfd, &tdm_api);
+ sangoma_flush_event_bufs(chan->sockfd, &tdm_api);
#else
/*
* With wanpipe 3.4.4.2 I get failure even though the events are enabled, /var/log/messages said:
@@ -513,10 +519,10 @@ static FIO_OPEN_FUNCTION(wanpipe_open)
wanpipe_tdm_api_t tdm_api;
memset(&tdm_api,0,sizeof(tdm_api));
+
sangoma_tdm_flush_bufs(ftdmchan->sockfd, &tdm_api);
-#ifdef LIBSANGOMA_VERSION
- sangoma_flush_event_bufs(ftdmchan->sockfd, &tdm_api);
-#endif
+ sangoma_flush_stats(ftdmchan->sockfd, &tdm_api);
+ memset(&ftdmchan->iostats, 0, sizeof(ftdmchan->iostats));
if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921 || ftdmchan->type == FTDM_CHAN_TYPE_DQ931) {
ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_NONE;
@@ -745,19 +751,150 @@ static FIO_COMMAND_FUNCTION(wanpipe_command)
}
}
break;
+ case FTDM_COMMAND_FLUSH_BUFFERS:
+ {
+ err = sangoma_flush_bufs(ftdmchan->sockfd, &tdm_api);
+ }
+ break;
+ case FTDM_COMMAND_FLUSH_RX_BUFFERS:
+ {
+ err = sangoma_flush_rx_bufs(ftdmchan->sockfd, &tdm_api);
+ }
+ break;
+ case FTDM_COMMAND_FLUSH_TX_BUFFERS:
+ {
+ err = sangoma_flush_tx_bufs(ftdmchan->sockfd, &tdm_api);
+ }
+ break;
+ case FTDM_COMMAND_FLUSH_IOSTATS:
+ {
+ err = sangoma_flush_stats(ftdmchan->sockfd, &tdm_api);
+ memset(&ftdmchan->iostats, 0, sizeof(ftdmchan->iostats));
+ }
+ break;
+ case FTDM_COMMAND_SET_RX_QUEUE_SIZE:
+ {
+ uint32_t queue_size = FTDM_COMMAND_OBJ_INT;
+ err = sangoma_set_rx_queue_sz(ftdmchan->sockfd, &tdm_api, queue_size);
+ }
+ break;
+ case FTDM_COMMAND_SET_TX_QUEUE_SIZE:
+ {
+ uint32_t queue_size = FTDM_COMMAND_OBJ_INT;
+ err = sangoma_set_tx_queue_sz(ftdmchan->sockfd, &tdm_api, queue_size);
+ }
+ break;
default:
+ err = FTDM_NOTIMPL;
break;
};
if (err) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno));
- return FTDM_FAIL;
+ return err;
}
return FTDM_SUCCESS;
}
+static void wanpipe_write_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_tx_hdr_t *tx_stats)
+{
+ ftdmchan->iostats.tx.errors = tx_stats->wp_api_tx_hdr_errors;
+ ftdmchan->iostats.tx.queue_size = tx_stats->wp_api_tx_hdr_max_queue_length;
+ ftdmchan->iostats.tx.queue_len = tx_stats->wp_api_tx_hdr_number_of_frames_in_queue;
+
+ /* we don't test for 80% full in tx since is typically full for voice channels, should we test tx 80% full for D-channels? */
+ if (ftdmchan->iostats.tx.queue_len >= ftdmchan->iostats.tx.queue_size) {
+ ftdm_set_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL);
+ } else if (ftdm_test_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL)){
+ ftdm_clear_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL);
+ }
+
+ if (ftdmchan->iostats.tx.idle_packets < tx_stats->wp_api_tx_hdr_tx_idle_packets) {
+ /* HDLC channels do not always transmit, so its ok for drivers to fill with idle
+ * also do not report idle warning when we just started transmitting */
+ if (ftdmchan->iostats.tx.packets && FTDM_IS_VOICE_CHANNEL(ftdmchan)) {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx idle changed from %d to %d\n",
+ ftdmchan->iostats.tx.idle_packets, tx_stats->wp_api_tx_hdr_tx_idle_packets);
+ }
+ ftdmchan->iostats.tx.idle_packets = tx_stats->wp_api_tx_hdr_tx_idle_packets;
+ }
+
+ if (!ftdmchan->iostats.tx.packets) {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "First packet write stats: Tx queue len: %d, Tx queue size: %d, Tx idle: %d\n",
+ ftdmchan->iostats.tx.queue_len,
+ ftdmchan->iostats.tx.queue_size,
+ ftdmchan->iostats.tx.idle_packets);
+ }
+
+ ftdmchan->iostats.tx.packets++;
+}
+
+static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx_stats)
+{
+ ftdmchan->iostats.rx.errors = rx_stats->wp_api_rx_hdr_errors;
+ ftdmchan->iostats.rx.queue_size = rx_stats->wp_api_rx_hdr_max_queue_length;
+ ftdmchan->iostats.rx.queue_len = rx_stats->wp_api_rx_hdr_number_of_frames_in_queue;
+
+ if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_ABORT_ERROR_BIT))) {
+ ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT);
+ } else {
+ ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT);
+ }
+
+ if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_DMA_ERROR_BIT))) {
+ ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA);
+ } else {
+ ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA);
+ }
+
+ if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_FIFO_ERROR_BIT))) {
+ ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO);
+ } else {
+ ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO);
+ }
+
+ if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_CRC_ERROR_BIT))) {
+ ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC);
+ } else {
+ ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC);
+ }
+
+ if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_FRAME_ERROR_BIT))) {
+ ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME);
+ } else {
+ ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME);
+ }
+
+ if (ftdmchan->iostats.rx.queue_len >= (0.8 * ftdmchan->iostats.rx.queue_size)) {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Rx Queue length exceeded 80% threshold (%d/%d)\n",
+ ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
+ ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES);
+ } else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){
+ ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Rx Queue length reduced 80% threshold (%d/%d)\n",
+ ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
+ ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES);
+ }
+
+ if (ftdmchan->iostats.rx.queue_len >= ftdmchan->iostats.rx.queue_size) {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Rx Queue Full (%d/%d)\n",
+ ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
+ ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL);
+ } else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)){
+ ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Rx Queue no longer full (%d/%d)\n",
+ ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
+ ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL);
+ }
+
+ if (!ftdmchan->iostats.rx.packets) {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "First packet read stats: Rx queue len: %d, Rx queue size: %d\n",
+ ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
+ }
+
+ ftdmchan->iostats.rx.packets++;
+}
+
/**
* \brief Reads data from a Wanpipe channel
* \param ftdmchan Channel to read from
@@ -786,9 +923,11 @@ static FIO_READ_FUNCTION(wanpipe_read)
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno));
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read from sangoma device: %s (%d)\n", strerror(errno), rx_len);
return FTDM_FAIL;
- }
-
+ }
+ if (ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS)) {
+ wanpipe_read_stats(ftdmchan, &hdrframe);
+ }
return FTDM_SUCCESS;
}
@@ -801,7 +940,8 @@ static FIO_READ_FUNCTION(wanpipe_read)
*/
static FIO_WRITE_FUNCTION(wanpipe_write)
{
- int bsent;
+ int bsent = 0;
+ int err = 0;
wp_tdm_api_tx_hdr_t hdrframe;
/* Do we even need the headerframe here? on windows, we don't even pass it to the driver */
@@ -809,11 +949,28 @@ static FIO_WRITE_FUNCTION(wanpipe_write)
if (*datalen == 0) {
return FTDM_SUCCESS;
}
+
+ if (ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS) && !ftdmchan->iostats.tx.packets) {
+ wanpipe_tdm_api_t tdm_api;
+ memset(&tdm_api, 0, sizeof(tdm_api));
+ /* if this is the first write ever, flush the tx first to have clean stats */
+ err = sangoma_flush_tx_bufs(ftdmchan->sockfd, &tdm_api);
+ if (err) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to flush on first write\n");
+ }
+ }
+
bsent = sangoma_writemsg_tdm(ftdmchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (unsigned short)(*datalen),0);
/* should we be checking if bsent == *datalen here? */
if (bsent > 0) {
*datalen = bsent;
+ if (ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS)) {
+ /* BRI cards do not support TX queues for now */
+ if(!FTDM_SPAN_IS_BRI(ftdmchan->span)) {
+ wanpipe_write_stats(ftdmchan, &hdrframe);
+ }
+ }
return FTDM_SUCCESS;
}
@@ -1049,13 +1206,155 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms)
return FTDM_SUCCESS;
}
+/**
+ * \brief Retrieves an event from a wanpipe channel
+ * \param channel Channel to retrieve event from
+ * \param event FreeTDM event to return
+ * \return Success or failure
+ */
+FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event)
+{
+ ftdm_status_t status;
+ ftdm_oob_event_t event_id;
+ wanpipe_tdm_api_t tdm_api;
+ ftdm_span_t *span = ftdmchan->span;
+
+ if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT))
+ ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_EVENT);
+
+ memset(&tdm_api, 0, sizeof(tdm_api));
+ status = sangoma_tdm_read_event(ftdmchan->sockfd, &tdm_api);
+ if (status != FTDM_SUCCESS) {
+ snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno));
+ ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to read event from channel: %s\n", strerror(errno));
+ return FTDM_FAIL;
+ }
+
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "read wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type);
+ switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type) {
+
+ case WP_TDMAPI_EVENT_LINK_STATUS:
+ {
+ switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_link_status) {
+ case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED:
+ event_id = FTDM_OOB_ALARM_CLEAR;
+ break;
+ default:
+ event_id = FTDM_OOB_ALARM_TRAP;
+ break;
+ };
+ }
+ break;
+
+ case WP_TDMAPI_EVENT_RXHOOK:
+ {
+ if (ftdmchan->type == FTDM_CHAN_TYPE_FXS) {
+ event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_OFFHOOK : FTDM_OOB_ONHOOK;
+ if (event_id == FTDM_OOB_OFFHOOK) {
+ if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_FLASH)) {
+ ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH);
+ ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_WINK);
+ event_id = FTDM_OOB_FLASH;
+ goto event;
+ } else {
+ ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_WINK);
+ }
+ } else {
+ if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_WINK)) {
+ ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_WINK);
+ ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH);
+ event_id = FTDM_OOB_WINK;
+ goto event;
+ } else {
+ ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH);
+ }
+ }
+ break;
+ } else {
+ wanpipe_tdm_api_t onhook_tdm_api;
+ memset(&onhook_tdm_api, 0, sizeof(onhook_tdm_api));
+ status = sangoma_tdm_txsig_onhook(ftdmchan->sockfd, &onhook_tdm_api);
+ if (status) {
+ snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "ONHOOK Failed");
+ return FTDM_FAIL;
+ }
+ event_id = onhook_tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_ONHOOK : FTDM_OOB_NOOP;
+ }
+ }
+ break;
+ case WP_TDMAPI_EVENT_RING_DETECT:
+ {
+ event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_RING_START : FTDM_OOB_RING_STOP;
+ }
+ break;
+ /*
+ disabled this ones when configuring, we don't need them, do we?
+ case WP_TDMAPI_EVENT_RING_TRIP_DETECT:
+ {
+ event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_ONHOOK : FTDM_OOB_OFFHOOK;
+ }
+ break;
+ */
+ case WP_TDMAPI_EVENT_RBS:
+ {
+ event_id = FTDM_OOB_CAS_BITS_CHANGE;
+ ftdmchan->rx_cas_bits = wanpipe_swap_bits(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_rbs_bits);
+ }
+ break;
+ case WP_TDMAPI_EVENT_DTMF:
+ {
+ char tmp_dtmf[2] = { tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_digit, 0 };
+ event_id = FTDM_OOB_NOOP;
+
+ if (tmp_dtmf[0] == 'f') {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Ignoring wanpipe DTMF: %c, fax tones will be passed through!\n", tmp_dtmf[0]);
+ break;
+ }
+
+ if (tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_PRESENT) {
+ ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_MUTE);
+ }
+
+ if (tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_STOP) {
+ ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_MUTE);
+ if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Queuing wanpipe DTMF: %c\n", tmp_dtmf[0]);
+ ftdm_channel_queue_dtmf(ftdmchan, tmp_dtmf);
+ }
+ }
+ }
+ break;
+ case WP_TDMAPI_EVENT_ALARM:
+ {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Got wanpipe alarms %d\n", tdm_api.wp_tdm_cmd.event.wp_api_event_alarm);
+ event_id = FTDM_OOB_ALARM_TRAP;
+ }
+ break;
+ default:
+ {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unhandled wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type);
+ event_id = FTDM_OOB_INVALID;
+ }
+ break;
+ }
+
+event:
+
+ ftdmchan->last_event_time = 0;
+ span->event_header.e_type = FTDM_EVENT_OOB;
+ span->event_header.enum_id = event_id;
+ span->event_header.channel = ftdmchan;
+ *event = &span->event_header;
+ return FTDM_SUCCESS;
+}
+
/**
* \brief Retrieves an event from a wanpipe span
* \param span Span to retrieve event from
* \param event FreeTDM event to return
* \return Success or failure
*/
-FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event)
+FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event)
{
uint32_t i,err;
ftdm_oob_event_t event_id;
@@ -1287,7 +1586,8 @@ static FIO_IO_LOAD_FUNCTION(wanpipe_init)
wanpipe_interface.read = wanpipe_read;
wanpipe_interface.write = wanpipe_write;
wanpipe_interface.poll_event = wanpipe_poll_event;
- wanpipe_interface.next_event = wanpipe_next_event;
+ wanpipe_interface.next_event = wanpipe_span_next_event;
+ wanpipe_interface.channel_next_event = wanpipe_channel_next_event;
wanpipe_interface.channel_destroy = wanpipe_channel_destroy;
wanpipe_interface.get_alarms = wanpipe_get_alarms;
*fio = &wanpipe_interface;
diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ozmod_wanpipe.2005.vcproj b/libs/freetdm/src/ftmod/ftmod_wanpipe/ozmod_wanpipe.2005.vcproj
deleted file mode 100644
index abebf30427..0000000000
--- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ozmod_wanpipe.2005.vcproj
+++ /dev/null
@@ -1,196 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/wanpipe_tdm_api_iface.h b/libs/freetdm/src/ftmod/ftmod_wanpipe/wanpipe_tdm_api_iface.h
deleted file mode 100644
index 3801ff9c8c..0000000000
--- a/libs/freetdm/src/ftmod/ftmod_wanpipe/wanpipe_tdm_api_iface.h
+++ /dev/null
@@ -1,351 +0,0 @@
-/*****************************************************************************
-* wanpipe_tdm_api_iface.h
-*
-* WANPIPE(tm) AFT TE1 Hardware Support
-*
-* Authors: Nenad Corbic
-*
-* Copyright (c) 2007 - 08, Sangoma Technologies
-* 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 nor the
-* names of its contributors may be used to endorse or promote products
-* derived from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY ``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 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.
-
-* ============================================================================
-* Oct 04, 2005 Nenad Corbic Initial version.
-*
-* Jul 25, 2006 David Rokhvarg Ported to Windows.
-*****************************************************************************/
-
-#ifndef __WANPIPE_TDM_API_IFACE_H_
-#define __WANPIPE_TDM_API_IFACE_H_
-
-
-#if defined(__WINDOWS__)
-typedef HANDLE sng_fd_t;
-#else
-typedef int sng_fd_t;
-#endif
-
-/* Indicate to library that new features exist */
-#define WP_TDM_FEATURE_DTMF_EVENTS 1
-#define WP_TDM_FEATURE_FE_ALARM 1
-#define WP_TDM_FEATURE_EVENTS 1
-#define WP_TDM_FEATURE_LINK_STATUS 1
-
-enum wanpipe_tdm_api_cmds {
-
- SIOC_WP_TDM_GET_USR_MTU_MRU, /* 0x00 */
-
- SIOC_WP_TDM_SET_USR_PERIOD, /* 0x01 */
- SIOC_WP_TDM_GET_USR_PERIOD, /* 0x02 */
-
- SIOC_WP_TDM_SET_HW_MTU_MRU, /* 0x03 */
- SIOC_WP_TDM_GET_HW_MTU_MRU, /* 0x04 */
-
- SIOC_WP_TDM_SET_CODEC, /* 0x05 */
- SIOC_WP_TDM_GET_CODEC, /* 0x06 */
-
- SIOC_WP_TDM_SET_POWER_LEVEL, /* 0x07 */
- SIOC_WP_TDM_GET_POWER_LEVEL, /* 0x08 */
-
- SIOC_WP_TDM_TOGGLE_RX, /* 0x09 */
- SIOC_WP_TDM_TOGGLE_TX, /* 0x0A */
-
- SIOC_WP_TDM_GET_HW_CODING, /* 0x0B */
- SIOC_WP_TDM_SET_HW_CODING, /* 0x0C */
-
- SIOC_WP_TDM_GET_FULL_CFG, /* 0x0D */
-
- SIOC_WP_TDM_SET_EC_TAP, /* 0x0E */
- SIOC_WP_TDM_GET_EC_TAP, /* 0x0F */
-
- SIOC_WP_TDM_ENABLE_RBS_EVENTS, /* 0x10 */
- SIOC_WP_TDM_DISABLE_RBS_EVENTS, /* 0x11 */
- SIOC_WP_TDM_WRITE_RBS_BITS, /* 0x12 */
-
- SIOC_WP_TDM_GET_STATS, /* 0x13 */
- SIOC_WP_TDM_FLUSH_BUFFERS, /* 0x14 */
-
- SIOC_WP_TDM_READ_EVENT, /* 0x15 */
-
- SIOC_WP_TDM_SET_EVENT, /* 0x16 */
-
- SIOC_WP_TDM_SET_RX_GAINS, /* 0x17 */
- SIOC_WP_TDM_SET_TX_GAINS, /* 0x18 */
- SIOC_WP_TDM_CLEAR_RX_GAINS, /* 0x19 */
- SIOC_WP_TDM_CLEAR_TX_GAINS, /* 0x1A */
-
- SIOC_WP_TDM_GET_FE_ALARMS, /* 0x1B */
-
- SIOC_WP_TDM_ENABLE_HWEC, /* 0x1C */
- SIOC_WP_TDM_DISABLE_HWEC, /* 0x1D */
-
- SIOC_WP_TDM_SET_FE_STATUS, /* 0x1E */
- SIOC_WP_TDM_GET_FE_STATUS, /* 0x1F */
-
- SIOC_WP_TDM_GET_HW_DTMF, /* 0x20 */
-
- SIOC_WP_TDM_NOTSUPP /* */
-
-};
-
-#define SIOC_WP_TDM_GET_LINK_STATUS SIOC_WP_TDM_GET_FE_STATUS
-
-enum wanpipe_tdm_api_events {
- WP_TDMAPI_EVENT_NONE,
- WP_TDMAPI_EVENT_RBS,
- WP_TDMAPI_EVENT_ALARM,
- WP_TDMAPI_EVENT_DTMF,
- WP_TDMAPI_EVENT_RM_DTMF,
- WP_TDMAPI_EVENT_RXHOOK,
- WP_TDMAPI_EVENT_RING,
- WP_TDMAPI_EVENT_RING_DETECT,
- WP_TDMAPI_EVENT_RING_TRIP_DETECT,
- WP_TDMAPI_EVENT_TONE,
- WP_TDMAPI_EVENT_TXSIG_KEWL,
- WP_TDMAPI_EVENT_TXSIG_START,
- WP_TDMAPI_EVENT_TXSIG_OFFHOOK,
- WP_TDMAPI_EVENT_TXSIG_ONHOOK,
- WP_TDMAPI_EVENT_ONHOOKTRANSFER,
- WP_TDMAPI_EVENT_SETPOLARITY,
- WP_TDMAPI_EVENT_BRI_CHAN_LOOPBACK,
- WP_TDMAPI_EVENT_LINK_STATUS
-};
-
-#define WP_TDMAPI_EVENT_FE_ALARM WP_TDMAPI_EVENT_ALARM
-
-
-#define WP_TDMAPI_EVENT_ENABLE 0x01
-#define WP_TDMAPI_EVENT_DISABLE 0x02
-#define WP_TDMAPI_EVENT_MODE_DECODE(mode) \
- ((mode) == WP_TDMAPI_EVENT_ENABLE) ? "Enable" : \
- ((mode) == WP_TDMAPI_EVENT_DISABLE) ? "Disable" : \
- "(Unknown mode)"
-
-#define WPTDM_A_BIT WAN_RBS_SIG_A
-#define WPTDM_B_BIT WAN_RBS_SIG_B
-#define WPTDM_C_BIT WAN_RBS_SIG_C
-#define WPTDM_D_BIT WAN_RBS_SIG_D
-
-#define WP_TDMAPI_EVENT_RXHOOK_OFF 0x01
-#define WP_TDMAPI_EVENT_RXHOOK_ON 0x02
-#define WP_TDMAPI_EVENT_RXHOOK_DECODE(state) \
- ((state) == WP_TDMAPI_EVENT_RXHOOK_OFF) ? "Off-hook" : \
- ((state) == WP_TDMAPI_EVENT_RXHOOK_ON) ? "On-hook" : \
- "(Unknown state)"
-
-#define WP_TDMAPI_EVENT_RING_PRESENT 0x01
-#define WP_TDMAPI_EVENT_RING_STOP 0x02
-#define WP_TDMAPI_EVENT_RING_DECODE(state) \
- ((state) == WP_TDMAPI_EVENT_RING_PRESENT) ? "Ring Present" : \
- ((state) == WP_TDMAPI_EVENT_RING_STOP) ? "Ring Stop" : \
- "(Unknown state)"
-
-#define WP_TDMAPI_EVENT_RING_TRIP_PRESENT 0x01
-#define WP_TDMAPI_EVENT_RING_TRIP_STOP 0x02
-#define WP_TDMAPI_EVENT_RING_TRIP_DECODE(state) \
- ((state) == WP_TDMAPI_EVENT_RING_TRIP_PRESENT) ? "Ring Present" : \
- ((state) == WP_TDMAPI_EVENT_RING_TRIP_STOP) ? "Ring Stop" : \
- "(Unknown state)"
-/*Link Status */
-#define WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED 0x01
-#define WP_TDMAPI_EVENT_LINK_STATUS_DISCONNECTED 0x02
-#define WP_TDMAPI_EVENT_LINK_STATUS_DECODE(status) \
- ((status) == WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED) ? "Connected" : \
- ((status) == WP_TDMAPI_EVENT_LINK_STATUS_DISCONNECTED) ? "Disconnected" : \
- "Unknown"
-#define WP_TDMAPI_EVENT_TONE_DIAL 0x01
-#define WP_TDMAPI_EVENT_TONE_BUSY 0x02
-#define WP_TDMAPI_EVENT_TONE_RING 0x03
-#define WP_TDMAPI_EVENT_TONE_CONGESTION 0x04
-
-/* BRI channels list */
-#define WAN_BRI_BCHAN1 0x01
-#define WAN_BRI_BCHAN2 0x02
-#define WAN_BRI_DCHAN 0x03
-
-
-typedef struct {
-
- u_int8_t type;
- u_int8_t mode;
- u_int32_t time_stamp;
- u_int8_t channel;
- u_int32_t chan_map;
- u_int8_t span;
- union {
- struct {
- u_int8_t alarm;
- } te1_alarm;
- struct {
- u_int8_t rbs_bits;
- } te1_rbs;
- struct {
- u_int8_t state;
- u_int8_t sig;
- } rm_hook;
- struct {
- u_int8_t state;
- } rm_ring;
- struct {
- u_int8_t type;
- } rm_tone;
- struct {
- u_int8_t digit; /* DTMF: digit */
- u_int8_t port; /* DTMF: SOUT/ROUT */
- u_int8_t type; /* DTMF: PRESET/STOP */
- } dtmf;
- struct {
- u_int16_t polarity;
- u_int16_t ohttimer;
- } rm_common;
- struct{
- u_int16_t status;
- } linkstatus;
- } wp_tdm_api_event_u;
-#define wp_tdm_api_event_type type
-#define wp_tdm_api_event_mode mode
-#define wp_tdm_api_event_alarm wp_tdm_api_event_u.te1_alarm.alarm
-#define wp_tdm_api_event_alarm wp_tdm_api_event_u.te1_alarm.alarm
-#define wp_tdm_api_event_rbs_bits wp_tdm_api_event_u.te1_rbs.rbs_bits
-#define wp_tdm_api_event_hook_state wp_tdm_api_event_u.rm_hook.state
-#define wp_tdm_api_event_hook_sig wp_tdm_api_event_u.rm_hook.sig
-#define wp_tdm_api_event_ring_state wp_tdm_api_event_u.rm_ring.state
-#define wp_tdm_api_event_tone_type wp_tdm_api_event_u.rm_tone.type
-#define wp_tdm_api_event_dtmf_digit wp_tdm_api_event_u.dtmf.digit
-#define wp_tdm_api_event_dtmf_type wp_tdm_api_event_u.dtmf.type
-#define wp_tdm_api_event_dtmf_port wp_tdm_api_event_u.dtmf.port
-#define wp_tdm_api_event_ohttimer wp_tdm_api_event_u.rm_common.ohttimer
-#define wp_tdm_api_event_polarity wp_tdm_api_event_u.rm_common.polarity
-#define wp_tdm_api_event_link_status wp_tdm_api_event_u.linkstatus.status
-} wp_tdm_api_event_t;
-
-typedef struct {
- union {
- unsigned char reserved[16];
- }wp_rx_hdr_u;
-} wp_tdm_api_rx_hdr_t;
-
-typedef struct {
- wp_tdm_api_rx_hdr_t hdr;
- unsigned char data[1];
-} wp_tdm_api_rx_element_t;
-
-typedef struct {
- union {
- struct {
- unsigned char _rbs_rx_bits;
- unsigned int _time_stamp;
- }wp_tx;
- unsigned char reserved[16];
- }wp_tx_hdr_u;
-#define wp_api_time_stamp wp_tx_hdr_u.wp_tx._time_stamp
-} wp_tdm_api_tx_hdr_t;
-
-typedef struct {
- wp_tdm_api_tx_hdr_t hdr;
- unsigned char data[1];
-} wp_tdm_api_tx_element_t;
-
-
-
-typedef struct wp_tdm_chan_stats
-{
- unsigned int rx_packets; /* total packets received */
- unsigned int tx_packets; /* total packets transmitted */
- unsigned int rx_bytes; /* total bytes received */
- unsigned int tx_bytes; /* total bytes transmitted */
- unsigned int rx_errors; /* bad packets received */
- unsigned int tx_errors; /* packet transmit problems */
- unsigned int rx_dropped; /* no space in linux buffers */
- unsigned int tx_dropped; /* no space available in linux */
- unsigned int multicast; /* multicast packets received */
-#if !defined(__WINDOWS__)
- unsigned int collisions;
-#endif
- /* detailed rx_errors: */
- unsigned int rx_length_errors;
- unsigned int rx_over_errors; /* receiver ring buff overflow */
- unsigned int rx_crc_errors; /* recved pkt with crc error */
- unsigned int rx_frame_errors; /* recv'd frame alignment error */
-#if !defined(__WINDOWS__)
- unsigned int rx_fifo_errors; /* recv'r fifo overrun */
-#endif
- unsigned int rx_missed_errors; /* receiver missed packet */
-
- /* detailed tx_errors */
-#if !defined(__WINDOWS__)
- unsigned int tx_aborted_errors;
- unsigned int tx_carrier_errors;
-#endif
- unsigned int tx_fifo_errors;
- unsigned int tx_heartbeat_errors;
- unsigned int tx_window_errors;
-
-}wp_tdm_chan_stats_t;
-
-
-
-typedef struct wanpipe_tdm_api_cmd{
- unsigned int cmd;
- unsigned int hw_tdm_coding; /* Set/Get HW TDM coding: uLaw muLaw */
- unsigned int hw_mtu_mru; /* Set/Get HW TDM MTU/MRU */
- unsigned int usr_period; /* Set/Get User Period in ms */
- unsigned int tdm_codec; /* Set/Get TDM Codec: SLinear */
- unsigned int power_level; /* Set/Get Power level treshold */
- unsigned int rx_disable; /* Enable/Disable Rx */
- unsigned int tx_disable; /* Enable/Disable Tx */
- unsigned int usr_mtu_mru; /* Set/Get User TDM MTU/MRU */
- unsigned int ec_tap; /* Echo Cancellation Tap */
- unsigned int rbs_poll; /* Enable/Disable RBS Polling */
- unsigned int rbs_rx_bits; /* Rx RBS Bits */
- unsigned int rbs_tx_bits; /* Tx RBS Bits */
- unsigned int hdlc; /* HDLC based device */
- unsigned int idle_flag; /* IDLE flag to Tx */
- unsigned int fe_alarms; /* FE Alarms detected */
- wp_tdm_chan_stats_t stats; /* TDM Statistics */
- /* Do NOT add anything above this! Important for binary backward compatibility. */
- wp_tdm_api_event_t event; /* TDM Event */
- unsigned int data_len;
- void *data;
- unsigned char fe_status; /* FE status - Connected or Disconnected */
- unsigned int hw_dtmf; /* HW DTMF enabled */
-}wanpipe_tdm_api_cmd_t;
-
-typedef struct wanpipe_tdm_api_event{
- int (*wp_rbs_event)(sng_fd_t fd, unsigned char rbs_bits);
- int (*wp_dtmf_event)(sng_fd_t fd, unsigned char dtmf, unsigned char type, unsigned char port);
- int (*wp_rxhook_event)(sng_fd_t fd, unsigned char hook_state);
- int (*wp_ring_detect_event)(sng_fd_t fd, unsigned char ring_state);
- int (*wp_ring_trip_detect_event)(sng_fd_t fd, unsigned char ring_state);
- int (*wp_fe_alarm_event)(sng_fd_t fd, unsigned char fe_alarm_event);
- int (*wp_link_status_event)(sng_fd_t fd, unsigned char link_status_event);
-}wanpipe_tdm_api_event_t;
-
-typedef struct wanpipe_tdm_api{
- wanpipe_tdm_api_cmd_t wp_tdm_cmd;
- wanpipe_tdm_api_event_t wp_tdm_event;
-}wanpipe_tdm_api_t;
-
-
-#endif
diff --git a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c
index ddf7b3ffab..7320934a49 100644
--- a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c
+++ b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c
@@ -35,6 +35,11 @@
#include "private/ftdm_core.h"
#include "ftmod_zt.h"
+/* used by dahdi to indicate there is no data available, but events to read */
+#ifndef ELAST
+#define ELAST 500
+#endif
+
/**
* \brief Zaptel globals
*/
@@ -889,13 +894,18 @@ static FIO_WAIT_FUNCTION(zt_wait)
inflags |= POLLPRI;
}
-
+pollagain:
memset(&pfds[0], 0, sizeof(pfds[0]));
pfds[0].fd = ftdmchan->sockfd;
pfds[0].events = inflags;
result = poll(pfds, 1, to);
*flags = 0;
+ if (result < 0 && errno == EINTR) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "DAHDI wait got interrupted, trying again\n");
+ goto pollagain;
+ }
+
if (pfds[0].revents & POLLERR) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "DAHDI device got POLLERR\n");
result = -1;
@@ -1076,7 +1086,6 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event)
}
return FTDM_FAIL;
-
}
/**
@@ -1095,12 +1104,19 @@ static FIO_READ_FUNCTION(zt_read)
if ((r = read(ftdmchan->sockfd, data, *datalen)) > 0) {
break;
}
- ftdm_sleep(10);
- if (r == 0) {
- errs--;
+ else if (r == 0) {
+ ftdm_sleep(10);
+ if (errs) errs--;
+ }
+ else {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ if (errno == ELAST)
+ break;
+
+ ftdm_log(FTDM_LOG_ERROR, "read failed: %s\n", strerror(errno));
}
}
-
if (r > 0) {
*datalen = r;
if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) {
@@ -1108,7 +1124,9 @@ static FIO_READ_FUNCTION(zt_read)
}
return FTDM_SUCCESS;
}
-
+ else if (errno == ELAST) {
+ return FTDM_SUCCESS;
+ }
return r == 0 ? FTDM_TIMEOUT : FTDM_FAIL;
}
diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h
index 31bc88b9ca..4ee6ff5f52 100644
--- a/libs/freetdm/src/include/freetdm.h
+++ b/libs/freetdm/src/include/freetdm.h
@@ -41,6 +41,7 @@
#include "ftdm_declare.h"
+#include "ftdm_call_utils.h"
/*! \brief Max number of channels per physical span */
#define FTDM_MAX_CHANNELS_PHYSICAL_SPAN 32
@@ -62,23 +63,6 @@
#define FTDM_INVALID_INT_PARM 0xFF
-/*! \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_TIMEOUT, /*!< Operation timed out (ie: polling on a device)*/
- FTDM_NOTIMPL, /*!< Operation not implemented */
- FTDM_BREAK, /*!< Request the caller to perform a break (context-dependant, ie: stop getting DNIS/ANI) */
- FTDM_EINVAL /*!< Invalid argument */
-} ftdm_status_t;
-
-/*! \brief FreeTDM bool type. */
-typedef enum {
- FTDM_FALSE,
- FTDM_TRUE
-} ftdm_bool_t;
-
/*! \brief Thread/Mutex OS abstraction API. */
#include "ftdm_os.h"
@@ -220,8 +204,10 @@ typedef enum {
FTDM_TON_SUBSCRIBER_NUMBER,
FTDM_TON_ABBREVIATED_NUMBER,
FTDM_TON_RESERVED,
- FTDM_TON_INVALID = 255
+ FTDM_TON_INVALID
} ftdm_ton_t;
+#define TON_STRINGS "unknown", "international", "national", "network-specific", "subscriber-number", "abbreviated-number", "reserved", "invalid"
+FTDM_STR2ENUM_P(ftdm_str2ftdm_ton, ftdm_ton2str, ftdm_ton_t)
/*! Numbering Plan Identification (NPI) */
typedef enum {
@@ -232,8 +218,52 @@ typedef enum {
FTDM_NPI_NATIONAL = 8,
FTDM_NPI_PRIVATE = 9,
FTDM_NPI_RESERVED = 10,
- FTDM_NPI_INVALID = 255
+ FTDM_NPI_INVALID
} ftdm_npi_t;
+#define NPI_STRINGS "unknown", "ISDN", "data", "telex", "national", "private", "reserved", "invalid"
+FTDM_STR2ENUM_P(ftdm_str2ftdm_npi, ftdm_npi2str, ftdm_npi_t)
+
+/*! Presentation Ind */
+typedef enum {
+ FTDM_PRES_ALLOWED,
+ FTDM_PRES_RESTRICTED,
+ FTDM_PRES_NOT_AVAILABLE,
+ FTDM_PRES_RESERVED,
+ FTDM_PRES_INVALID
+} ftdm_presentation_t;
+#define PRESENTATION_STRINGS "presentation-allowed", "presentation-restricted", "number-not-available", "reserved", "Invalid"
+FTDM_STR2ENUM_P(ftdm_str2ftdm_presentation, ftdm_presentation2str, ftdm_presentation_t)
+
+/*! Screening Ind */
+typedef enum {
+ FTDM_SCREENING_NOT_SCREENED,
+ FTDM_SCREENING_VERIFIED_PASSED,
+ FTDM_SCREENING_VERIFIED_FAILED,
+ FTDM_SCREENING_NETWORK_PROVIDED,
+ FTDM_SCREENING_INVALID
+} ftdm_screening_t;
+#define SCREENING_STRINGS "user-provided-not-screened", "user-provided-verified-and-passed", "user-provided-verified-and-failed", "network-provided", "invalid"
+FTDM_STR2ENUM_P(ftdm_str2ftdm_screening, ftdm_screening2str, ftdm_screening_t)
+
+/*! \brief bearer capability */
+typedef enum {
+ FTDM_BEARER_CAP_SPEECH = 0x00,
+ FTDM_BEARER_CAP_64K_UNRESTRICTED = 0x02,
+ FTDM_BEARER_CAP_3_1KHZ_AUDIO = 0x03,
+ FTDM_BEARER_CAP_INVALID
+} ftdm_bearer_cap_t;
+#define BEARER_CAP_STRINGS "speech", "unrestricted-digital-information", "3.1-Khz-audio", "invalid"
+FTDM_STR2ENUM_P(ftdm_str2ftdm_bearer_cap, ftdm_bearer_cap2str, ftdm_bearer_cap_t)
+
+/*! \brief user information layer 1 protocol */
+typedef enum {
+ FTDM_USER_LAYER1_PROT_V110 = 0x01,
+ FTDM_USER_LAYER1_PROT_ULAW = 0x02,
+ FTDM_USER_LAYER1_PROT_ALAW = 0x03,
+ FTDM_USER_LAYER1_PROT_INVALID
+} ftdm_user_layer1_prot_t;
+#define USER_LAYER1_PROT_STRINGS "V.110", "u-law", "a-law", "Invalid"
+FTDM_STR2ENUM_P(ftdm_str2ftdm_usr_layer1_prot, ftdm_user_layer1_prot2str, ftdm_user_layer1_prot_t)
/*! \brief Number abstraction */
typedef struct {
@@ -242,20 +272,8 @@ typedef struct {
uint8_t plan;
} ftdm_number_t;
-/*! \brief bearer capability */
-typedef enum {
- FTDM_BEARER_CAP_SPEECH = 0x00,
- FTDM_BEARER_CAP_64K_UNRESTRICTED = 0x02,
- FTDM_BEARER_CAP_3_1KHZ_AUDIO = 0x03
-} ftdm_bearer_cap_t;
-
-/*! \brief user information layer 1 protocol */
-typedef enum {
- FTDM_USER_LAYER1_PROT_V110 = 0x01,
- FTDM_USER_LAYER1_PROT_ULAW = 0x02,
- FTDM_USER_LAYER1_PROT_ALAW = 0x03,
-} ftdm_user_layer1_prot_t;
-
+typedef void * ftdm_variable_container_t;
+
/*! \brief Caller information */
typedef struct ftdm_caller_data {
char cid_date[8]; /*!< Caller ID date */
@@ -270,12 +288,13 @@ typedef struct ftdm_caller_data {
char collected[25]; /*!< Collected digits so far */
int hangup_cause; /*!< Hangup cause */
char raw_data[1024]; /*!< Protocol specific raw caller data */
- uint32_t raw_data_len; /* !< Raw data length */
+ uint32_t raw_data_len; /*!< Raw data length */
/* these 2 are undocumented right now, only used by boost: */
/* bearer capability */
ftdm_bearer_cap_t bearer_capability;
/* user information layer 1 protocol */
ftdm_user_layer1_prot_t bearer_layer1;
+ ftdm_variable_container_t variables; /*!variables and caller_data->raw_data.
+ * */
+FT_DECLARE(void) ftdm_call_clear_data(ftdm_caller_data_t *caller_data);
+
/*! \brief Get the span pointer associated to the channel */
FT_DECLARE(ftdm_span_t *) ftdm_channel_get_span(const ftdm_channel_t *ftdmchan);
diff --git a/libs/freetdm/src/include/ftdm_call_utils.h b/libs/freetdm/src/include/ftdm_call_utils.h
new file mode 100644
index 0000000000..835a5c6cdc
--- /dev/null
+++ b/libs/freetdm/src/include/ftdm_call_utils.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2010, Sangoma Technologies
+ * David Yat Sin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FTDM_CALL_UTILS_H__
+#define __FTDM_CALL_UTILS_H__
+
+/*!
+ * \brief Set the Numbering Plan Identification from a string
+ *
+ * \param npi_string string value
+ * \param target the target to set value to
+ *
+ * \retval FTDM_SUCCESS success
+ * \retval FTDM_FAIL failure
+ */
+FT_DECLARE(ftdm_status_t) ftdm_set_npi(const char *npi_string, uint8_t *target);
+
+
+/*!
+ * \brief Set the Type of number from a string
+ *
+ * \param ton_string string value
+ * \param target the target to set value to
+ *
+ * \retval FTDM_SUCCESS success
+ * \retval FTDM_FAIL failure
+ */
+FT_DECLARE(ftdm_status_t) ftdm_set_ton(const char *ton_string, uint8_t *target);
+
+/*!
+ * \brief Set the Bearer Capability from a string
+ *
+ * \param bc_string string value
+ * \param target the target to set value to
+ *
+ * \retval FTDM_SUCCESS success
+ * \retval FTDM_FAIL failure
+ */
+FT_DECLARE(ftdm_status_t) ftdm_set_bearer_capability(const char *bc_string, uint8_t *target);
+
+/*!
+ * \brief Set the Bearer Capability - Layer 1 from a string
+ *
+ * \param bc_string string value
+ * \param target the target to set value to
+ *
+ * \retval FTDM_SUCCESS success
+ * \retval FTDM_FAIL failure
+ */
+FT_DECLARE(ftdm_status_t) ftdm_set_bearer_layer1(const char *bc_string, uint8_t *target);
+
+/*!
+ * \brief Set the Screening Ind from a string
+ *
+ * \param screen_string string value
+ * \param target the target to set value to
+ *
+ * \retval FTDM_SUCCESS success
+ * \retval FTDM_FAIL failure
+ */
+FT_DECLARE(ftdm_status_t) ftdm_set_screening_ind(const char *string, uint8_t *target);
+
+
+/*!
+ * \brief Set the Presentation Ind from an enum
+ *
+ * \param screen_string string value
+ * \param target the target to set value to
+ *
+ * \retval FTDM_SUCCESS success
+ * \retval FTDM_FAIL failure
+ */
+FT_DECLARE(ftdm_status_t) ftdm_set_presentation_ind(const char *string, uint8_t *target);
+
+
+/*!
+ * \brief Checks whether a string contains only numbers
+ *
+ * \param number string value
+ *
+ * \retval FTDM_SUCCESS success
+ * \retval FTDM_FAIL failure
+ */
+FT_DECLARE(ftdm_status_t) ftdm_is_number(const char *number);
+
+#endif /* __FTDM_CALL_UTILS_H__ */
+
diff --git a/libs/freetdm/src/include/ftdm_declare.h b/libs/freetdm/src/include/ftdm_declare.h
index ab3b5c8966..4aba703f28 100644
--- a/libs/freetdm/src/include/ftdm_declare.h
+++ b/libs/freetdm/src/include/ftdm_declare.h
@@ -171,6 +171,23 @@ typedef int ftdm_socket_t;
#include
#endif
+/*! \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_TIMEOUT, /*!< Operation timed out (ie: polling on a device)*/
+ FTDM_NOTIMPL, /*!< Operation not implemented */
+ FTDM_BREAK, /*!< Request the caller to perform a break (context-dependant, ie: stop getting DNIS/ANI) */
+ FTDM_EINVAL /*!< Invalid argument */
+} ftdm_status_t;
+
+/*! \brief FreeTDM bool type. */
+typedef enum {
+ FTDM_FALSE,
+ FTDM_TRUE
+} ftdm_bool_t;
+
/*!
* \brief FreeTDM channel.
* This is the basic data structure used to place calls and I/O operations
diff --git a/libs/freetdm/src/include/private/ftdm_call_utils.h b/libs/freetdm/src/include/private/ftdm_call_utils.h
deleted file mode 100644
index 782abde927..0000000000
--- a/libs/freetdm/src/include/private/ftdm_call_utils.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2010, Sangoma Technologies
- * David Yat Sin
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of the original author; nor the names of any contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __FTDM_CALL_UTILS_H__
-#define __FTDM_CALL_UTILS_H__
-
-#include "freetdm.h"
-
-FT_DECLARE(ftdm_status_t) ftdm_span_set_npi(const char *npi_string, uint8_t *target);
-FT_DECLARE(ftdm_status_t) ftdm_span_set_ton(const char *ton_string, uint8_t *target);
-FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_capability(const char *bc_string, ftdm_bearer_cap_t *target);
-FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_layer1(const char *bc_string, ftdm_user_layer1_prot_t *target);
-FT_DECLARE(ftdm_status_t) ftdm_is_number(char *number);
-
-#endif /* __FTDM_CALL_UTILS_H__ */
-
diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h
index ab20ef8171..deabafd537 100644
--- a/libs/freetdm/src/include/private/ftdm_core.h
+++ b/libs/freetdm/src/include/private/ftdm_core.h
@@ -222,8 +222,7 @@ extern "C" {
#define ftdm_is_dtmf(key) ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119)
-#define FTDM_SPAN_IS_BRI(x) ((x)->trunk_type == FTDM_TRUNK_BRI || (x)->trunk_type == FTDM_TRUNK_BRI_PTMP)
-
+#define FTDM_SPAN_IS_BRI(x) ((x)->trunk_type == FTDM_TRUNK_BRI || (x)->trunk_type == FTDM_TRUNK_BRI_PTMP)
/*!
\brief Copy flags from one arbitrary object to another
\command dest the object to copy the flags to
@@ -343,20 +342,24 @@ typedef enum {
FTDM_TYPE_CHANNEL
} ftdm_data_type_t;
-#ifdef FTDM_DEBUG_DTMF
-/* number of bytes for the circular buffer (5 seconds worth of audio) */
-#define DTMF_DEBUG_SIZE 8 * 5000
-/* number of 20ms cycles before timeout and close the debug dtmf file (5 seconds) */
-#define DTMF_DEBUG_TIMEOUT 250
+/* number of bytes for the IO dump circular buffer (5 seconds worth of audio by default) */
+#define FTDM_IO_DUMP_DEFAULT_BUFF_SIZE 8 * 5000
typedef struct {
- FILE *file;
- char buffer[DTMF_DEBUG_SIZE];
+ char *buffer;
+ ftdm_size_t size;
int windex;
int wrapped;
- int closetimeout;
+} ftdm_io_dump_t;
+
+/* number of interval cycles before timeout and close the debug dtmf file (5 seconds if interval is 20) */
+#define DTMF_DEBUG_TIMEOUT 250
+typedef struct {
+ uint8_t enabled;
+ uint8_t requested;
+ FILE *file;
+ int32_t closetimeout;
ftdm_mutex_t *mutex;
} ftdm_dtmf_debug_t;
-#endif
typedef struct {
const char *file;
@@ -367,6 +370,35 @@ typedef struct {
ftdm_time_t time;
} ftdm_channel_history_entry_t;
+typedef enum {
+ FTDM_IOSTATS_ERROR_CRC = (1 << 0),
+ FTDM_IOSTATS_ERROR_FRAME = (1 << 1),
+ FTDM_IOSTATS_ERROR_ABORT = (1 << 2),
+ FTDM_IOSTATS_ERROR_FIFO = (1 << 3),
+ FTDM_IOSTATS_ERROR_DMA = (1 << 4),
+ FTDM_IOSTATS_ERROR_QUEUE_THRES = (1 << 5), /* Queue reached high threshold */
+ FTDM_IOSTATS_ERROR_QUEUE_FULL = (1 << 6), /* Queue is full */
+} ftdm_iostats_error_type_t;
+
+typedef struct {
+ struct {
+ uint32_t errors;
+ uint16_t flags;
+ uint8_t queue_size; /* max queue size configured */
+ uint8_t queue_len; /* Current number of elements in queue */
+ uint64_t packets;
+ } rx;
+
+ struct {
+ uint32_t errors;
+ uint16_t flags;
+ uint8_t idle_packets;
+ uint8_t queue_size; /* max queue size configured */
+ uint8_t queue_len; /* Current number of elements in queue */
+ uint64_t packets;
+ } tx;
+} ftdm_channel_iostats_t;
+
/* 2^8 table size, one for each byte (sample) value */
#define FTDM_GAINS_TABLE_SIZE 256
struct ftdm_channel {
@@ -441,9 +473,12 @@ struct ftdm_channel {
int availability_rate;
void *user_private;
ftdm_timer_id_t hangup_timer;
-#ifdef FTDM_DEBUG_DTMF
+ ftdm_channel_iostats_t iostats;
ftdm_dtmf_debug_t dtmfdbg;
-#endif
+ ftdm_io_dump_t rxdump;
+ ftdm_io_dump_t txdump;
+ int32_t txdrops;
+ int32_t rxdrops;
};
struct ftdm_span {
@@ -468,6 +503,7 @@ struct ftdm_span {
teletone_multi_tone_t tone_finder[FTDM_TONEMAP_INVALID+1];
ftdm_channel_t *channels[FTDM_MAX_CHANNELS_SPAN+1];
fio_channel_outgoing_call_t outgoing_call;
+ fio_channel_send_msg_t send_msg;
fio_channel_set_sig_status_t set_channel_sig_status;
fio_channel_get_sig_status_t get_channel_sig_status;
fio_span_set_sig_status_t set_span_sig_status;
@@ -476,6 +512,7 @@ struct ftdm_span {
ftdm_span_start_t start;
ftdm_span_stop_t stop;
ftdm_channel_sig_read_t sig_read;
+ ftdm_channel_sig_write_t sig_write;
/* Private I/O data per span. Do not touch unless you are an I/O module */
void *io_data;
char *type;
@@ -637,10 +674,21 @@ FT_DECLARE(void) ftdm_channel_clear_detected_tones(ftdm_channel_t *ftdmchan);
#define ftdm_channel_lock(chan) ftdm_mutex_lock(chan->mutex)
#define ftdm_channel_unlock(chan) ftdm_mutex_unlock(chan->mutex)
+
+#define ftdm_log_throttle(level, ...) \
+ time_current_throttle_log = ftdm_current_time_in_ms(); \
+ if (time_current_throttle_log - time_last_throttle_log > FTDM_THROTTLE_LOG_INTERVAL) {\
+ ftdm_log(level, __VA_ARGS__); \
+ time_last_throttle_log = time_current_throttle_log; \
+ }
+
#define ftdm_log_chan_ex(fchan, file, func, line, level, format, ...) ftdm_log(file, func, line, level, "[s%dc%d][%d:%d] " format, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, __VA_ARGS__)
#define ftdm_log_chan(fchan, level, format, ...) ftdm_log(level, "[s%dc%d][%d:%d] " format, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, __VA_ARGS__)
#define ftdm_log_chan_msg(fchan, level, msg) ftdm_log(level, "[s%dc%d][%d:%d] " msg, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id)
+#define ftdm_log_chan_throttle(fchan, level, format, ...) ftdm_log_throttle(level, "[s%dc%d][%d:%d] " format, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, __VA_ARGS__)
+#define ftdm_log_chan_msg_throttle(fchan, level, format, ...) ftdm_log_throttle(level, "[s%dc%d][%d:%d] " format, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, __VA_ARGS__)
+
#define ftdm_span_lock(span) ftdm_mutex_lock(span->mutex)
#define ftdm_span_unlock(span) ftdm_mutex_unlock(span->mutex)
diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h
index 78ac8f63eb..313044abc4 100644
--- a/libs/freetdm/src/include/private/ftdm_types.h
+++ b/libs/freetdm/src/include/private/ftdm_types.h
@@ -58,6 +58,7 @@ typedef int ftdm_filehandle_t;
extern "C" {
#endif
+#define FTDM_COMMAND_OBJ_SIZE *((ftdm_size_t *)obj)
#define FTDM_COMMAND_OBJ_INT *((int *)obj)
#define FTDM_COMMAND_OBJ_CHAR_P (char *)obj
#define FTDM_COMMAND_OBJ_FLOAT *(float *)obj
@@ -181,6 +182,11 @@ typedef enum {
* after having called ftdm_send_span_signal(), which with this flag it will just enqueue the signal
* for later delivery */
FTDM_SPAN_USE_SIGNALS_QUEUE = (1 << 10),
+ /* If this flag is set, channel will be moved to proceed state when calls goes to routing */
+ FTDM_SPAN_USE_PROCEED_STATE = (1 << 11),
+ /* If this flag is set, the signalling module supports jumping directly to state up, without
+ going through PROGRESS/PROGRESS_MEDIA */
+ FTDM_SPAN_USE_SKIP_STATES = (1 << 12),
} ftdm_span_flag_t;
/*! \brief Channel supported features */
@@ -194,6 +200,7 @@ typedef enum {
FTDM_CHANNEL_FEATURE_CALLWAITING = (1 << 6), /*!< Channel will allow call waiting (ie: FXS devices) (read/write) */
FTDM_CHANNEL_FEATURE_HWEC = (1<<7), /*!< Channel has a hardware echo canceller */
FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE = (1<<8), /*!< hardware echo canceller is disabled when there are no calls on this channel */
+ FTDM_CHANNEL_FEATURE_IO_STATS = (1<<9), /*!< Channel supports IO statistics (HDLC channels only) */
} ftdm_channel_feature_t;
typedef enum {
@@ -203,6 +210,7 @@ typedef enum {
FTDM_CHANNEL_STATE_DIALTONE,
FTDM_CHANNEL_STATE_COLLECT,
FTDM_CHANNEL_STATE_RING,
+ FTDM_CHANNEL_STATE_RINGING,
FTDM_CHANNEL_STATE_BUSY,
FTDM_CHANNEL_STATE_ATTN,
FTDM_CHANNEL_STATE_GENRING,
@@ -210,6 +218,7 @@ typedef enum {
FTDM_CHANNEL_STATE_GET_CALLERID,
FTDM_CHANNEL_STATE_CALLWAITING,
FTDM_CHANNEL_STATE_RESTART,
+ FTDM_CHANNEL_STATE_PROCEED,
FTDM_CHANNEL_STATE_PROGRESS,
FTDM_CHANNEL_STATE_PROGRESS_MEDIA,
FTDM_CHANNEL_STATE_UP,
@@ -222,8 +231,8 @@ typedef enum {
FTDM_CHANNEL_STATE_INVALID
} ftdm_channel_state_t;
#define CHANNEL_STATE_STRINGS "DOWN", "HOLD", "SUSPENDED", "DIALTONE", "COLLECT", \
- "RING", "BUSY", "ATTN", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \
- "RESTART", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "CANCEL", \
+ "RING", "RINGING", "BUSY", "ATTN", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \
+ "RESTART", "PROCEED", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "CANCEL", \
"HANGUP", "HANGUP_COMPLETE", "IN_LOOP", "INVALID"
FTDM_STR2ENUM_P(ftdm_str2ftdm_channel_state, ftdm_channel_state2str, ftdm_channel_state_t)
@@ -258,6 +267,9 @@ typedef enum {
FTDM_CHANNEL_IN_ALARM = (1 << 27),
FTDM_CHANNEL_SIG_UP = (1 << 28),
FTDM_CHANNEL_USER_HANGUP = (1 << 29),
+ FTDM_CHANNEL_RX_DISABLED = (1 << 30),
+ FTDM_CHANNEL_TX_DISABLED = (1 << 31),
+ /* ok, when we reach 32, we need to move to uint64_t all the flag stuff */
} ftdm_channel_flag_t;
#if defined(__cplusplus) && defined(WIN32)
// fix C2676
@@ -374,6 +386,7 @@ typedef struct ftdm_fsk_modulator ftdm_fsk_modulator_t;
typedef ftdm_status_t (*ftdm_span_start_t)(ftdm_span_t *span);
typedef ftdm_status_t (*ftdm_span_stop_t)(ftdm_span_t *span);
typedef ftdm_status_t (*ftdm_channel_sig_read_t)(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t size);
+typedef ftdm_status_t (*ftdm_channel_sig_write_t)(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t size);
typedef enum {
FTDM_ITERATOR_VARS = 1,
diff --git a/libs/freetdm/src/testanalog.c b/libs/freetdm/src/testanalog.c
index 84d09f73c9..326bb5aec5 100644
--- a/libs/freetdm/src/testanalog.c
+++ b/libs/freetdm/src/testanalog.c
@@ -50,7 +50,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_signal)
switch(sigmsg->event_id) {
case FTDM_SIGEVENT_START:
- ftdm_channel_call_indicate(sigmsg->channel, FTDM_CHANNEL_INDICATE_RING);
+ ftdm_channel_call_indicate(sigmsg->channel, FTDM_CHANNEL_INDICATE_RINGING);
ftdm_log(FTDM_LOG_DEBUG, "launching thread and indicating ring\n");
ftdm_thread_create_detached(test_call, sigmsg->channel);
break;
diff --git a/libs/freetdm/src/testsangomaboost.c b/libs/freetdm/src/testsangomaboost.c
index 38eac3c190..01e5a6be22 100644
--- a/libs/freetdm/src/testsangomaboost.c
+++ b/libs/freetdm/src/testsangomaboost.c
@@ -45,10 +45,14 @@
#include
-#include "freetdm.h"
#include
#include
#include
+#if defined(__linux__) && !defined(__USE_BSD)
+#define __USE_BSD
+#endif
+#include
+#include "freetdm.h"
/* arbitrary limit for max calls in this sample program */
@@ -338,9 +342,9 @@ int main(int argc, char *argv[])
exit(-1);
}
- if (!strcasecmp(argv[2], "cpe")) {
+ if (!strcmp(argv[2], "cpe")) {
sigtype = "pri_cpe";
- } else if (!strcasecmp(argv[2], "net")) {
+ } else if (!strcmp(argv[2], "net")) {
sigtype = "pri_net";
} else {
fprintf(stderr, "Valid signaling types are cpe and net only\n");
diff --git a/libs/js/nsprpub/pr/src/io/prmwait.c b/libs/js/nsprpub/pr/src/io/prmwait.c
index 1a2e1cd77b..afdcddf215 100644
--- a/libs/js/nsprpub/pr/src/io/prmwait.c
+++ b/libs/js/nsprpub/pr/src/io/prmwait.c
@@ -235,7 +235,7 @@ void _PR_InitMW(void)
* We use NT 4's InterlockedCompareExchange() to operate
* on PRMWStatus variables.
*/
- PR_ASSERT(sizeof(PVOID) == sizeof(PRMWStatus));
+ //PR_ASSERT(sizeof(PVOID) == sizeof(PRMWStatus));
TimerInit();
#endif
mw_lock = PR_NewLock();
diff --git a/libs/js/src/jscpucfg.h b/libs/js/src/jscpucfg.h
index 7b8b2add45..f8b25d1ef7 100644
--- a/libs/js/src/jscpucfg.h
+++ b/libs/js/src/jscpucfg.h
@@ -44,11 +44,62 @@
#if defined(XP_WIN) || defined(XP_OS2) || defined(WINCE)
+#if defined(_WIN64)
+
+#if defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+
+#define JS_BYTES_PER_BYTE 1Ll
+#define JS_BYTES_PER_SHORT 2L
+#define JS_BYTES_PER_INT 4L
+#define JS_BYTES_PER_INT64 8L
+#define JS_BYTES_PER_LONG 4L
+#define JS_BYTES_PER_FLOAT 4L
+#define JS_BYTES_PER_DOUBLE 8L
+#define JS_BYTES_PER_WORD 8L
+#define JS_BYTES_PER_DWORD 8L
+
+#define JS_BITS_PER_BYTE 8L
+#define JS_BITS_PER_SHORT 16L
+#define JS_BITS_PER_INT 32L
+#define JS_BITS_PER_INT64 64L
+#define JS_BITS_PER_LONG 32L
+#define JS_BITS_PER_FLOAT 32L
+#define JS_BITS_PER_DOUBLE 64L
+#define JS_BITS_PER_WORD 64L
+
+#define JS_BITS_PER_BYTE_LOG2 3L
+#define JS_BITS_PER_SHORT_LOG2 4L
+#define JS_BITS_PER_INT_LOG2 5L
+#define JS_BITS_PER_INT64_LOG2 6L
+#define JS_BITS_PER_LONG_LOG2 5L
+#define JS_BITS_PER_FLOAT_LOG2 5L
+#define JS_BITS_PER_DOUBLE_LOG2 6L
+#define JS_BITS_PER_WORD_LOG2 6L
+
+#define JS_ALIGN_OF_SHORT 2L
+#define JS_ALIGN_OF_INT 4L
+#define JS_ALIGN_OF_LONG 4L
+#define JS_ALIGN_OF_INT64 8L
+#define JS_ALIGN_OF_FLOAT 4L
+#define JS_ALIGN_OF_DOUBLE 8L
+#define JS_ALIGN_OF_POINTER 8L
+#define JS_ALIGN_OF_WORD 8L
+
+#define JS_BYTES_PER_WORD_LOG2 3L
+#define JS_BYTES_PER_DWORD_LOG2 3L
+#define PR_WORDS_PER_DWORD_LOG2 0L
+#else /* !(defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)) */
+#error "CPU type is unknown"
+#endif /* !(defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)) */
+
+#elif defined(_WIN32) || defined(XP_OS2) || defined(WINCE)
+
#ifdef __WATCOMC__
#define HAVE_VA_LIST_AS_ARRAY
#endif
-#if defined(_WIN32) || defined(XP_OS2) || defined(WINCE)
#define IS_LITTLE_ENDIAN 1
#undef IS_BIG_ENDIAN
@@ -95,6 +146,7 @@
#endif /* _WIN32 || XP_OS2 || WINCE*/
#if defined(_WINDOWS) && !defined(_WIN32) /* WIN16 */
+
#define IS_LITTLE_ENDIAN 1
#undef IS_BIG_ENDIAN
@@ -138,6 +190,7 @@
#define JS_BYTES_PER_WORD_LOG2 2L
#define JS_BYTES_PER_DWORD_LOG2 3L
#define PR_WORDS_PER_DWORD_LOG2 1L
+
#endif /* defined(_WINDOWS) && !defined(_WIN32) */
#elif defined(XP_UNIX) || defined(XP_BEOS)
diff --git a/libs/js/src/jstypes.h b/libs/js/src/jstypes.h
index 0a76d478cf..e5d9544413 100644
--- a/libs/js/src/jstypes.h
+++ b/libs/js/src/jstypes.h
@@ -77,35 +77,25 @@
**
***********************************************************************/
#ifdef WIN32
+
/* These also work for __MWERKS__ */
-#define JS_EXTERN_API(__type) extern __declspec(dllexport) __type
-#define JS_EXPORT_API(__type) __declspec(dllexport) __type
-#define JS_EXTERN_DATA(__type) extern __declspec(dllexport) __type
-#define JS_EXPORT_DATA(__type) __declspec(dllexport) __type
+# define JS_EXTERN_API(__type) extern __declspec(dllexport) __type
+# define JS_EXPORT_API(__type) __declspec(dllexport) __type
+# define JS_EXTERN_DATA(__type) extern __declspec(dllexport) __type
+# define JS_EXPORT_DATA(__type) __declspec(dllexport) __type
-#define JS_DLL_CALLBACK
-#define JS_STATIC_DLL_CALLBACK(__x) static __x
+# define JS_DLL_CALLBACK
+# define JS_STATIC_DLL_CALLBACK(__x) static __x
-#elif defined(WIN16)
+#elif defined(XP_OS2) && defined(__declspec)
-#ifdef _WINDLL
-#define JS_EXTERN_API(__type) extern __type _cdecl _export _loadds
-#define JS_EXPORT_API(__type) __type _cdecl _export _loadds
-#define JS_EXTERN_DATA(__type) extern __type _export
-#define JS_EXPORT_DATA(__type) __type _export
+# define JS_EXTERN_API(__type) extern __declspec(dllexport) __type
+# define JS_EXPORT_API(__type) __declspec(dllexport) __type
+# define JS_EXTERN_DATA(__type) extern __declspec(dllexport) __type
+# define JS_EXPORT_DATA(__type) __declspec(dllexport) __type
-#define JS_DLL_CALLBACK __cdecl __loadds
-#define JS_STATIC_DLL_CALLBACK(__x) static __x CALLBACK
-
-#else /* this must be .EXE */
-#define JS_EXTERN_API(__type) extern __type _cdecl _export
-#define JS_EXPORT_API(__type) __type _cdecl _export
-#define JS_EXTERN_DATA(__type) extern __type _export
-#define JS_EXPORT_DATA(__type) __type _export
-
-#define JS_DLL_CALLBACK __cdecl __loadds
-#define JS_STATIC_DLL_CALLBACK(__x) __x JS_DLL_CALLBACK
-#endif /* _WINDLL */
+# define JS_DLL_CALLBACK
+# define JS_STATIC_DLL_CALLBACK(__x) static __x
#else /* Unix */
@@ -126,44 +116,57 @@
#endif
#ifdef _WIN32
-# if defined(__MWERKS__) || defined(__GNUC__)
-# define JS_IMPORT_API(__x) __x
-# else
-# define JS_IMPORT_API(__x) __declspec(dllimport) __x
-# endif
+# if defined(__MWERKS__) || defined(__GNUC__)
+# define JS_IMPORT_API(__x) __x
+# else
+# define JS_IMPORT_API(__x) __declspec(dllimport) __x
+# endif
+#elif defined(XP_OS2) && defined(__declspec)
+# define JS_IMPORT_API(__x) __declspec(dllimport) __x
#else
-# define JS_IMPORT_API(__x) JS_EXPORT_API (__x)
+# define JS_IMPORT_API(__x) JS_EXPORT_API (__x)
#endif
#if defined(_WIN32) && !defined(__MWERKS__)
-# define JS_IMPORT_DATA(__x) __declspec(dllimport) __x
+# define JS_IMPORT_DATA(__x) __declspec(dllimport) __x
+#elif defined(XP_OS2) && defined(__declspec)
+# define JS_IMPORT_DATA(__x) __declspec(dllimport) __x
#else
-# define JS_IMPORT_DATA(__x) JS_EXPORT_DATA (__x)
+# define JS_IMPORT_DATA(__x) JS_EXPORT_DATA (__x)
#endif
/*
* The linkage of JS API functions differs depending on whether the file is
- * used within the JS library or not. Any source file within the JS
+ * used within the JS library or not. Any source file within the JS
* interpreter should define EXPORT_JS_API whereas any client of the library
- * should not.
+ * should not. STATIC_JS_API is used to build JS as a static library.
*/
-#ifdef EXPORT_JS_API
-#define JS_PUBLIC_API(t) JS_EXPORT_API(t)
-#define JS_PUBLIC_DATA(t) JS_EXPORT_DATA(t)
+#if defined(STATIC_JS_API)
+
+# define JS_PUBLIC_API(t) t
+# define JS_PUBLIC_DATA(t) t
+
+#elif defined(EXPORT_JS_API)
+
+# define JS_PUBLIC_API(t) JS_EXPORT_API(t)
+# define JS_PUBLIC_DATA(t) JS_EXPORT_DATA(t)
+
#else
-#define JS_PUBLIC_API(t) JS_IMPORT_API(t)
-#define JS_PUBLIC_DATA(t) JS_IMPORT_DATA(t)
+
+# define JS_PUBLIC_API(t) JS_IMPORT_API(t)
+# define JS_PUBLIC_DATA(t) JS_IMPORT_DATA(t)
+
#endif
#define JS_FRIEND_API(t) JS_PUBLIC_API(t)
#define JS_FRIEND_DATA(t) JS_PUBLIC_DATA(t)
-#ifdef _WIN32
-# define JS_INLINE __inline
+#if defined(_MSC_VER)
+# define JS_INLINE __forceinline
#elif defined(__GNUC__)
# define JS_INLINE
#else
-# define JS_INLINE
+# define JS_INLINE
#endif
/***********************************************************************
@@ -174,7 +177,14 @@
** behave syntactically more like functions when called.
***********************************************************************/
#define JS_BEGIN_MACRO do {
-#define JS_END_MACRO } while (0)
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+# define JS_END_MACRO \
+ } __pragma(warning(push)) __pragma(warning(disable:4127)) \
+ while (0) __pragma(warning(pop))
+#else
+# define JS_END_MACRO } while (0)
+#endif
/***********************************************************************
** MACROS: JS_BEGIN_EXTERN_C
@@ -183,11 +193,15 @@
** Macro shorthands for conditional C++ extern block delimiters.
***********************************************************************/
#ifdef __cplusplus
-#define JS_BEGIN_EXTERN_C extern "C" {
-#define JS_END_EXTERN_C }
+
+# define JS_BEGIN_EXTERN_C extern "C" {
+# define JS_END_EXTERN_C }
+
#else
-#define JS_BEGIN_EXTERN_C
-#define JS_END_EXTERN_C
+
+# define JS_BEGIN_EXTERN_C
+# define JS_END_EXTERN_C
+
#endif
/***********************************************************************
@@ -226,12 +240,12 @@
#define JS_MAX(x,y) ((x)>(y)?(x):(y))
#if (defined(XP_WIN) && !defined(CROSS_COMPILE)) || defined (WINCE)
-# include "jscpucfg.h" /* Use standard Mac or Windows configuration */
+# include "jscpucfg.h" /* Use standard Mac or Windows configuration */
#elif defined(XP_UNIX) || defined(XP_BEOS) || defined(XP_OS2) || defined(CROSS_COMPILE)
-# include "jsautocfg.h" /* Use auto-detected configuration */
+# include "jsautocfg.h" /* Use auto-detected configuration */
# include "jsosdep.h" /* ...and platform-specific flags */
#else
-# error "Must define one of XP_BEOS, XP_OS2, XP_WIN or XP_UNIX"
+# error "Must define one of XP_BEOS, XP_OS2, XP_WIN or XP_UNIX"
#endif
JS_BEGIN_EXTERN_C
@@ -247,7 +261,7 @@ JS_BEGIN_EXTERN_C
typedef unsigned char JSUint8;
typedef signed char JSInt8;
#else
-#error No suitable type for JSInt8/JSUint8
+# error No suitable type for JSInt8/JSUint8
#endif
/************************************************************************
@@ -260,7 +274,7 @@ typedef signed char JSInt8;
typedef unsigned short JSUint16;
typedef short JSInt16;
#else
-#error No suitable type for JSInt16/JSUint16
+# error No suitable type for JSInt16/JSUint16
#endif
/************************************************************************
@@ -272,15 +286,15 @@ typedef short JSInt16;
#if JS_BYTES_PER_INT == 4
typedef unsigned int JSUint32;
typedef int JSInt32;
-#define JS_INT32(x) x
-#define JS_UINT32(x) x ## U
+# define JS_INT32(x) x
+# define JS_UINT32(x) x ## U
#elif JS_BYTES_PER_LONG == 4
typedef unsigned long JSUint32;
typedef long JSInt32;
-#define JS_INT32(x) x ## L
-#define JS_UINT32(x) x ## UL
+# define JS_INT32(x) x ## L
+# define JS_UINT32(x) x ## UL
#else
-#error No suitable type for JSInt32/JSUint32
+# error No suitable type for JSInt32/JSUint32
#endif
/************************************************************************
@@ -294,28 +308,32 @@ typedef long JSInt32;
** the JSLL_ macros (see jslong.h).
************************************************************************/
#ifdef JS_HAVE_LONG_LONG
-#if JS_BYTES_PER_LONG == 8
+
+# if JS_BYTES_PER_LONG == 8
typedef long JSInt64;
typedef unsigned long JSUint64;
-#elif defined(WIN16)
+# elif defined(WIN16)
typedef __int64 JSInt64;
typedef unsigned __int64 JSUint64;
-#elif defined(WIN32) && !defined(__GNUC__)
+# elif defined(WIN32) && !defined(__GNUC__)
typedef __int64 JSInt64;
typedef unsigned __int64 JSUint64;
-#else
+# else
typedef long long JSInt64;
typedef unsigned long long JSUint64;
-#endif /* JS_BYTES_PER_LONG == 8 */
+# endif /* JS_BYTES_PER_LONG == 8 */
+
#else /* !JS_HAVE_LONG_LONG */
+
typedef struct {
-#ifdef IS_LITTLE_ENDIAN
+# ifdef IS_LITTLE_ENDIAN
JSUint32 lo, hi;
-#else
+# else
JSUint32 hi, lo;
#endif
} JSInt64;
typedef JSInt64 JSUint64;
+
#endif /* !JS_HAVE_LONG_LONG */
/************************************************************************
@@ -331,7 +349,7 @@ typedef JSInt64 JSUint64;
typedef int JSIntn;
typedef unsigned int JSUintn;
#else
-#error 'sizeof(int)' not sufficient for platform use
+# error 'sizeof(int)' not sufficient for platform use
#endif
/************************************************************************
@@ -362,7 +380,11 @@ typedef ptrdiff_t JSPtrdiff;
** A type for pointer difference. Variables of this type are suitable
** for storing a pointer or pointer sutraction.
************************************************************************/
+#if JS_BYTES_PER_WORD == 8 && JS_BYTES_PER_LONG != 8
+typedef JSUint64 JSUptrdiff;
+#else
typedef unsigned long JSUptrdiff;
+#endif
/************************************************************************
** TYPES: JSBool
@@ -380,15 +402,20 @@ typedef JSIntn JSBool;
** TYPES: JSPackedBool
** DESCRIPTION:
** Use JSPackedBool within structs where bitfields are not desireable
-** but minimum and consistant overhead matters.
+** but minimum and consistent overhead matters.
************************************************************************/
typedef JSUint8 JSPackedBool;
/*
** A JSWord is an integer that is the same size as a void*
*/
+#if JS_BYTES_PER_WORD == 8 && JS_BYTES_PER_LONG != 8
+typedef JSInt64 JSWord;
+typedef JSUint64 JSUword;
+#else
typedef long JSWord;
typedef unsigned long JSUword;
+#endif
#include "jsotypes.h"
@@ -409,13 +436,37 @@ typedef unsigned long JSUword;
**
***********************************************************************/
#if defined(__GNUC__) && (__GNUC__ > 2)
-#define JS_LIKELY(x) (__builtin_expect((x), 1))
-#define JS_UNLIKELY(x) (__builtin_expect((x), 0))
+
+# define JS_LIKELY(x) (__builtin_expect((x), 1))
+# define JS_UNLIKELY(x) (__builtin_expect((x), 0))
+
#else
-#define JS_LIKELY(x) (x)
-#define JS_UNLIKELY(x) (x)
+
+# define JS_LIKELY(x) (x)
+# define JS_UNLIKELY(x) (x)
+
#endif
+/***********************************************************************
+** MACROS: JS_ARRAY_LENGTH
+** JS_ARRAY_END
+** DESCRIPTION:
+** Macros to get the number of elements and the pointer to one past the
+** last element of a C array. Use them like this:
+**
+** jschar buf[10], *s;
+** JSString *str;
+** ...
+** for (s = buf; s != JS_ARRAY_END(buf); ++s) *s = ...;
+** ...
+** str = JS_NewStringCopyN(cx, buf, JS_ARRAY_LENGTH(buf));
+** ...
+**
+***********************************************************************/
+
+#define JS_ARRAY_LENGTH(array) (sizeof (array) / sizeof (array)[0])
+#define JS_ARRAY_END(array) ((array) + JS_ARRAY_LENGTH(array))
+
JS_END_EXTERN_C
#endif /* jstypes_h___ */
diff --git a/libs/libsndfile/M4/lt~obsolete.m4 b/libs/libsndfile/M4/lt~obsolete.m4
deleted file mode 100644
index c573da90c5..0000000000
--- a/libs/libsndfile/M4/lt~obsolete.m4
+++ /dev/null
@@ -1,98 +0,0 @@
-# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
-#
-# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
-# Written by Scott James Remnant, 2004.
-#
-# This file is free software; the Free Software Foundation gives
-# unlimited permission to copy and/or distribute it, with or without
-# modifications, as long as this notice is preserved.
-
-# serial 5 lt~obsolete.m4
-
-# These exist entirely to fool aclocal when bootstrapping libtool.
-#
-# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
-# which have later been changed to m4_define as they aren't part of the
-# exported API, or moved to Autoconf or Automake where they belong.
-#
-# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
-# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
-# using a macro with the same name in our local m4/libtool.m4 it'll
-# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
-# and doesn't know about Autoconf macros at all.)
-#
-# So we provide this file, which has a silly filename so it's always
-# included after everything else. This provides aclocal with the
-# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
-# because those macros already exist, or will be overwritten later.
-# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
-#
-# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
-# Yes, that means every name once taken will need to remain here until
-# we give up compatibility with versions before 1.7, at which point
-# we need to keep only those names which we still refer to.
-
-# This is to help aclocal find these macros, as it can't see m4_define.
-AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
-
-m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
-m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
-m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
-m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
-m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
-m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
-m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
-m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
-m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
-m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
-m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
-m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
-m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
-m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
-m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
-m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
-m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
-m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
-m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
-m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
-m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
-m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
-m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
-m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
-m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
-m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
-m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
-m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
-m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
-m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
-m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
-m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
-m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
-m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
-m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
-m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
-m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
-m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
-m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
-m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
-m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
-m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
-m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
-m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
-m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
-m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
-m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
-m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
-m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
-m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
-m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
-m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
-m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
-m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
-m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
-m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])])
-m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
-m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
-m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
-m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
-m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])
diff --git a/libs/stfu/stfu.c b/libs/stfu/stfu.c
index 7c30ab2ad4..0422cd2081 100644
--- a/libs/stfu/stfu.c
+++ b/libs/stfu/stfu.c
@@ -47,6 +47,7 @@ struct stfu_instance {
struct stfu_queue *in_queue;
struct stfu_queue *out_queue;
struct stfu_frame *last_frame;
+ uint32_t cur_ts;
uint32_t last_wr_ts;
uint32_t last_rd_ts;
uint32_t interval;
@@ -267,27 +268,26 @@ static int stfu_n_find_frame(stfu_queue_t *queue, uint32_t ts, stfu_frame_t **r_
stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i)
{
uint32_t index;
- uint32_t should_have = 0;
stfu_frame_t *rframe = NULL;
-
+
if (((i->out_queue->wr_len == i->out_queue->array_len) || !i->out_queue->array_len)) {
return NULL;
}
- if (i->last_wr_ts) {
- should_have = i->last_wr_ts + i->interval;
- } else {
- should_have = i->out_queue->array[0].ts;
- }
+ if (i->cur_ts == 0) {
+ i->cur_ts = i->out_queue->array[0].ts;
+ } else {
+ i->cur_ts += i->interval;
+ }
+
- if (stfu_n_find_frame(i->out_queue, should_have, &rframe, &index) || stfu_n_find_frame(i->in_queue, should_have, &rframe, &index)) {
+ if (stfu_n_find_frame(i->out_queue, i->cur_ts, &rframe, &index) || stfu_n_find_frame(i->in_queue, i->cur_ts, &rframe, &index)) {
i->last_frame = rframe;
i->out_queue->wr_len++;
i->last_wr_ts = rframe->ts;
- rframe->was_read = 1;
i->miss_count = 0;
} else {
- i->last_wr_ts = should_have;
+ i->last_wr_ts = i->cur_ts;
rframe = &i->out_queue->int_frame;
if (i->last_frame && i->last_frame != rframe) {
@@ -296,12 +296,11 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i)
memcpy(rframe->data, i->last_frame->data, rframe->dlen);
}
- rframe->ts = should_have;
+ rframe->ts = i->cur_ts;
if (++i->miss_count > i->max_plc) {
- i->interval = 0;
i->out_queue->wr_len = i->out_queue->array_size;
- i->last_wr_ts = 0;
+ i->cur_ts = 0;
rframe = NULL;
}
}
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_consumer_task.c b/libs/unimrcp/libs/apr-toolkit/src/apt_consumer_task.c
index 3b96373a74..ceb9320d98 100644
--- a/libs/unimrcp/libs/apr-toolkit/src/apt_consumer_task.c
+++ b/libs/unimrcp/libs/apr-toolkit/src/apt_consumer_task.c
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include
#include
#include "apt_consumer_task.h"
#include "apt_log.h"
diff --git a/libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2010.vcxproj b/libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2010.vcxproj
index c6aaba5cd6..b3931497c7 100644
--- a/libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2010.vcxproj
+++ b/libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2010.vcxproj
@@ -127,6 +127,11 @@
+
+
+ {70a49bc2-7500-41d0-b75d-edcc5be987a0}
+
+
diff --git a/scripts/perl/add_user b/scripts/perl/add_user
new file mode 100755
index 0000000000..d16ebb5efe
--- /dev/null
+++ b/scripts/perl/add_user
@@ -0,0 +1,306 @@
+#!/usr/bin/perl
+#
+# add_user
+#
+# Add one or more users to the XML directory
+#
+#
+
+use strict;
+use warnings;
+use Getopt::Long;
+use Data::Dumper;
+
+## Useful items
+my $path_sep;
+my $config_path;
+my @dir_elem;
+my $user_template = &get_user_template;
+my $new_user_count = 0;
+
+## Command line args
+my $users;
+my $domain;
+my $dirpath;
+my $help;
+
+## Misc items somewhat related to cmd line args
+my $start;
+my $end;
+my $user;
+
+## Check for Windows vs. *nix
+if ( $^O =~ m/^win/i ) {
+ ## Detected Windows (probably)
+ $path_sep = "\\"; # single backslash (\)
+ use File::Spec::Win32;
+} else {
+ $path_sep = '/'; # single slash (/)
+ use File::Spec;
+}
+
+GetOptions(
+ 'h' => \$help,
+ 'help' => \$help,
+ 'domain=s' => \$domain,
+ 'users=s' => \$users,
+ 'confpath=s' => \$config_path,
+);
+
+if ( $help ) {
+ usage();
+ exit(0);
+}
+
+if ( ! $domain ) {
+ $domain='default';
+}
+
+## Validate users if specified on command line
+if ( $users ) {
+ ($start,$end) = split /-/,$users;
+ if ( ! $start && ! $end ) {
+ die "Please specify both a start and end range, separated by a hyphen:\n add_user --users=xxxx-yyyy\n";
+ }
+
+ unless ( $start =~ m/[1-9]\d+/ ) {
+ die "Start of range '$start' is not numeric or is too short\n";
+ }
+
+ unless ( $end =~ m/[1-9]\d+/ ) {
+ die "End of range '$end' is not numberic or is too short\n";
+ }
+
+ if ( $end <= $start ) {
+ die "End of range needs to be greater than start of range\n";
+ }
+} else {
+ ## Look for user id in $ARGV[0]
+ if ( ! $ARGV[0] ) {
+ die "You must specify user id as a command line argument to add user, or use the --users option.\n";
+ }
+ unless ( $ARGV[0] =~ m/^[1-9]\d+$/ ) {
+ die "User id must be numeric, be at least 2 digits long, and cannot begin with the digit zero.\n"
+ }
+ $user = $ARGV[0];
+}
+
+if ( ! $config_path ) {
+ $config_path = '/usr/local/freeswitch/conf';
+}
+
+## Check to make sure the directories in question exists
+unless ( -d $config_path ) {
+ die "Configuration path '$config_path' does not exist.\n";
+}
+
+my $directory_path = $config_path . $path_sep . 'directory';
+unless ( -d $directory_path ) {
+ die "Directory path '$directory_path' does not exist.\n";
+}
+
+## Now check domain pathname and test existence
+if ( ! $domain ) {
+ $domain = 'default';
+}
+
+## Full directory path includes the domain name
+my $full_dir_path = $directory_path . $path_sep . $domain;
+unless ( -d $full_dir_path ) {
+ die "Full path to directory and domain '$full_dir_path' does not exist. \n";
+}
+
+unless ( -w $full_dir_path ) {
+ die "This user does not have write access to '$full_dir_path'.\n";
+}
+print "\n";
+
+## Regexp assemble items to show user what a PCRE might look like for his new users
+my $ra_present;
+my $ra_new;
+my $ra_all;
+eval { require Regexp::Assemble; };
+if ( ! $@ ) {
+ ## If Regexp::Assemble is available flag it for later building regexes
+ $ra_present = 'true';
+ $ra_new = Regexp::Assemble->new( # new user regex
+ reduce => 1,
+ flags => 0,
+);
+ $ra_all = Regexp::Assemble->new( # all users regex w/ new users thrown in
+ reduce => 1,
+ flags => 0,
+);
+}
+
+## If we're this far then we can read in the existing users and put them in a hash
+## Later we can check hash to avoid adding duplicate users
+my %current_users;
+my @CURRENT_USER_FILES = glob($full_dir_path . $path_sep . '*.xml');
+foreach ( @CURRENT_USER_FILES ) {
+ #print "User: $_\n";
+ open(FILEIN,'<',$_);
+ while() {
+ next unless m/user id|number-alias/;
+ m/user id="(\d+)"/;
+ my $user_id = $1;
+ if ( ! $user_id ) {
+ m/alias="(\d+)"/;
+ $user_id = $1;
+ }
+
+ next unless $user_id;
+ $current_users{$user_id}++;
+
+ if ( $ra_present && $user_id =~ m/^\d+$/ ) {
+ #print "Adding $user_id to \$re_all...\n";
+ $ra_all->add($user_id)->anchor_line_begin->anchor_line_end;
+ }
+ last;
+ }
+ close(FILEIN);
+}
+
+#print Dumper(%current_users) . "\n";
+if ( $start && $end ) {
+ ## Add range of users
+ foreach $user ($start .. $end) {
+ &add_user($user);
+ }
+} else {
+ ## Add single user
+ &add_user($user);
+}
+
+print "\nOperation complete. ";
+if ( $new_user_count == 0 ) {
+ print "No users added.\n";
+ exit(0);
+} else {
+ printf "%d user%s added.\n", $new_user_count, $new_user_count==1 ? "" : "s";
+ print "Be sure to reloadxml.\n\n";
+}
+
+if ( $ra_present ) {
+ print "Regular expression information:\n\n";
+ ## Regexp::Assemble adds some stuff we really don't need
+ ## These lines just make the regexp pattern a bit more readable
+ my $tmp = $ra_new->as_string;
+ $tmp =~ s/\?://g;
+ $tmp =~ s/^\(\?\-xism:\^/^(/;
+ $tmp =~ s/\$\)$/)\$/;
+ $tmp =~ s/\\d/[0-9]/g; # [0-9] is sometimes easier to read than \d
+ print " Sample regex for all new users: " . $tmp . "\n";
+ $tmp = $ra_all->as_string;
+ $tmp =~ s/\?://g;
+ $tmp =~ s/^\(\?\-xism:\^/^(/;
+ $tmp =~ s/\$\)$/)\$/;
+ $tmp =~ s/\\d/[0-9]/g; # [0-9] is sometimes easier to read than \d
+ print "Sample regex for all new AND current users: " . $tmp . "\n\n";
+ print "In the default configuration you can modify the expression in the condition for 'Local_Extension'.\n";
+ print ""
+} else {
+ print "If CPAN module Regexp::Assemble were installed this program would be able to suggest a regex for your new users.\n"
+}
+
+exit(0);
+
+sub add_user {
+ my $user_id = shift;
+ if ( exists( $current_users{$user_id} ) ) {
+ warn "User id $user_id already exists, skipping...\n";
+ } else {
+ my $new_user = $user_template;
+ $new_user =~ s/__USERID__/$user_id/g;
+ #print "Adding user id '$user_id' with this XML:\n";
+ #print $new_user . "\n";
+
+ ## Attempt to create the user file
+ my $user_file_name = $full_dir_path . $path_sep . $user_id . '.xml';
+
+ ## Does it already exist?
+ if ( -f $user_file_name ) {
+ warn "$user_file_name exists, skipping...\n";
+ }
+ my $fh;
+ open($fh,'>',$user_file_name);
+ if ( ! $fh ) {
+ warn "Unable to open '$user_file_name' - $!\n";
+ warn "Skipping...\n";
+ next;
+ }
+
+ print $fh $new_user;
+ close($fh);
+ print "Added $user_id in file $user_file_name \n";
+ $new_user_count++;
+ if ( $ra_present ) {
+ $ra_new->add($user_id)->anchor_line_begin->anchor_line_end;
+ $ra_all->add($user_id)->anchor_line_begin->anchor_line_end;
+ }
+ }
+
+}
+
+sub get_user_template {
+ my $templ = <
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ENDUSERTEMPLATE
+
+ return $templ;
+}
+
+sub usage {
+ print < [--domain=] [--confpath=]
+ add_user --users=- [--domain=] [--confpath=]
+
+In its simplest form, add_user will simply add the user_id specified at the command line.
+By default, users are added to the "default" domain. Use the --domain option to specify
+a different domain for the user(s) that are added.
+
+To specify a range of user IDs use the --users option. Separate the beginning and
+end of the range with a hyphen (-) character.
+
+By default add_user will look for the XML directory in its default location of
+/usr/local/freeswitch/conf/directory. Use the --confpath (configuration path)
+option to specify an alternate directory location.
+
+
+ NOTES:
+
+add_user assumes
+User IDs must be numeric and cannot begin with zero.
+User IDs must be at least two digits long and have no specific length limit.
+If a user ID exists it will be skipped.
+If a domain specified does not exist no users will be created.
+
+ENDUSAGE
+
+}
diff --git a/scripts/perl/blacklist.pl b/scripts/perl/blacklist.pl
index f434669f36..a2834b62bf 100755
--- a/scripts/perl/blacklist.pl
+++ b/scripts/perl/blacklist.pl
@@ -17,13 +17,17 @@ my @netblocks = split(/\n/, get("http://www.infiltrated.net/voipabuse/netblocks.
print "\n";
foreach $addr (@addresses) {
- print " \n";
+ $addr =~ s/\s//g; # strip whitespace
+ next unless $addr =~ m/\d+\.\d+\.\d+\.\d+/; # imperfect but useful IP addr check
+ print " \n";
}
print "
\n";
print "\n";
foreach $netb (@netblocks) {
- print " \n";
+ $netb =~ s/\s//g; # strip whitespace
+ next unless $netb =~ m/\d+\.\d+\.\d+\.\d+/; # imperfect but useful IP addr check
+ print " \n";
}
print "
\n";
diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h
index 3df9001b0c..13410a00ae 100644
--- a/src/include/private/switch_core_pvt.h
+++ b/src/include/private/switch_core_pvt.h
@@ -135,6 +135,7 @@ struct switch_core_session {
switch_mutex_t *frame_read_mutex;
switch_thread_rwlock_t *rwlock;
+ switch_thread_rwlock_t *io_rwlock;
void *streams[SWITCH_MAX_STREAMS];
int stream_count;
diff --git a/src/include/switch_apr.h b/src/include/switch_apr.h
index b049c05d40..8a4928d14a 100644
--- a/src/include/switch_apr.h
+++ b/src/include/switch_apr.h
@@ -592,6 +592,22 @@ SWITCH_DECLARE(switch_status_t) switch_queue_create(switch_queue_t ** queue, uns
*/
SWITCH_DECLARE(switch_status_t) switch_queue_pop(switch_queue_t *queue, void **data);
+/**
+ * pop/get an object from the queue, blocking if the queue is already empty
+ *
+ * @param queue the queue
+ * @param data the data
+ * @param timeout The amount of time in microseconds to wait. This is
+ * a maximum, not a minimum. If the condition is signaled, we
+ * will wake up before this time, otherwise the error APR_TIMEUP
+ * is returned.
+ * @returns APR_TIMEUP the request timed out
+ * @returns APR_EINTR the blocking was interrupted (try again)
+ * @returns APR_EOF if the queue has been terminated
+ * @returns APR_SUCCESS on a successfull pop
+ */
+SWITCH_DECLARE(switch_status_t) switch_queue_pop_timeout(switch_queue_t *queue, void **data, switch_interval_time_t timeout);
+
/**
* push/add a object to the queue, blocking if the queue is already full
*
diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h
index a1f13edd85..d6bce5e8bf 100644
--- a/src/include/switch_channel.h
+++ b/src/include/switch_channel.h
@@ -179,8 +179,8 @@ SWITCH_DECLARE(void) switch_channel_uninit(switch_channel_t *channel);
SWITCH_DECLARE(void) switch_channel_set_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile);
/*!
- \brief Retrive the given channel's caller profile
- \param channel channel to retrive the profile from
+ \brief Retrieve the given channel's caller profile
+ \param channel channel to retrieve the profile from
\return the requested profile
*/
SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_caller_profile(switch_channel_t *channel);
@@ -195,8 +195,8 @@ SWITCH_DECLARE(void) switch_channel_set_originator_caller_profile(switch_channel
SWITCH_DECLARE(void) switch_channel_set_hunt_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile);
/*!
- \brief Retrive the given channel's originator caller profile
- \param channel channel to retrive the profile from
+ \brief Retrieve the given channel's originator caller profile
+ \param channel channel to retrieve the profile from
\return the requested profile
*/
SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_originator_caller_profile(switch_channel_t *channel);
@@ -209,8 +209,8 @@ SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_originator_caller_p
SWITCH_DECLARE(void) switch_channel_set_originatee_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile);
/*!
- \brief Retrive the given channel's originatee caller profile
- \param channel channel to retrive the profile from
+ \brief Retrieve the given channel's originatee caller profile
+ \param channel channel to retrieve the profile from
\return the requested profile
*/
SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_originatee_caller_profile(switch_channel_t *channel);
@@ -223,16 +223,16 @@ SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_originatee_caller_p
SWITCH_DECLARE(void) switch_channel_set_origination_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile);
/*!
- \brief Retrive the given channel's origination caller profile
- \param channel channel to retrive the profile from
+ \brief Retrieve the given channel's origination caller profile
+ \param channel channel to retrieve the profile from
\return the requested profile
*/
SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_origination_caller_profile(switch_channel_t *channel);
/*!
- \brief Retrive the given channel's unique id
- \param channel channel to retrive the unique id from
+ \brief Retrieve the given channel's unique id
+ \param channel channel to retrieve the unique id from
\return the unique id
*/
SWITCH_DECLARE(char *) switch_channel_get_uuid(switch_channel_t *channel);
@@ -241,7 +241,7 @@ SWITCH_DECLARE(char *) switch_channel_get_uuid(switch_channel_t *channel);
\brief Set a variable on a given channel
\param channel channel to set variable on
\param varname the name of the variable
- \param value the vaule of the variable
+ \param value the value of the variable
\returns SWITCH_STATUS_SUCCESS if successful
*/
diff --git a/src/include/switch_core.h b/src/include/switch_core.h
index 3f636d00c4..840a06c204 100644
--- a/src/include/switch_core.h
+++ b/src/include/switch_core.h
@@ -354,6 +354,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_destroy(void);
///\ingroup core1
///\{
+
+SWITCH_DECLARE(switch_status_t) switch_core_session_io_read_lock(switch_core_session_t *session);
+SWITCH_DECLARE(switch_status_t) switch_core_session_io_write_lock(switch_core_session_t *session);
+SWITCH_DECLARE(switch_status_t) switch_core_session_io_rwunlock(switch_core_session_t *session);
+
#ifdef SWITCH_DEBUG_RWLOCKS
SWITCH_DECLARE(switch_status_t) switch_core_session_perform_read_lock(_In_ switch_core_session_t *session, const char *file, const char *func, int line);
#endif
@@ -882,6 +887,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_exec(_In_ switch_core_sessio
SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flags(_In_ switch_core_session_t *session,
_In_ const char *app, _In_opt_z_ const char *arg, _Out_opt_ int32_t *flags);
+SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_async(switch_core_session_t *session, const char *app, const char *arg);
+
SWITCH_DECLARE(switch_status_t) switch_core_session_get_app_flags(const char *app, int32_t *flags);
/*!
@@ -1024,6 +1031,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_queue_event(_In_ switch_core
*/
SWITCH_DECLARE(uint32_t) switch_core_session_event_count(_In_ switch_core_session_t *session);
+/*
+ Number of parsable messages waiting on the session.
+ */
+SWITCH_DECLARE(uint32_t) switch_core_session_messages_waiting(switch_core_session_t *session);
+
/*!
\brief DE-Queue an event on a given session
\param session the session to de-queue the message on
diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h
index 249ac63a58..da366c5b8d 100644
--- a/src/include/switch_ivr.h
+++ b/src/include/switch_ivr.h
@@ -874,6 +874,12 @@ SWITCH_DECLARE(void) switch_ivr_dmachine_set_input_timeout_ms(switch_ivr_dmachin
SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_clear_realm(switch_ivr_dmachine_t *dmachine, const char *realm);
SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_set_realm(switch_ivr_dmachine_t *dmachine, const char *realm);
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_get_file_handle(switch_core_session_t *session, switch_file_handle_t **fh);
+SWITCH_DECLARE(switch_status_t) switch_ivr_release_file_handle(switch_core_session_t *session, switch_file_handle_t **fh);
+SWITCH_DECLARE(switch_status_t) switch_ivr_process_fh(switch_core_session_t *session, const char *cmd, switch_file_handle_t *fhp);
+SWITCH_DECLARE(switch_status_t) switch_ivr_insert_file(switch_core_session_t *session, const char *file, const char *insert_file, switch_size_t sample_point);
+
/** @} */
SWITCH_END_EXTERN_C
diff --git a/src/mod/.gitignore b/src/mod/.gitignore
index 47cdbafa70..b6e7842a50 100644
--- a/src/mod/.gitignore
+++ b/src/mod/.gitignore
@@ -7,6 +7,7 @@
/applications/mod_spandsp/mod_spandsp.log
/applications/mod_commands/Makefile
/applications/mod_conference/Makefile
+/applications/mod_db/Makefile
/applications/mod_dptools/Makefile
/applications/mod_enum/Makefile
/applications/mod_enum/Makefile.in
diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c
index 1b0ba1331a..ca92b17fa4 100644
--- a/src/mod/applications/mod_callcenter/mod_callcenter.c
+++ b/src/mod/applications/mod_callcenter/mod_callcenter.c
@@ -1346,6 +1346,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_time_t t_agent_called = 0;
switch_time_t t_agent_answered = 0;
switch_time_t t_member_called = atoi(h->member_joined_epoch);
+ switch_event_t *event = NULL;
switch_mutex_lock(globals.mutex);
globals.threads++;
@@ -1360,6 +1361,21 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_safe_free(sql);
goto done;
}
+
+ /* Proceed contact the agent to offer the member */
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", h->queue_name);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "agent-offering");
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-Type", h->agent_type);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-System", h->agent_system);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
+ switch_event_fire(&event);
+ }
+
+ /* CallBack Mode */
if (!strcasecmp(h->agent_type, CC_AGENT_TYPE_CALLBACK)) {
switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_queue", "%s", h->queue_name);
@@ -1375,6 +1391,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_safe_free(dialstr);
switch_event_destroy(&ovars);
+ /* UUID Standby Mode */
} else if (!strcasecmp(h->agent_type, CC_AGENT_TYPE_UUID_STANDBY)) {
agent_session = switch_core_session_locate(h->agent_uuid);
if (agent_session) {
@@ -1400,14 +1417,17 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
cc_agent_update("status", cc_agent_status2str(CC_AGENT_STATUS_LOGGED_OUT), h->agent_name);
cc_agent_update("uuid", "", h->agent_name);
}
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Invalid agent type '%s' for agent '%s', aborting member offering", h->agent_type, h->agent_name);
+ status = SWITCH_CAUSE_USER_NOT_REGISTERED;
}
+ /* Originate/Bridge is not finished, processing the return value */
if (status == SWITCH_STATUS_SUCCESS) {
/* Agent Answered */
const char *agent_uuid = switch_core_session_get_uuid(agent_session);
switch_channel_t *member_channel = switch_core_session_get_channel(member_session);
switch_channel_t *agent_channel = switch_core_session_get_channel(agent_session);
- switch_event_t *event;
switch_channel_set_variable(agent_channel, "cc_member_pre_answer_uuid", NULL);
diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c
index 40ec1ee2f6..a99c884529 100644
--- a/src/mod/applications/mod_commands/mod_commands.c
+++ b/src/mod/applications/mod_commands/mod_commands.c
@@ -2491,24 +2491,47 @@ SWITCH_STANDARD_API(uuid_display_function)
#define SIMPLIFY_SYNTAX ""
SWITCH_STANDARD_API(uuid_simplify_function)
{
+ char *mydata = NULL, *argv[2] = { 0 };
+ int argc = 0;
+
switch_status_t status = SWITCH_STATUS_FALSE;
if (zstr(cmd)) {
- stream->write_function(stream, "-USAGE: %s\n", SIMPLIFY_SYNTAX);
- } else {
+ goto error;
+ }
+
+ mydata = strdup(cmd);
+ switch_assert(mydata);
+
+ argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+
+ if (argc < 1) {
+ goto error;
+ }
+ if (argv[0]) {
switch_core_session_message_t msg = { 0 };
switch_core_session_t *lsession = NULL;
msg.message_id = SWITCH_MESSAGE_INDICATE_SIMPLIFY;
- msg.string_arg = cmd;
+ msg.string_arg = argv[0];
msg.from = __FILE__;
- if ((lsession = switch_core_session_locate(cmd))) {
+ if ((lsession = switch_core_session_locate(argv[0]))) {
status = switch_core_session_receive_message(lsession, &msg);
switch_core_session_rwunlock(lsession);
}
+ goto ok;
+ } else {
+ goto error;
}
+ error:
+ stream->write_function(stream, "-USAGE: %s\n", SIMPLIFY_SYNTAX);
+ switch_safe_free(mydata);
+ return SWITCH_STATUS_SUCCESS;
+ ok:
+ switch_safe_free(mydata);
+
if (status == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "+OK Success\n");
} else {
@@ -3968,6 +3991,47 @@ SWITCH_STANDARD_API(uuid_getvar_function)
return SWITCH_STATUS_SUCCESS;
}
+
+#define FILEMAN_SYNTAX " :"
+SWITCH_STANDARD_API(uuid_fileman_function)
+{
+ switch_core_session_t *psession = NULL;
+ char *mycmd = NULL, *argv[4] = { 0 };
+ int argc = 0;
+
+ if (!zstr(cmd) && (mycmd = strdup(cmd))) {
+ argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+ if (argc >= 2 && !zstr(argv[0])) {
+ char *uuid = argv[0];
+ char *cmd = argv[1];
+
+ if ((psession = switch_core_session_locate(uuid))) {
+ switch_channel_t *channel;
+ switch_file_handle_t *fh = NULL;
+
+ channel = switch_core_session_get_channel(psession);
+
+ if (switch_ivr_get_file_handle(psession, &fh) == SWITCH_STATUS_SUCCESS) {
+ switch_ivr_process_fh(psession, cmd, fh);
+ switch_ivr_release_file_handle(psession, &fh);
+ }
+
+ switch_core_session_rwunlock(psession);
+
+ } else {
+ stream->write_function(stream, "-ERR No Such Channel!\n");
+ }
+ goto done;
+ }
+ }
+
+ stream->write_function(stream, "-USAGE: %s\n", GETVAR_SYNTAX);
+
+ done:
+ switch_safe_free(mycmd);
+ return SWITCH_STATUS_SUCCESS;
+}
+
#define UUID_SEND_DTMF_SYNTAX " "
SWITCH_STANDARD_API(uuid_send_dtmf_function)
{
@@ -4674,6 +4738,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
SWITCH_ADD_API(commands_api_interface, "uuid_display", "change display", uuid_display_function, DISPLAY_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_dump", "uuid_dump", uuid_dump_function, DUMP_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_exists", "see if a uuid exists", uuid_exists_function, EXISTS_SYNTAX);
+ SWITCH_ADD_API(commands_api_interface, "uuid_fileman", "uuid_fileman", uuid_fileman_function, FILEMAN_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_flush_dtmf", "Flush dtmf on a given uuid", uuid_flush_dtmf_function, "");
SWITCH_ADD_API(commands_api_interface, "uuid_getvar", "uuid_getvar", uuid_getvar_function, GETVAR_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_hold", "hold", uuid_hold_function, HOLD_SYNTAX);
@@ -4785,6 +4850,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
switch_console_set_complete("add uuid_display ::console::list_uuid");
switch_console_set_complete("add uuid_dump ::console::list_uuid");
switch_console_set_complete("add uuid_exists ::console::list_uuid");
+ switch_console_set_complete("add uuid_fileman ::console::list_uuid");
switch_console_set_complete("add uuid_flush_dtmf ::console::list_uuid");
switch_console_set_complete("add uuid_getvar ::console::list_uuid");
switch_console_set_complete("add uuid_hold ::console::list_uuid");
@@ -4810,6 +4876,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
switch_console_set_complete("add uuid_session_heartbeat ::console::list_uuid");
switch_console_set_complete("add uuid_setvar_multi ::console::list_uuid");
switch_console_set_complete("add uuid_setvar ::console::list_uuid");
+ switch_console_set_complete("add uuid_simplify ::console::list_uuid");
switch_console_set_complete("add uuid_transfer ::console::list_uuid");
switch_console_set_complete("add uuid_dual_transfer ::console::list_uuid");
switch_console_set_complete("add version");
diff --git a/src/mod/applications/mod_hash/mod_hash.c b/src/mod/applications/mod_hash/mod_hash.c
index 29a056104f..2609b6cb87 100644
--- a/src/mod/applications/mod_hash/mod_hash.c
+++ b/src/mod/applications/mod_hash/mod_hash.c
@@ -130,7 +130,7 @@ SWITCH_LIMIT_INCR(limit_incr_hash)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
char *hashkey = NULL;
- switch_bool_t status = SWITCH_STATUS_SUCCESS;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
limit_hash_item_t *item = NULL;
time_t now = switch_epoch_time_now(NULL);
limit_hash_private_t *pvt = NULL;
diff --git a/src/mod/applications/mod_lcr/mod_lcr.c b/src/mod/applications/mod_lcr/mod_lcr.c
index cc93707367..5f70e0ab77 100644
--- a/src/mod/applications/mod_lcr/mod_lcr.c
+++ b/src/mod/applications/mod_lcr/mod_lcr.c
@@ -1387,7 +1387,6 @@ SWITCH_STANDARD_DIALPLAN(lcr_dialplan_hunt)
switch_channel_t *channel = switch_core_session_get_channel(session);
callback_t routes = { 0 };
lcr_route cur_route = { 0 };
- char *lcr_profile = NULL;
switch_memory_pool_t *pool = NULL;
switch_event_t *event = NULL;
const char *intrastate = NULL;
@@ -1403,11 +1402,6 @@ SWITCH_STANDARD_DIALPLAN(lcr_dialplan_hunt)
}
routes.pool = pool;
- if (!(routes.profile = locate_profile(lcr_profile))) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unknown profile: %s\n", lcr_profile);
- goto end;
- }
-
intrastate = switch_channel_get_variable(channel, "intrastate");
intralata = switch_channel_get_variable(channel, "intralata");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "intrastate channel var is [%s]\n", intrastate);
@@ -1427,7 +1421,12 @@ SWITCH_STANDARD_DIALPLAN(lcr_dialplan_hunt)
caller_profile = switch_channel_get_caller_profile(channel);
}
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "LCR Lookup on %s using profile %s\n", caller_profile->destination_number, lcr_profile);
+ if (!(routes.profile = locate_profile(caller_profile->context))) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unknown profile: %s\n", caller_profile->context);
+ goto end;
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "LCR Lookup on %s using profile %s\n", caller_profile->destination_number, caller_profile->context);
routes.lookup_number = caller_profile->destination_number;
routes.cid = (char *) caller_profile->caller_id_number;
if (lcr_do_lookup(&routes) == SWITCH_STATUS_SUCCESS) {
@@ -1465,7 +1464,7 @@ SWITCH_STANDARD_DIALPLAN(lcr_dialplan_hunt)
switch_caller_extension_add_application(session, extension, app, argc);
}
} else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "LCR lookup failed for %s using profile %s\n", caller_profile->destination_number, lcr_profile);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "LCR lookup failed for %s using profile %s\n", caller_profile->destination_number, caller_profile->context);
}
end:
diff --git a/src/mod/applications/mod_spandsp/mod_spandsp_dsp.c b/src/mod/applications/mod_spandsp/mod_spandsp_dsp.c
index 005924194f..f576b7dd01 100644
--- a/src/mod/applications/mod_spandsp/mod_spandsp_dsp.c
+++ b/src/mod/applications/mod_spandsp/mod_spandsp_dsp.c
@@ -495,7 +495,7 @@ switch_status_t callprogress_detector_stop(switch_core_session_t *session)
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_media_bug_t *bug = switch_channel_get_private(channel, TONE_PRIVATE);
if (bug) {
- switch_core_media_bug_close(&bug);
+ switch_core_media_bug_remove(session, &bug);
switch_channel_set_private(channel, TONE_PRIVATE, NULL);
}
return SWITCH_STATUS_SUCCESS;
diff --git a/src/mod/applications/mod_valet_parking/mod_valet_parking.2010.vcxproj b/src/mod/applications/mod_valet_parking/mod_valet_parking.2010.vcxproj
index 5e006e13f9..29c0c4a742 100644
--- a/src/mod/applications/mod_valet_parking/mod_valet_parking.2010.vcxproj
+++ b/src/mod/applications/mod_valet_parking/mod_valet_parking.2010.vcxproj
@@ -63,10 +63,6 @@
<_ProjectFileVersion>10.0.30319.1
- $(Platform)\$(Configuration)\
- $(Platform)\$(Configuration)\
- $(Platform)\$(Configuration)\
- $(Platform)\$(Configuration)\
diff --git a/src/mod/asr_tts/mod_cepstral/WinReadme.txt b/src/mod/asr_tts/mod_cepstral/WinReadme.txt
new file mode 100644
index 0000000000..56b4e79a39
--- /dev/null
+++ b/src/mod/asr_tts/mod_cepstral/WinReadme.txt
@@ -0,0 +1,4 @@
+The Cepstral SDK for Windows should be placed in c:\dev\cepstral
+ex. C:\dev\cepstral\sdk\include
+This SDK can be obtained from http://cepstral.com/
+If you want a prebuilt version you may download one from http://files.freeswitch.org/windows/installer/
\ No newline at end of file
diff --git a/src/mod/asr_tts/mod_cepstral/mod_cepstral.2010.vcxproj b/src/mod/asr_tts/mod_cepstral/mod_cepstral.2010.vcxproj
index 2bc46efdca..b7e42eb850 100644
--- a/src/mod/asr_tts/mod_cepstral/mod_cepstral.2010.vcxproj
+++ b/src/mod/asr_tts/mod_cepstral/mod_cepstral.2010.vcxproj
@@ -66,13 +66,13 @@
- C:\Program Files\Cepstral\sdk\include;%(AdditionalIncludeDirectories)
+ C:\dev\cepstral\sdk\include;%(AdditionalIncludeDirectories)
swift.lib;%(AdditionalDependencies)
- C:\Program Files\Cepstral\sdk\lib\winnt;C:\Program Files\Cepstral\sdk\lib\windows;%(AdditionalLibraryDirectories)
+ C:\dev\cepstral\sdk\lib\lib-windows;%(AdditionalLibraryDirectories)
false
@@ -83,13 +83,13 @@
X64
- C:\Program Files\Cepstral\sdk\include;%(AdditionalIncludeDirectories)
+ C:\dev\cepstral\sdk\include;%(AdditionalIncludeDirectories)
swift.lib;%(AdditionalDependencies)
- C:\Program Files\Cepstral\sdk\lib\winnt;C:\Program Files\Cepstral\sdk\lib\windows;%(AdditionalLibraryDirectories)
+ C:\dev\cepstral\sdk\lib\lib-windows_x64;%(AdditionalLibraryDirectories)
false
@@ -98,13 +98,13 @@
- C:\Program Files\Cepstral\sdk\include;%(AdditionalIncludeDirectories)
+ C:\dev\cepstral\sdk\include;%(AdditionalIncludeDirectories)
swift.lib;%(AdditionalDependencies)
- C:\Program Files\Cepstral\sdk\lib\winnt;C:\Program Files\Cepstral\sdk\lib\windows;%(AdditionalLibraryDirectories)
+ C:\dev\cepstral\sdk\lib\lib-windows;%(AdditionalLibraryDirectories)
false
@@ -115,13 +115,13 @@
X64
- C:\Program Files\Cepstral\sdk\include;%(AdditionalIncludeDirectories)
+ C:\dev\cepstral\sdk\include;%(AdditionalIncludeDirectories)
swift.lib;%(AdditionalDependencies)
- C:\Program Files\Cepstral\sdk\lib\winnt;C:\Program Files\Cepstral\sdk\lib\windows;%(AdditionalLibraryDirectories)
+ C:\dev\cepstral\sdk\lib\lib-windows_x64;%(AdditionalLibraryDirectories)
false
@@ -132,9 +132,8 @@
-
+
{202d7a4e-760d-4d0e-afa1-d7459ced30ff}
- false
diff --git a/src/mod/codecs/mod_celt/mod_celt.vcxproj b/src/mod/codecs/mod_celt/mod_celt.vcxproj
index 01c55d4217..ee8a70ca3f 100644
--- a/src/mod/codecs/mod_celt/mod_celt.vcxproj
+++ b/src/mod/codecs/mod_celt/mod_celt.vcxproj
@@ -62,10 +62,6 @@
<_ProjectFileVersion>10.0.30319.1
- $(Platform)\$(Configuration)\
- $(Platform)\$(Configuration)\
- $(Platform)\$(Configuration)\
- $(Platform)\$(Configuration)\
diff --git a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c
index 6e6fe58af6..97d9f6de9e 100644
--- a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c
+++ b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c
@@ -40,7 +40,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sangoma_codec_shutdown);
SWITCH_MODULE_DEFINITION(mod_sangoma_codec, mod_sangoma_codec_load, mod_sangoma_codec_shutdown, NULL);
-#define IANA_LINEAR 10
#define SANGOMA_SESS_HASH_KEY_FORMAT "sngtc%lu"
/* it seemed we need higher PTIME than the calling parties, so we assume nobody will use higher ptime than 40 */
@@ -83,26 +82,26 @@ typedef struct vocallo_codec_s {
int autoinit; /* initialize on start loop or manually */
} vocallo_codec_t;
-#define ILBC_133_PAYLOAD 97
-#define ILBC_152_PAYLOAD 98
vocallo_codec_t g_codec_map[] =
{
/* auto-init codecs */
- { SNGTC_CODEC_PCMU, 0, "PCMU", "Sangoma PCMU", 40, 64000, 10000, 80, 160, 80, 8000, 8000, 1 },
- { SNGTC_CODEC_PCMA, 8, "PCMA", "Sangoma PCMA", 40, 64000, 10000, 80, 160, 80, 8000, 8000, 1 },
- { SNGTC_CODEC_L16_1, 10, "L16", "Sangoma L16", 40, 120000, 10000, 80, 160, 160, 8000, 8000, 0 },
- { SNGTC_CODEC_L16_2, 10, "L16", "Sangoma L16 2", 40, 320000, 10000, 80, 320, 320, 16000, 16000, 0 },
- { SNGTC_CODEC_G729AB, 18, "G729", "Sangoma G729", 40, 8000, 10000, 80, 160, 10, 8000, 8000, 1 },
- { SNGTC_CODEC_G726_32, 122, "G726-32", "Sangoma G.726 32k", 40, 32000, 10000, 80, 160, 40, 8000, 8000, 1 },
- { SNGTC_CODEC_G722, 9, "G722", "Sangoma G722", 20, 64000, 10000, 80, 160, 80, 8000, 8000, 1 },
+ { SNGTC_CODEC_PCMU, IANA_PCMU_A_8000_1, "PCMU", "Sangoma PCMU", 40, 64000, 10000, 80, 160, 80, 8000, 8000, 1 },
+ { SNGTC_CODEC_PCMA, IANA_PCMA_A_8000_1, "PCMA", "Sangoma PCMA", 40, 64000, 10000, 80, 160, 80, 8000, 8000, 1 },
+ { SNGTC_CODEC_L16_1, IANA_L16_A_8000_1, "L16", "Sangoma L16", 40, 120000, 10000, 80, 160, 160, 8000, 8000, 0 },
+ { SNGTC_CODEC_L16_2, IANA_L16_A_16000_1, "L16", "Sangoma L16 2", 40, 320000, 10000, 160, 320, 320, 16000, 16000, 0 },
+ { SNGTC_CODEC_G729AB, IANA_G729_AB_8000_1, "G729", "Sangoma G729", 40, 8000, 10000, 80, 160, 10, 8000, 8000, 1 },
+ { SNGTC_CODEC_G726_32, IANA_G726_32_8000_1, "G726-32", "Sangoma G.726 32k", 40, 32000, 10000, 80, 160, 40, 8000, 8000, 1 },
+ { SNGTC_CODEC_G722, IANA_G722_A_8000_1, "G722", "Sangoma G722", 20, 64000, 10000, 80, 160, 80, 8000, 8000, 1 },
/* manually initialized */
- { SNGTC_CODEC_GSM_FR, 3, "GSM", "Sangoma GSM", 20, 13200, 20000, 160, 320, 33, 8000, 8000, 0 },
- { SNGTC_CODEC_G723_1_63, 4, "G723", "Sangoma G723", 90, 6300, 30000, 240, 480, 24, 8000, 8000, 0 },
- { SNGTC_CODEC_AMR_1220, 96, "AMR", "Sangoma AMR", 20, 12200, 20000, 160, 320, 0, 8000, 8000, 0 },
- { SNGTC_CODEC_ILBC_133, ILBC_133_PAYLOAD, "iLBC", "Sangoma iLBC", -1, -1, -1, -1, -1, -1, -1, -1, 0 },
- { SNGTC_CODEC_ILBC_152, ILBC_152_PAYLOAD, "iLBC", "Sangoma iLBC", -1, -1, -1, -1, -1, -1, -1, -1, 0 },
- { -1, -1, NULL, NULL, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
+ { SNGTC_CODEC_GSM_FR, IANA_GSM_A_8000_1, "GSM", "Sangoma GSM", 20, 13200, 20000, 160, 320, 33, 8000, 8000, 0 },
+ { SNGTC_CODEC_G723_1_63, IANA_G723_A_8000_1, "G723", "Sangoma G723", 90, 6300, 30000, 240, 480, 24, 8000, 8000, 0 },
+ { SNGTC_CODEC_AMR_1220, IANA_AMR_WB_16000_1, "AMR", "Sangoma AMR", 20, 12200, 20000, 160, 320, 0, 8000, 8000, 0 },
+ { SNGTC_CODEC_SIREN7_24, IANA_SIREN7, "G7221", "Sangoma G722.1", 20, 24000, 20000, 320, 640, 60, 16000, 16000, 0 },
+ { SNGTC_CODEC_SIREN7_32, IANA_SIREN7, "G7221", "Sangoma G722.1", 20, 32000, 20000, 320, 640, 80, 16000, 16000, 0 },
+ { SNGTC_CODEC_ILBC_133, IANA_ILBC_133_8000_1, "iLBC", "Sangoma iLBC", 30, 13300, 30000, 240, 480, 50, 8000, 8000, 0 },
+ { SNGTC_CODEC_ILBC_152, IANA_ILBC_152_8000_1, "iLBC", "Sangoma iLBC", 20, 15200, 20000, 160, 320, 38, 8000, 8000, 0 },
+ { -1, -1, NULL, NULL, -1, -1, -1, -1, -1, -1, -1, -1, 0 },
};
/* RFC3389 RTP Payload for Comfort Noise */
@@ -181,11 +180,14 @@ static int codec_id_to_iana(int codec_id)
return -1;
}
-static vocallo_codec_t *get_codec_from_iana(int iana)
+static vocallo_codec_t *get_codec_from_iana(int iana, int bitrate)
{
int i;
for (i = 0; g_codec_map[i].codec_id != -1; i++) {
- if (iana == g_codec_map[i].iana) {
+ if (iana == g_codec_map[i].iana && !bitrate) {
+ return &g_codec_map[i];
+ }
+ if (iana == g_codec_map[i].iana && bitrate == g_codec_map[i].bps) {
return &g_codec_map[i];
}
}
@@ -319,7 +321,7 @@ static switch_status_t switch_sangoma_init(switch_codec_t *codec, switch_codec_f
sess->pool = codec->memory_pool;
sess->impl = codec->implementation;
- vcodec = get_codec_from_iana(codec->implementation->ianacode);
+ vcodec = get_codec_from_iana(codec->implementation->ianacode, codec->implementation->bits_per_second);
switch_mutex_lock(g_sessions_lock);
@@ -386,6 +388,12 @@ static switch_status_t switch_sangoma_init_ilbc(switch_codec_t *codec, switch_co
return switch_sangoma_init(codec, flags, codec_settings);
}
+static switch_status_t switch_sangoma_init_siren7(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
+{
+ int bit_rate = codec->implementation->bits_per_second;
+ codec->fmtp_out = switch_core_sprintf(codec->memory_pool, "bitrate=%d", bit_rate);
+ return switch_sangoma_init(codec, flags, codec_settings);
+}
static void flush_rtp(switch_rtp_t *rtp)
{
@@ -435,6 +443,7 @@ static switch_status_t switch_sangoma_encode(switch_codec_t *codec, switch_codec
switch_time_t func_start_time = 0, func_end_time = 0;
int i = 0;
int res = 0;
+ int linear_payload = codec->implementation->actual_samples_per_second == 8000 ? IANA_L16_A_8000_1 : IANA_L16_A_16000_1;
struct sangoma_transcoding_session *sess = codec->private_info;
if (sess->encoder.debug_timing) {
@@ -473,7 +482,7 @@ static switch_status_t switch_sangoma_encode(switch_codec_t *codec, switch_codec
linear_frame.source = __FUNCTION__;
linear_frame.data = decoded_byteswapped_data;
linear_frame.datalen = decoded_data_len;
- linear_frame.payload = IANA_LINEAR;
+ linear_frame.payload = linear_payload;
/* copy and byte-swap */
for (i = 0; i < decoded_data_len/2; i++) {
@@ -531,9 +540,9 @@ static switch_status_t switch_sangoma_encode(switch_codec_t *codec, switch_codec
if (sess->encoder.request.b.codec_id == SNGTC_CODEC_ILBC_152 || sess->encoder.request.b.codec_id == SNGTC_CODEC_ILBC_133) {
/* since we moved to SOAP based communications, the mapping between vocallo IANA and our IANA does not work,
* some codecs checks cannot be completely done, like iLBC */
- if (encoded_frame.payload != ILBC_152_PAYLOAD && encoded_frame.payload != ILBC_133_PAYLOAD) {
+ if (encoded_frame.payload != IANA_ILBC_152_8000_1 && encoded_frame.payload != IANA_ILBC_133_8000_1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read unexpected payload %d in Sangoma encoder RTP session, expecting either %d or %d\n",
- encoded_frame.payload, ILBC_152_PAYLOAD, ILBC_133_PAYLOAD);
+ encoded_frame.payload, IANA_ILBC_152_8000_1, IANA_ILBC_133_8000_1);
break;
}
} else {
@@ -633,6 +642,7 @@ static switch_status_t switch_sangoma_decode(switch_codec_t *codec, /* codec ses
uint16_t *rtp_data_linear;
int res = 0;
int i = 0;
+ int linear_payload = codec->implementation->actual_samples_per_second == 8000 ? IANA_L16_A_8000_1 : IANA_L16_A_16000_1;
struct sangoma_transcoding_session *sess = codec->private_info;
if (sess->decoder.debug_timing) {
@@ -722,9 +732,9 @@ static switch_status_t switch_sangoma_decode(switch_codec_t *codec, /* codec ses
continue;
}
- if (linear_frame.payload != IANA_LINEAR) {
+ if (linear_frame.payload != linear_payload) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read unexpected payload %d in Sangoma decoder RTP session, expecting %d\n",
- linear_frame.payload, IANA_LINEAR);
+ linear_frame.payload, linear_payload);
break;
}
@@ -1156,7 +1166,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load)
switch_api_interface_t *api_interface = NULL;
int i = 0, c = 0;
int ilbc_done = 0;
+ int siren_done = 0;
vocallo_codec_t *ilbc_codec = NULL;
+ vocallo_codec_t *siren_codec = NULL;
int detected = 0, activated = 0;
/* make sure we have valid configuration */
@@ -1214,17 +1226,18 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load)
continue;
}
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Registering implementations for codec %s\n", g_codec_map[c].iana_name);
-
- /* let know the library which iana to use */
- sngtc_set_iana_code_based_on_codec_id(g_codec_map[c].codec_id, g_codec_map[c].iana);
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Mapped codec %d to IANA %d\n", g_codec_map[c].codec_id, g_codec_map[c].iana);
-
/* special check for iLBC to add a single codec interface for both ILBC bitrate versions */
if ((g_codec_map[c].codec_id == SNGTC_CODEC_ILBC_152 || g_codec_map[c].codec_id == SNGTC_CODEC_ILBC_133) && ilbc_done) {
continue;
}
+ /* special check for siren to add a single codec interface for all siren bitrate versions */
+ if ((g_codec_map[c].codec_id == SNGTC_CODEC_SIREN7_24 || g_codec_map[c].codec_id == SNGTC_CODEC_SIREN7_32) && siren_done) {
+ continue;
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Registering implementations for codec %s\n", g_codec_map[c].iana_name);
+
/* SWITCH_ADD_CODEC allocates a codec interface structure from the pool the core gave us and adds it to the internal interface
* list the core keeps, gets a codec id and set the given codec name to it.
* At this point there is an empty shell codec interface registered, but not yet implementations */
@@ -1322,7 +1335,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load)
50, /* number of bytes per frame compressed */
1, /* number of channels represented */
1, /* number of frames per network packet (I dont think this is used at all) */
- switch_sangoma_init, /* function to initialize a codec session using this implementation */
+ switch_sangoma_init_ilbc, /* function to initialize a codec session using this implementation */
switch_sangoma_encode, /* function to encode slinear data into encoded data */
switch_sangoma_decode, /* function to decode encoded data into slinear data */
switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */
@@ -1353,6 +1366,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load)
}
break;
+
case SNGTC_CODEC_AMR_1220:
switch_core_codec_add_implementation(pool, codec_interface, /* the codec interface we allocated and we want to register with the core */
SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
@@ -1374,6 +1388,51 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load)
switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */
break;
+ case SNGTC_CODEC_SIREN7_24:
+ case SNGTC_CODEC_SIREN7_32:
+
+ siren_codec = get_codec_from_id(SNGTC_CODEC_SIREN7_24);
+ switch_core_codec_add_implementation(pool, codec_interface, /* the codec interface we allocated and we want to register with the core */
+ SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
+ siren_codec->iana, /* the IANA code number, ie http://www.iana.org/assignments/rtp-parameters */
+ siren_codec->iana_name, /* the IANA code name */
+ "bitrate=24000", /* default fmtp to send (can be overridden by the init function), fmtp is used in SDP for format specific parameters */
+ siren_codec->sampling_rate, /* samples transferred per second */
+ siren_codec->actual_sampling_rate, /* actual samples transferred per second */
+ siren_codec->bps, /* bits transferred per second */
+ siren_codec->mpf, /* microseconds per frame */
+ siren_codec->spf, /* samples per frame */
+ siren_codec->bpfd, /* number of bytes per frame decompressed */
+ siren_codec->bpfc, /* number of bytes per frame compressed */
+ 1, /* number of channels represented */
+ siren_codec->spf, /* number of frames per network packet (I dont think this is used at all) */
+ switch_sangoma_init_siren7, /* function to initialize a codec session using this implementation */
+ switch_sangoma_encode, /* function to encode slinear data into encoded data */
+ switch_sangoma_decode, /* function to decode encoded data into slinear data */
+ switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */
+
+ siren_codec = get_codec_from_id(SNGTC_CODEC_SIREN7_32);
+ switch_core_codec_add_implementation(pool, codec_interface, /* the codec interface we allocated and we want to register with the core */
+ SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
+ siren_codec->iana, /* the IANA code number, ie http://www.iana.org/assignments/rtp-parameters */
+ siren_codec->iana_name, /* the IANA code name */
+ "bitrate=32000", /* default fmtp to send (can be overridden by the init function), fmtp is used in SDP for format specific parameters */
+ siren_codec->sampling_rate, /* samples transferred per second */
+ siren_codec->actual_sampling_rate, /* actual samples transferred per second */
+ siren_codec->bps, /* bits transferred per second */
+ siren_codec->mpf, /* microseconds per frame */
+ siren_codec->spf, /* samples per frame */
+ siren_codec->bpfd, /* number of bytes per frame decompressed */
+ siren_codec->bpfc, /* number of bytes per frame compressed */
+ 1, /* number of channels represented */
+ siren_codec->spf, /* number of frames per network packet (I dont think this is used at all) */
+ switch_sangoma_init_siren7, /* function to initialize a codec session using this implementation */
+ switch_sangoma_encode, /* function to encode slinear data into encoded data */
+ switch_sangoma_decode, /* function to decode encoded data into slinear data */
+ switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */
+ siren_done = 1;
+ break;
+
default:
break;
}
diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c
index 7558e1b1b8..75329a0848 100644
--- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c
+++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c
@@ -514,13 +514,19 @@ static switch_status_t chat_send(const char *proto, const char *from, const char
from = hint;
} else {
char *p;
- ffrom = switch_mprintf("%s+%s", proto, from);
- from = ffrom;
+
+ if (!(profile->user_flags & LDL_FLAG_COMPONENT)) {
+ from = ffrom = strdup(profile->login);
+ } else {
+ from = ffrom = switch_mprintf("%s+%s", proto, from);
+ }
+
if ((p = strchr(from, '/'))) {
*p = '\0';
}
}
ldl_handle_send_msg(profile->handle, (char *) from, (char *) to, NULL, switch_str_nil(body));
+ switch_safe_free(ffrom);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Profile %s\n", f_host ? f_host : "NULL");
return SWITCH_STATUS_FALSE;
@@ -602,7 +608,7 @@ static void ipchanged_event_handler(switch_event_t *event)
for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, NULL, NULL, &val);
profile = (mdl_profile_t *) val;
- if (old_ip4 && !strcmp(profile->extip, old_ip4)) {
+ if (old_ip4 && profile->extip && !strcmp(profile->extip, old_ip4)) {
tmp = profile->extip;
profile->extip = strdup(new_ip4);
switch_safe_free(tmp);
diff --git a/src/mod/endpoints/mod_gsmopen/gsmopen.h b/src/mod/endpoints/mod_gsmopen/gsmopen.h
index fd94bccc2a..05ef1641bf 100644
--- a/src/mod/endpoints/mod_gsmopen/gsmopen.h
+++ b/src/mod/endpoints/mod_gsmopen/gsmopen.h
@@ -158,7 +158,7 @@ typedef enum {
#define WARNINGA(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "rev "GSMOPEN_SVN_VERSION "[%p|%-7lx][WARNINGA %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
#define NOTICA(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "rev "GSMOPEN_SVN_VERSION "[%p|%-7lx][NOTICA %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ );
-#define GSMOPEN_P_LOG NULL, (unsigned long)55, __LINE__, tech_pvt ? tech_pvt->name ? tech_pvt->name : "none" : "none", -1, tech_pvt ? tech_pvt->interface_state : -1, tech_pvt ? tech_pvt->phone_callflow : -1
+#define GSMOPEN_P_LOG (void *)NULL, (unsigned long)55, __LINE__, tech_pvt ? tech_pvt->name ? tech_pvt->name : "none" : "none", -1, tech_pvt ? tech_pvt->interface_state : -1, tech_pvt ? tech_pvt->phone_callflow : -1
/*********************************/
#define GSMOPEN_CAUSE_NORMAL 1
diff --git a/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp b/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp
index e4bb6b9200..76d32ac3f0 100644
--- a/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp
+++ b/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp
@@ -3294,12 +3294,18 @@ int alsa_write(private_t * tech_pvt, short *data, int datalen)
time_t now_timestamp;
/* size_t frames = 0; */
snd_pcm_state_t state;
- snd_pcm_sframes_t delayp1;
- snd_pcm_sframes_t delayp2;
+ snd_pcm_sframes_t delayp1=0;
+ snd_pcm_sframes_t delayp2=0;
if(tech_pvt->no_sound==1){
return res;
}
+
+
+ memset(sizbuf, 255, sizeof(sizbuf));
+ memset(sizbuf2, 255, sizeof(sizbuf));
+ memset(silencebuf, 255, sizeof(sizbuf));
+
//ERRORA("data=%p, datalen=%d\n", GSMOPEN_P_LOG, (void *)data, datalen);
/* We have to digest the frame in 160-byte portions */
if (datalen > sizeof(sizbuf) - sizpos) {
@@ -3307,8 +3313,11 @@ int alsa_write(private_t * tech_pvt, short *data, int datalen)
res = -1;
} else {
memcpy(sizbuf + sizpos, data, datalen);
+ memset(data, 255, datalen);
len += datalen;
pos = 0;
+
+
#ifdef ALSA_MONITOR
alsa_monitor_write(sizbuf, len);
#endif
@@ -3456,6 +3465,7 @@ int alsa_write(private_t * tech_pvt, short *data, int datalen)
if (res == -ESTRPIPE) {
ERRORA("You've got some big problems\n", GSMOPEN_P_LOG);
} else if (res == -EAGAIN) {
+ DEBUGA_GSMOPEN("Momentarily busy\n", GSMOPEN_P_LOG);
res = 0;
} else if (res < 0) {
ERRORA("Error %d on audio write: \"%s\"\n", GSMOPEN_P_LOG, res, snd_strerror(res));
@@ -3572,9 +3582,11 @@ int alsa_read(private_t * tech_pvt, short *data, int datalen)
return r;
} else if (r == -EAGAIN) {
- DEBUGA_GSMOPEN("ALSA read -EAGAIN, the soundcard is not ready to be read by gsmopen\n", GSMOPEN_P_LOG);
+ int count=0;
while (r == -EAGAIN) {
- gsmopen_sleep(1000);
+ gsmopen_sleep(10000);
+ DEBUGA_GSMOPEN("%d ALSA read -EAGAIN, the soundcard is not ready to be read by gsmopen\n", GSMOPEN_P_LOG, count);
+ count++;
if (tech_pvt->alsa_capture_is_mono) {
r = snd_pcm_readi(tech_pvt->alsac, buf + readpos, left);
diff --git a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp
index cb440d3bcb..7e20b7c25e 100644
--- a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp
+++ b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp
@@ -1904,14 +1904,25 @@ static switch_status_t load_config(int reload_type)
if (globals.GSMOPEN_INTERFACES[interface_id].controldevprotocol != PROTOCOL_NO_SERIAL) {
res = gsmopen_serial_config(&globals.GSMOPEN_INTERFACES[interface_id]);
if (res) {
- ERRORA("gsmopen_serial_config failed\n", GSMOPEN_P_LOG);
- ERRORA("STARTING interface_id=%d FAILED\n", GSMOPEN_P_LOG, interface_id);
- //return SWITCH_STATUS_FALSE;
- globals.GSMOPEN_INTERFACES[interface_id].running=0;
- alarm_event(&globals.GSMOPEN_INTERFACES[interface_id], ALARM_FAILED_INTERFACE, "gsmopen_serial_config failed");
- globals.GSMOPEN_INTERFACES[interface_id].active=0;
- globals.GSMOPEN_INTERFACES[interface_id].name[0]='\0';
- continue;
+ int count = 0;
+ ERRORA("gsmopen_serial_config failed, let's try again\n", GSMOPEN_P_LOG);
+ while(res && count < 5){
+ switch_sleep(100000); //0.1 seconds
+ res = gsmopen_serial_config(&globals.GSMOPEN_INTERFACES[interface_id]);
+ count++;
+ if (res) {
+ ERRORA("%d: gsmopen_serial_config failed, let's try again\n", GSMOPEN_P_LOG, count);
+ }
+ }
+ if (res) {
+ ERRORA("STARTING interface_id=%d FAILED\n", GSMOPEN_P_LOG, interface_id);
+ //return SWITCH_STATUS_FALSE;
+ globals.GSMOPEN_INTERFACES[interface_id].running=0;
+ alarm_event(&globals.GSMOPEN_INTERFACES[interface_id], ALARM_FAILED_INTERFACE, "gsmopen_serial_config failed");
+ globals.GSMOPEN_INTERFACES[interface_id].active=0;
+ globals.GSMOPEN_INTERFACES[interface_id].name[0]='\0';
+ continue;
+ }
}
}
diff --git a/src/mod/endpoints/mod_h323/changes.txt b/src/mod/endpoints/mod_h323/changes.txt
index 19aca46dc8..4f75aef8b4 100644
--- a/src/mod/endpoints/mod_h323/changes.txt
+++ b/src/mod/endpoints/mod_h323/changes.txt
@@ -1,3 +1,6 @@
+Adds an extra switch_rtp_destroy or switch_rtp_release_port when a session ends
+ - to make sure the port is returned to FS. thx to Peter Olsson.
+fix issues with Progress message type if pre_answer enabled
fix crashes on FSH323Connection calls in on_hangup routine in different threads.
move PTrace level set to FSH323EndPoint::Initialise
partially apply patch from from Peter Olsson, Remove UnLock() when TryLock() failed and DEBUG_RTP_PACKETS directive.
diff --git a/src/mod/endpoints/mod_h323/mod_h323.cpp b/src/mod/endpoints/mod_h323/mod_h323.cpp
index 142506dd92..74fb6ae11a 100644
--- a/src/mod/endpoints/mod_h323/mod_h323.cpp
+++ b/src/mod/endpoints/mod_h323/mod_h323.cpp
@@ -343,7 +343,7 @@ PString GetH245CodecName(const H323Capability* cap)
}
FSProcess::FSProcess()
- : PLibraryProcess("Test", "mod_h323", 1, 0, AlphaCode, 1)
+ : PLibraryProcess("FreeSWITCH", "mod_h323", 1, 0, AlphaCode, 1)
, m_h323endpoint(NULL){
}
@@ -742,6 +742,14 @@ FSH323Connection::~FSH323Connection()
switch_core_session_unlock_codec_write(m_fsSession);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"------------->switch_core_session_unlock_codec_write [%p]\n",m_fsSession);
}
+
+ if (tech_pvt->rtp_session) {
+ switch_rtp_destroy(&tech_pvt->rtp_session);
+ tech_pvt->rtp_session = NULL;
+ } else if (m_RTPlocalPort) {
+ switch_rtp_release_port((const char *)m_RTPlocalIP.AsString(), m_RTPlocalPort);
+ }
+
tech_pvt->me = NULL;
// switch_mutex_unlock(tech_pvt->h323_mutex);
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"------------->h323_mutex_unlock\n");
@@ -1148,7 +1156,7 @@ void FSH323Connection::AnsweringCall(AnswerCallResponse response)
if (!mediaWaitForConnect) {
// create a new facility PDU if doing AnswerDeferredWithMedia
H323SignalPDU want245PDU;
- //H225_Progress_UUIE & prog = want245PDU.BuildProgress(*this);
+ want245PDU.BuildProgress(*this);
PBoolean sendPDU = TRUE;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,"mediaWaitForConnect = FALSE\n");
/* if (SendFastStartAcknowledge(prog.m_fastStart)){
diff --git a/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml b/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml
index 45268f304b..79c00516b9 100644
--- a/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml
+++ b/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml
@@ -95,16 +95,6 @@ should be opened for the channel. Limited to 25ms min, 500ms max.
-->
-
-
-
-
-
-
-
-
-
-
diff --git a/src/mod/endpoints/mod_khomp/Makefile b/src/mod/endpoints/mod_khomp/Makefile
index 94923c7cda..db1a6fe4e4 100644
--- a/src/mod/endpoints/mod_khomp/Makefile
+++ b/src/mod/endpoints/mod_khomp/Makefile
@@ -1,6 +1,9 @@
MODNAME := mod_khomp
VERBOSE := 1
+#FreeSWITCH source PATH is needed:
+# Set FREESWITCH_PATH
+
ifeq ($(strip $(FREESWITCH_PATH)),)
BASE := ../../../../
else
@@ -11,12 +14,12 @@ curr_dir := $(shell pwd)
versions := -DFS_VERSION_MAJOR=$(shell bash $(curr_dir)/tools/getversion.sh "SWITCH_VERSION_MAJOR" $(BASE)) -DFS_VERSION_MINOR=$(shell bash $(curr_dir)/tools/getversion.sh "SWITCH_VERSION_MINOR" $(BASE)) -DFS_VERSION_MICRO=$(shell bash $(curr_dir)/tools/getversion.sh "SWITCH_VERSION_MICRO" $(BASE))
-LOCAL_CFLAGS = -I./ -I./include -I./commons -I./support -D_REENTRANT -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DK3L_HOSTSYSTEM -DCOMMONS_LIBRARY_USING_FREESWITCH -g -ggdb #-DDEBUG_FLAGS
+LOCAL_CFLAGS = -I./ -I./include -I./commons -I./commons/base -I./support -D_REENTRANT -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DK3L_HOSTSYSTEM -DCOMMONS_LIBRARY_USING_FREESWITCH -g -ggdb #-DDEBUG_FLAGS
LOCAL_CFLAGS += $(versions)
LOCAL_LDFLAGS = -lk3l
-LOCAL_OBJS = ./commons/k3lapi.o ./commons/k3lutil.o ./commons/config_options.o ./commons/format.o ./commons/strings.o ./commons/ringbuffer.o ./commons/verbose.o ./commons/saved_condition.o ./commons/regex.o ./commons/timer.o ./commons/configurator/configfile.o ./commons/configurator/option.o ./commons/configurator/section.o ./commons/configurator/restriction.o
+LOCAL_OBJS = ./commons/base/k3lapi.o ./commons/base/k3lutil.o ./commons/base/config_options.o ./commons/base/format.o ./commons/base/strings.o ./commons/base/ringbuffer.o ./commons/base/verbose.o ./commons/base/saved_condition.o ./commons/base/regex.o ./commons/base/timer.o ./commons/base/configurator/configfile.o ./commons/base/configurator/option.o ./commons/base/configurator/section.o ./commons/base/configurator/restriction.o ./commons/base/verbose_traits.o
LOCAL_OBJS += ./support/klog-config.o ./support/klog-options.o ./support/config_defaults.o
LOCAL_OBJS += ./src/globals.o ./src/opt.o ./src/frame.o ./src/utils.o ./src/lock.o ./src/spec.o ./src/applications.o ./src/khomp_pvt_fxo.o ./src/khomp_pvt_gsm.o ./src/khomp_pvt_kxe1.o ./src/khomp_pvt_passive.o ./src/khomp_pvt.o ./src/logger.o ./src/cli.o
@@ -27,7 +30,20 @@ conf_file_install = $(sysconfdir)/autoload_configs
include $(BASE)/build/modmake.rules
+local_depend:
+ @if test ! -f $(curr_dir)/commons/base/verbose_traits.hpp || test ! -f $(curr_dir)/commons/base/verbose_traits.cpp ; then \
+ echo "Generating verbose_traits" ;\
+ bash $(curr_dir)/commons/tools/generate-verbose-headers.sh commons/base/ include/k3l.h ;\
+ fi;
+
depend_install:
+ @if test "w`kserver --version 2>/dev/null | grep 2.1`" == "w" ; then \
+ echo "###############################################################################" ;\
+ echo "Install k3l from KHOMP." ;\
+ echo "Run: $(curr_dir)/tools/getk3l.sh" ;\
+ echo "###############################################################################" ;\
+ exit 1;\
+ fi;
@echo "Copy $(conf_file_name)"
@if test -d $(conf_file_install) ; then \
if test -f $(conf_file_dir)/$(conf_file_name) ; then \
diff --git a/src/mod/endpoints/mod_khomp/commons/atomic.hpp b/src/mod/endpoints/mod_khomp/commons/base/atomic.hpp
similarity index 90%
rename from src/mod/endpoints/mod_khomp/commons/atomic.hpp
rename to src/mod/endpoints/mod_khomp/commons/base/atomic.hpp
index daa598c9b4..02278b390c 100644
--- a/src/mod/endpoints/mod_khomp/commons/atomic.hpp
+++ b/src/mod/endpoints/mod_khomp/commons/base/atomic.hpp
@@ -64,17 +64,31 @@ namespace Atomic
PunnedType pval; pval.valtype = VAL; \
unsigned long long vexp = *(pexp.podtype); \
unsigned long long vval = *(pval.podtype); \
- unsigned long long res = (unsigned long long)exp; \
+ unsigned long vval32 = (unsigned long)vval; \
unsigned char chg = 0; \
- asm volatile("lock; cmpxchg8b %2; sete %1;" \
+ asm volatile( \
+ "xchgl %%ebx, %4;" \
+ "lock; cmpxchg8b %2; sete %1;" \
+ "movl %4, %%ebx; " \
: "+A" (vexp), /* 0 (result) */ \
- "=q" (chg) /* 1 */ \
+ "=c" (chg) /* 1 */ \
: "m" (*(unsigned char**)(PTR)), /* 2 */ \
- "b" ((unsigned long)(vval)), \
- "c" ((unsigned long)(vval >> 32))); \
+ "c" ((unsigned long)(vval >> 32)), \
+ "m" (vval32)); \
*(pexp.podtype) = vexp; \
return (chg != 0 ? true : false);
+// "movl %%ecx, %4;"
+//
+// "m" (*((unsigned long*)(*(pval.podtype)))),
+// "m" ((unsigned long)(vval >> 32))
+//
+// "m" (*((unsigned long*)(&vval))),
+// "m" ((unsigned long)(vval >> 32))
+//
+// unsigned long long vval = *(pval.podtype);
+// unsigned long long res = (unsigned long long)exp;
+//
// Types used for making CMPXCHG instructions independent from base type.
template < typename ValType, typename PodType >
diff --git a/src/mod/endpoints/mod_khomp/commons/config_commons.hpp b/src/mod/endpoints/mod_khomp/commons/base/config_commons.hpp
similarity index 92%
rename from src/mod/endpoints/mod_khomp/commons/config_commons.hpp
rename to src/mod/endpoints/mod_khomp/commons/base/config_commons.hpp
index de8f327df4..dad16f4e92 100644
--- a/src/mod/endpoints/mod_khomp/commons/config_commons.hpp
+++ b/src/mod/endpoints/mod_khomp/commons/base/config_commons.hpp
@@ -63,7 +63,12 @@
#error Unknown implementation selected. Please define COMMONS_LIBRARY_USING_* correctly.
#endif
-#define COMMONS_INCLUDE(file)
+#define COMMONS_INCLUDE(file)
+
+#define COMMONS_VERSION_MAJOR 1
+#define COMMONS_VERSION_MINOR 1
+
+#define COMMONS_AT_LEAST(x,y) \
+ (COMMONS_VERSION_MAJOR > x || (COMMONS_VERSION_MAJOR == x && COMMONS_VERSION_MINOR >= y))
#endif /* _CONFIG_COMMONS_HPP_ */
-
diff --git a/src/mod/endpoints/mod_khomp/commons/base/config_options.cpp b/src/mod/endpoints/mod_khomp/commons/base/config_options.cpp
new file mode 100644
index 0000000000..7412b4b1a0
--- /dev/null
+++ b/src/mod/endpoints/mod_khomp/commons/base/config_options.cpp
@@ -0,0 +1,302 @@
+/*
+ KHOMP generic endpoint/channel library.
+ Copyright (C) 2007-2009 Khomp Ind. & Com.
+
+ 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.
+
+ Alternatively, the contents of this file may be used under the terms of the
+ "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
+ case the provisions of "LGPL License" are applicable instead of those above.
+
+ If you wish to allow use of your version of this file only under the terms of
+ the LGPL License and not to allow others to use your version of this file under
+ the MPL, indicate your decision by deleting the provisions above and replace them
+ with the notice and other provisions required by the LGPL License. If you do not
+ delete the provisions above, a recipient may use your version of this file under
+ either the MPL or the LGPL License.
+
+ The LGPL header follows below:
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#include
+
+void Config::Restriction::checkRange(const std::string & name, const SIntType value, const Range < SIntType > & range)
+{
+ if (value < range.minimum)
+ throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (too low)") % value % name));
+
+ if (value > range.maximum)
+ throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (too high)") % value % name));
+
+ if (((value - range.minimum) % range.step) != 0)
+ throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (outside allowed step)") % value % name));
+}
+
+void Config::Restriction::checkRange(const std::string & name, const UIntType value, const Range < UIntType > & range)
+{
+ if (value < range.minimum)
+ throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (too low)") % value % name));
+
+ if (value > range.maximum)
+ throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (too high)") % value % name));
+
+ if (((value - range.minimum) % range.step) != 0)
+ throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (outside allowed step)") % value % name));
+}
+
+void Config::Restriction::checkStringSet(const std::string & name, const StringType & value, const StringSet & allowed)
+{
+ if (allowed.empty())
+ return;
+
+ if (allowed.find(value) != allowed.end())
+ return;
+
+ std::string strlist;
+
+ for (StringSet::const_iterator i = allowed.begin(); i != allowed.end(); i++)
+ {
+ strlist += " '";
+ strlist += (*i);
+ strlist += "'";
+ }
+
+ throw Failure(STG(FMT("value '%s' not allowed for option '%s' (allowed values:%s)")
+ % value % name % strlist));
+}
+
+Config::Option::Option(std::string name, Config::Option::StringMemberType value, const StringType defvalue, StringSet & allowed, bool listme)
+: _myname(name), _option(InnerStringType(name, value, defvalue, allowed)), _listme(listme), _values(NULL)
+{};
+
+Config::Option::Option(std::string name, Config::Option::StringMemberType value, const StringType defvalue, bool listme)
+: _myname(name), _option(InnerStringType(name, value, defvalue)), _listme(listme), _values(NULL)
+{};
+
+Config::Option::Option(std::string name, Config::Option::BooleanMemberType value, const BooleanType defvalue, bool listme)
+: _myname(name), _option(InnerBooleanType(name, value, defvalue)), _listme(listme), _values(NULL)
+{};
+
+Config::Option::Option(std::string name, Config::Option::SIntMemberType value, const SIntType defvalue,
+ SIntType min, SIntType max, SIntType step, bool listme)
+: _myname(name), _option(InnerSIntType(name, value, defvalue, min, max, step)), _listme(listme), _values(NULL)
+{};
+
+Config::Option::Option(std::string name, Config::Option::UIntMemberType value, const UIntType defvalue,
+ UIntType min, UIntType max, UIntType step, bool listme)
+: _myname(name), _option(InnerUIntType(name, value, defvalue, min, max, step)), _listme(listme), _values(NULL)
+{};
+
+Config::Option::Option(const Config::Option & o)
+: _myname(o._myname), _option(o._option), _listme(o._listme), _values(o._values)
+{};
+
+Config::Option::Option(std::string name, Config::Option::FunctionMemberType value, const StringType defvalue, StringSet & allowed, bool listme)
+: _myname(name), _option(InnerFunctionType(name, value, defvalue, allowed)), _listme(listme), _values(NULL)
+{};
+
+Config::Option::Option(std::string name, Config::Option::FunctionMemberType value, const StringType defvalue, bool listme)
+: _myname(name), _option(InnerFunctionType(name, value, defvalue)), _listme(listme), _values(NULL)
+{};
+
+Config::Option::~Option(void)
+{
+ if (_values)
+ {
+ for (unsigned int i = 0; _values[i] != NULL; i++)
+ delete _values[i];
+
+ delete[] _values;
+ _values = NULL;
+ }
+};
+
+const char ** Config::Option::values(void)
+{
+ if (_values != NULL)
+ return _values;
+
+ /**/ if (_option.check())
+ {
+ _values = new const char*[3];
+
+ _values[0] = strdup("yes");
+ _values[1] = strdup("no");
+ _values[2] = NULL;
+
+ }
+ else if (_option.check())
+ {
+ const InnerSIntType & tmp = _option.get();
+
+ unsigned int count = ((tmp._range.maximum - tmp._range.minimum) / tmp._range.step) + 1;
+ unsigned int index = 0;
+
+ _values = new const char*[count + 1];
+
+ for (SIntType i = tmp._range.minimum; i <= tmp._range.maximum; i += tmp._range.step, ++index)
+ _values[index] = strdup(STG(FMT("%d") % i).c_str());
+
+ _values[index] = NULL;
+ }
+ else if (_option.check())
+ {
+ const InnerUIntType & tmp = _option.get();
+
+ unsigned int count = ((tmp._range.maximum - tmp._range.minimum) / tmp._range.step) + 1;
+ unsigned int index = 0;
+
+ _values = new const char*[count + 1];
+
+ for (UIntType i = tmp._range.minimum; i <= tmp._range.maximum; i += tmp._range.step, ++index)
+ _values[index] = strdup(STG(FMT("%d") % i).c_str());
+
+ _values[index] = NULL;
+ }
+ else if (_option.check())
+ {
+ const InnerStringType & tmp = _option.get();
+
+ _values = new const char*[ tmp._allowed.size() + 1 ];
+
+ unsigned int index = 0;
+
+ for (StringSet::iterator i = tmp._allowed.begin(); i != tmp._allowed.end(); ++i, ++index)
+ _values[index] = strdup((*i).c_str());
+
+ _values[index] = NULL;
+ }
+ else if (_option.check())
+ {
+ const InnerFunctionType & tmp = _option.get();
+
+ _values = new const char*[ tmp._allowed.size() + 1 ];
+
+ unsigned int index = 0;
+
+ for (StringSet::iterator i = tmp._allowed.begin(); i != tmp._allowed.end(); ++i, ++index)
+ _values[index] = strdup((*i).c_str());
+
+ _values[index] = NULL;
+ }
+ else
+ {
+ throw Failure(STG(FMT("values() not implemented for type used in option '%s'") % _myname));
+ }
+
+ return _values;
+};
+
+/*********************************/
+
+Config::Options::Options(void)
+: _values(NULL)
+{};
+
+Config::Options::~Options()
+{
+ if (_values)
+ {
+ for (unsigned int i = 0; _values[i] != NULL; i++)
+ free((void*)(_values[i]));
+
+ delete[] _values;
+ _values = NULL;
+ }
+};
+
+bool Config::Options::add(Config::Option option)
+{
+ std::pair ret = _map.insert(OptionPair(option.name(), option));
+
+ return ret.second;
+}
+
+bool Config::Options::synonym(std::string equiv_opt, std::string main_opt)
+{
+ std::pair ret = _syn_map.insert(SynOptionPair(equiv_opt, main_opt));
+
+ return ret.second;
+}
+
+Config::StringSet Config::Options::options(void)
+{
+ StringSet res;
+
+ for (OptionMap::iterator i = _map.begin(); i != _map.end(); i++)
+ res.insert(i->first);
+
+ return res;
+}
+
+const char ** Config::Options::values(const char * name)
+{
+ OptionMap::iterator iter = find_option(name);
+
+ if (iter == _map.end())
+ throw Failure(STG(FMT("unknown option '%s'") % name));
+
+ return iter->second.values();
+}
+
+const char ** Config::Options::values(void)
+{
+ if (_values != NULL)
+ return _values;
+
+ unsigned int count = 0;
+
+ for (OptionMap::iterator i = _map.begin(); i != _map.end(); ++i)
+ if (i->second.listme())
+ ++count;
+
+ _values = new const char*[ count + 1 ];
+
+ unsigned int index = 0;
+
+ for (OptionMap::iterator i = _map.begin(); i != _map.end(); ++i)
+ {
+ if (i->second.listme())
+ {
+ _values[index] = strdup(i->first.c_str());
+ ++index;
+ }
+ }
+
+ _values[index] = NULL;
+
+ return _values;
+}
+
+Config::Options::OptionMap::iterator Config::Options::find_option(std::string name)
+{
+ SynOptionMap::iterator syn_iter = _syn_map.find(name);
+
+ if (syn_iter != _syn_map.end())
+ name = syn_iter->second;
+
+ OptionMap::iterator iter = _map.find(name);
+
+ return iter;
+}
diff --git a/src/mod/endpoints/mod_khomp/commons/base/config_options.hpp b/src/mod/endpoints/mod_khomp/commons/base/config_options.hpp
new file mode 100644
index 0000000000..59e381f893
--- /dev/null
+++ b/src/mod/endpoints/mod_khomp/commons/base/config_options.hpp
@@ -0,0 +1,772 @@
+/*
+ KHOMP generic endpoint/channel library.
+ Copyright (C) 2007-2009 Khomp Ind. & Com.
+
+ 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.
+
+ Alternatively, the contents of this file may be used under the terms of the
+ "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
+ case the provisions of "LGPL License" are applicable instead of those above.
+
+ If you wish to allow use of your version of this file only under the terms of
+ the LGPL License and not to allow others to use your version of this file under
+ the MPL, indicate your decision by deleting the provisions above and replace them
+ with the notice and other provisions required by the LGPL License. If you do not
+ delete the provisions above, a recipient may use your version of this file under
+ either the MPL or the LGPL License.
+
+ The LGPL header follows below:
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#ifndef _CONFIG_OPTIONS_HPP_
+#define _CONFIG_OPTIONS_HPP_
+
+#include
+#include