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.2008.express.sln b/Freeswitch.2008.express.sln
index 672406bda2..ad3cafe5cd 100644
--- a/Freeswitch.2008.express.sln
+++ b/Freeswitch.2008.express.sln
@@ -1,6 +1,6 @@

Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual Studio 2008
+# Visual C++ Express 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSwitchConsole", "w32\Console\FreeSwitchConsole.2008.vcproj", "{1AF3A893-F7BE-43DD-B697-8AB2397C0D67}"
ProjectSection(ProjectDependencies) = postProject
{202D7A4E-760D-4D0E-AFA1-D7459CED30FF} = {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}
@@ -11,6 +11,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSwitchCoreLib", "w32\Li
ProjectSection(ProjectDependencies) = postProject
{8D04B550-D240-4A44-8A18-35DA3F7038D9} = {8D04B550-D240-4A44-8A18-35DA3F7038D9}
{89385C74-5860-4174-9CAF-A39E7C48909C} = {89385C74-5860-4174-9CAF-A39E7C48909C}
+ {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5} = {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}
{F057DA7F-79E5-4B00-845C-EF446EF055E3} = {F057DA7F-79E5-4B00-845C-EF446EF055E3}
{03207781-0D1C-4DB3-A71D-45C608F28DBD} = {03207781-0D1C-4DB3-A71D-45C608F28DBD}
{F6C55D93-B927-4483-BB69-15AEF3DD2DFF} = {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}
diff --git a/Freeswitch.2008.sln b/Freeswitch.2008.sln
index 01a4cf43c1..e171ffe418 100644
--- a/Freeswitch.2008.sln
+++ b/Freeswitch.2008.sln
@@ -381,6 +381,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSwitchCoreLib", "w32\Li
ProjectSection(ProjectDependencies) = postProject
{8D04B550-D240-4A44-8A18-35DA3F7038D9} = {8D04B550-D240-4A44-8A18-35DA3F7038D9}
{89385C74-5860-4174-9CAF-A39E7C48909C} = {89385C74-5860-4174-9CAF-A39E7C48909C}
+ {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5} = {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}
{F057DA7F-79E5-4B00-845C-EF446EF055E3} = {F057DA7F-79E5-4B00-845C-EF446EF055E3}
{03207781-0D1C-4DB3-A71D-45C608F28DBD} = {03207781-0D1C-4DB3-A71D-45C608F28DBD}
{F6C55D93-B927-4483-BB69-15AEF3DD2DFF} = {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}
diff --git a/Makefile.am b/Makefile.am
index 944511dac9..df1ee2e0d0 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`
@@ -100,6 +102,7 @@ CORE_CFLAGS += -I$(switch_srcdir)/libs/pcre
CORE_CFLAGS += -I$(switch_srcdir)/libs/speex/include -Ilibs/speex/include
CORE_CFLAGS += -I$(switch_srcdir)/libs/srtp/include
CORE_CFLAGS += -I$(switch_srcdir)/libs/srtp/crypto/include -Ilibs/srtp/crypto/include
+CORE_CFLAGS += -I$(switch_srcdir)/libs/spandsp/src -I$(switch_srcdir)/libs/tiff-3.8.2/libtiff
CORE_LIBS = libs/apr-util/libaprutil-1.la libs/apr/libapr-1.la
CORE_LIBS += libs/sqlite/libsqlite3.la libs/pcre/libpcre.la libs/speex/libspeex/libspeexdsp.la
@@ -247,7 +250,8 @@ libfreeswitch_la_SOURCES = \
libs/miniupnpc/minissdpc.c \
libs/miniupnpc/upnperrors.c \
libs/libnatpmp/natpmp.c \
- libs/libnatpmp/getgateway.c
+ libs/libnatpmp/getgateway.c\
+ libs/spandsp/src/plc.c
if ENABLE_CPP
libfreeswitch_la_SOURCES += src/switch_cpp.cpp
@@ -272,7 +276,8 @@ bin_PROGRAMS = freeswitch fs_cli fs_ivrd tone2wav fs_encode
##
## fs_cli ()
##
-fs_cli_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c libs/esl/src/esl_threadmutex.c libs/esl/fs_cli.c libs/esl/src/esl_json.c
+fs_cli_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c \
+ libs/esl/src/esl_threadmutex.c libs/esl/fs_cli.c libs/esl/src/esl_json.c libs/esl/src/esl_buffer.c
fs_cli_CFLAGS = $(AM_CFLAGS) -I$(switch_srcdir)/libs/esl/src/include
fs_cli_LDFLAGS = $(AM_LDFLAGS) -lpthread $(ESL_LDFLAGS) -lm
@@ -300,7 +305,8 @@ tone2wav_LDADD = libfreeswitch.la
##
## fs_ivrd ()
##
-fs_ivrd_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c libs/esl/src/esl_threadmutex.c libs/esl/ivrd.c libs/esl/src/esl_json.c
+fs_ivrd_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c \
+ libs/esl/src/esl_threadmutex.c libs/esl/ivrd.c libs/esl/src/esl_json.c libs/esl/src/esl_buffer.c
fs_ivrd_CFLAGS = $(AM_CFLAGS) -I$(switch_srcdir)/libs/esl/src/include
fs_ivrd_LDFLAGS = $(AM_LDFLAGS) -lpthread $(ESL_LDFLAGS) -lm
@@ -374,7 +380,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 b1ab0f1723..d91cf11419 100644
--- a/configure.in
+++ b/configure.in
@@ -377,6 +377,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 6037c14ec7..0ca48c0e81 100644
--- a/docs/ChangeLog
+++ b/docs/ChangeLog
@@ -20,6 +20,7 @@ freeswitch (1.0.7)
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)
+ build: add plc to core (r:b7c80a84)
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
@@ -32,6 +33,8 @@ freeswitch (1.0.7)
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)
+ config: Bump Doxygen.conf version to 1.0.6... belatedly (r:cfeae1ba)
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
@@ -134,6 +137,25 @@ freeswitch (1.0.7)
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)
+ core: Fix crash in ODBC when SQL Server kills TCP connection (r:5aba96e3/FS-2910)
+ core: Fix fallback to CORE_DB when MSSQL fails init (r:3406d05b)
+ core: add new function to init an empty switch_sockaddr_t to avoid an unnecessary dns lookup on 0.0.0.0 (r:009c41d4)
+ core: fix endless RTP loop in Windows (r:cb2d0736/FS-2924)
+ core: play_and_get_digits should actually timeout, not last forever... (r:28cab5ed/FS-2923)
+ core: Fix crash w/o core dump (r:00046ee0/FS-2933)
+ core: normalize tests for outbound channels to use switch_channel_direction instead of testing for CF_OUTBOUND (r:93cc3dc5)
+ core: add CF_DIALPLAN (r:3ff07445)
+ core: tweak on calle[re] id (r:9db4a826)
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)
@@ -151,6 +173,9 @@ freeswitch (1.0.7)
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)
+ libesl: Make last_event pointer last longer (r:a15f51d5/ESL-37)
+ libesl: use a packet buffer for ESL (r:2081bf97)
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)
@@ -189,7 +214,8 @@ freeswitch (1.0.7)
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 ammount of second before it kicked out of the queue rather than get rejected automaticly. (r:81a03869)
+ 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
@@ -205,6 +231,10 @@ freeswitch (1.0.7)
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_commands: allow epoch in strftime_tz (r:bbf1cd1f)
+ mod_commands: Dramatic jitterbuffer changes (r:d5470961)
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
@@ -214,6 +244,7 @@ freeswitch (1.0.7)
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_conference: revert to the last transfered conference on recover (r:d11c83b1)
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)
@@ -221,6 +252,8 @@ freeswitch (1.0.7)
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_distributor: Add mod_distributor to VS2010 - not built by default (r:bac79ba1)
mod_dptools: add eavesdrop_enable_dtmf chan var (r:596c0012)
@@ -279,8 +312,10 @@ freeswitch (1.0.7)
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)
@@ -324,6 +359,7 @@ freeswitch (1.0.7)
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
@@ -472,6 +508,19 @@ freeswitch (1.0.7)
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_sofia: Add reuse-connections sofia profile param to allow users to turn off TPTAG_REUSE, thus not re-using TCP connections (r:98ed05cc)
+ mod_sofia: Make sofia recover also work on custom uuid (r:3a645dee/FS-2913)
+ mod_sofia: remove check for va_list completely in sofia since i don't even think it happens ever (r:dfecc914)
+ mod_sofia: have mod_sofia always elect to be the session refresher so we know it will work, also make the session-expires set to 0 imply 100% disabled session timers (r:321013ef)
+ mod_sofia: Do not set nat mode when the device's network_ip is within the acl also so if your FS is behind nat and your phone is too then it will still make the right decisions (r:6c6eab8c)
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)
@@ -487,6 +536,7 @@ freeswitch (1.0.7)
mod_spidermonkey: fix seg in js hangup (r:7d554c11)
mod_spidermonkey: Fix mod_spidermonkey build on FreeBSD, (Undefined symbol PR_LocalTimeParameters). (r:3edb8419)
mod_spy: add support for loopback endpoint (MODAPP-416)
+ mod_spy: fix crash when session can't be located (r:c4154633/FS-2929)
mod_tts_commandline: fix core dump, temp file problem. flush can be called several times (FSMOD-35)
mod_unimrcp: fix fortify findings for mod_unimrcp (r:336f0b4e/FSMOD-67)
mod_valet_parking: add event data to valet parking hold event
@@ -508,6 +558,8 @@ freeswitch (1.0.7)
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)
diff --git a/docs/Doxygen.conf b/docs/Doxygen.conf
index ccdb3b8a47..2c06417833 100644
--- a/docs/Doxygen.conf
+++ b/docs/Doxygen.conf
@@ -31,7 +31,7 @@ PROJECT_NAME = FreeSWITCH
# This could be handy for archiving the generated documentation or
# if some version control system is used.
-PROJECT_NUMBER = 1.0.4
+PROJECT_NUMBER = 1.0.6
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
diff --git a/docs/phrase/phrase_en.xml b/docs/phrase/phrase_en.xml
index a028a2aae0..41bc69cde1 100644
--- a/docs/phrase/phrase_en.xml
+++ b/docs/phrase/phrase_en.xml
@@ -221,6 +221,7 @@
+
@@ -241,6 +242,8 @@
+
+
@@ -259,6 +262,12 @@
+
+
+
+
+
+
@@ -362,8 +371,6 @@
-
-
@@ -390,15 +397,10 @@
-
-
-
-
-
@@ -409,10 +411,7 @@
-
-
-
@@ -425,20 +424,10 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
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/Makefile b/libs/esl/Makefile
index a180406bda..ab50bac4d9 100644
--- a/libs/esl/Makefile
+++ b/libs/esl/Makefile
@@ -9,9 +9,9 @@ CXXFLAGS=$(BASE_FLAGS) -Wall -Werror -Wno-unused-variable
MYLIB=libesl.a
LIBS=-lncurses -lpthread -lesl -lm
LDFLAGS=-L.
-OBJS=src/esl.o src/esl_event.o src/esl_threadmutex.o src/esl_config.o src/esl_json.o
-SRC=src/esl.c src/esl_json.c src/esl_event.c src/esl_threadmutex.c src/esl_config.c src/esl_oop.cpp src/esl_json.c
-HEADERS=src/include/esl_config.h src/include/esl_event.h src/include/esl.h src/include/esl_threadmutex.h src/include/esl_oop.h src/include/esl_json.h
+OBJS=src/esl.o src/esl_event.o src/esl_threadmutex.o src/esl_config.o src/esl_json.o src/esl_buffer.o
+SRC=src/esl.c src/esl_json.c src/esl_event.c src/esl_threadmutex.c src/esl_config.c src/esl_oop.cpp src/esl_json.c src/esl_buffer.c
+HEADERS=src/include/esl_config.h src/include/esl_event.h src/include/esl.h src/include/esl_threadmutex.h src/include/esl_oop.h src/include/esl_json.h src/include/esl_buffer.h
SOLINK=-shared -Xlinker -x
# comment the next line to disable c++ (no swig mods for you then)
OBJS += src/esl_oop.o
diff --git a/libs/esl/fs_cli.c b/libs/esl/fs_cli.c
index 91836b7aec..569e2cd169 100644
--- a/libs/esl/fs_cli.c
+++ b/libs/esl/fs_cli.c
@@ -1005,7 +1005,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/esl/src/esl.2008.vcproj b/libs/esl/src/esl.2008.vcproj
index 101348dd59..89daa17d9e 100644
--- a/libs/esl/src/esl.2008.vcproj
+++ b/libs/esl/src/esl.2008.vcproj
@@ -290,6 +290,10 @@
RelativePath=".\esl.c"
>
+
+
@@ -316,6 +320,10 @@
RelativePath=".\include\esl.h"
>
+
+
diff --git a/libs/esl/src/esl.2010.vcxproj b/libs/esl/src/esl.2010.vcxproj
index b215fe4bc8..fd5e3a8353 100644
--- a/libs/esl/src/esl.2010.vcxproj
+++ b/libs/esl/src/esl.2010.vcxproj
@@ -128,6 +128,7 @@
+
@@ -135,6 +136,7 @@
+
diff --git a/libs/esl/src/esl.c b/libs/esl/src/esl.c
index 4a02a8fe38..f5bab62fcb 100644
--- a/libs/esl/src/esl.c
+++ b/libs/esl/src/esl.c
@@ -428,6 +428,10 @@ ESL_DECLARE(esl_status_t) esl_attach_handle(esl_handle_t *handle, esl_socket_t s
esl_mutex_create(&handle->mutex);
}
+ if (!handle->packet_buf) {
+ esl_buffer_create(&handle->packet_buf, BUF_CHUNK, BUF_START, 0);
+ }
+
handle->connected = 1;
esl_send_recv(handle, "connect\n\n");
@@ -632,6 +636,10 @@ ESL_DECLARE(esl_status_t) esl_connect_timeout(esl_handle_t *handle, const char *
if (!handle->mutex) {
esl_mutex_create(&handle->mutex);
}
+
+ if (!handle->packet_buf) {
+ esl_buffer_create(&handle->packet_buf, BUF_CHUNK, BUF_START, 0);
+ }
handle->sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
@@ -805,6 +813,11 @@ ESL_DECLARE(esl_status_t) esl_disconnect(esl_handle_t *handle)
esl_mutex_destroy(&mutex);
}
+ if (handle->packet_buf) {
+ esl_buffer_destroy(&handle->packet_buf);
+ }
+
+
return status;
}
@@ -825,7 +838,7 @@ ESL_DECLARE(esl_status_t) esl_recv_event_timed(esl_handle_t *handle, uint32_t ms
if (check_q) {
esl_mutex_lock(handle->mutex);
- if (handle->race_event) {
+ if (handle->race_event || esl_buffer_packet_count(handle->packet_buf)) {
esl_mutex_unlock(handle->mutex);
return esl_recv_event(handle, check_q, save_event);
}
@@ -894,12 +907,15 @@ ESL_DECLARE(esl_status_t) esl_recv_event_timed(esl_handle_t *handle, uint32_t ms
}
+static esl_ssize_t handle_recv(esl_handle_t *handle, void *data, esl_size_t datalen)
+{
+ return recv(handle->sock, data, datalen, 0);
+}
ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_event_t **save_event)
{
char *c;
esl_ssize_t rrval;
- int crc = 0;
esl_event_t *revent = NULL;
char *beg;
char *hname, *hval;
@@ -907,7 +923,6 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
char *cl;
esl_ssize_t len;
int zc = 0;
- int bread = 0;
if (!handle || !handle->connected || handle->sock == ESL_SOCK_INVALID) {
return ESL_FAIL;
@@ -916,9 +931,7 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
esl_mutex_lock(handle->mutex);
if (!handle->connected || handle->sock == ESL_SOCK_INVALID) {
- handle->connected = 0;
- esl_mutex_unlock(handle->mutex);
- return ESL_FAIL;
+ goto fail;
}
esl_event_safe_destroy(&handle->last_event);
@@ -932,76 +945,62 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
goto parse_event;
}
- memset(handle->header_buf, 0, sizeof(handle->header_buf));
+
+ while(!revent && handle->connected) {
+ esl_size_t len1;
+
+ if ((len1 = esl_buffer_read_packet(handle->packet_buf, handle->socket_buf, sizeof(handle->socket_buf)))) {
+ char *data = (char *) handle->socket_buf;
+ char *p, *e;
+
+ esl_event_create(&revent, ESL_EVENT_CLONE);
+ revent->event_id = ESL_EVENT_SOCKET_DATA;
+ esl_event_add_header_string(revent, ESL_STACK_BOTTOM, "Event-Name", "SOCKET_DATA");
+
+ hname = p = data;
+ while(p) {
+ hname = p;
+ p = NULL;
- c = handle->header_buf;
- beg = c;
+ if ((hval = strchr(hname, ':'))) {
+ *hval++ = '\0';
+ while(*hval == ' ' || *hval == '\t') hval++;
- while(handle->connected) {
- if (bread + 2 >= sizeof(handle->header_buf)) {
- esl_log(ESL_LOG_CRIT, "OUT OF BUFFER SPACE!\n");
- handle->connected = 0;
- esl_mutex_unlock(handle->mutex);
- return ESL_DISCONNECTED;
+ if ((e = strchr(hval, '\n'))) {
+ *e++ = '\0';
+ while(*e == '\n' || *e == '\r') e++;
+
+ if (hname && hval) {
+ esl_url_decode(hval);
+ esl_log(ESL_LOG_DEBUG, "RECV HEADER [%s] = [%s]\n", hname, hval);
+ esl_event_add_header_string(revent, ESL_STACK_BOTTOM, hname, hval);
+ }
+
+ p = e;
+ }
+ }
+ }
+
+ break;
}
- rrval = recv(handle->sock, c, 1, 0);
+ rrval = handle_recv(handle, handle->socket_buf, sizeof(handle->socket_buf));
+
if (rrval == 0) {
if (++zc >= 100) {
- handle->connected = 0;
- esl_mutex_unlock(handle->mutex);
- return ESL_DISCONNECTED;
+ goto fail;
}
+ continue;
} else if (rrval < 0) {
strerror_r(handle->errnum, handle->err, sizeof(handle->err));
goto fail;
- } else {
- zc = 0;
-
- if (*c == '\n') {
-
- *(c+1) = '\0';
-
- if (++crc == 2) {
- break;
- }
-
- if (!revent) {
- esl_event_create(&revent, ESL_EVENT_CLONE);
- revent->event_id = ESL_EVENT_SOCKET_DATA;
- esl_event_add_header_string(revent, ESL_STACK_BOTTOM, "Event-Name", "SOCKET_DATA");
-
- }
-
- hname = beg;
- hval = col = NULL;
-
- if (hname && (col = strchr(hname, ':'))) {
- hval = col + 1;
- *col = '\0';
- while(*hval == ' ') hval++;
- }
-
- *c = '\0';
-
- if (hname && hval) {
- esl_url_decode(hval);
- esl_log(ESL_LOG_DEBUG, "RECV HEADER [%s] = [%s]\n", hname, hval);
- esl_event_add_header_string(revent, ESL_STACK_BOTTOM, hname, hval);
- }
-
- c = beg;
- bread = 0;
- continue;
-
- } else {
- crc = 0;
- }
-
- c++;
}
- }
+ zc = 0;
+
+ esl_buffer_write(handle->packet_buf, handle->socket_buf, rrval);
+ }
+
if (!revent) {
goto fail;
}
@@ -1016,12 +1015,28 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
*(body + len) = '\0';
do {
- esl_ssize_t r;
- if ((r = recv(handle->sock, body + sofar, len - sofar, 0)) < 0) {
- strerror_r(handle->errnum, handle->err, sizeof(handle->err));
- goto fail;
+ esl_ssize_t r,s = esl_buffer_inuse(handle->packet_buf);
+
+ if (s >= len) {
+ sofar = esl_buffer_read(handle->packet_buf, body, len);
+ } else {
+ r = handle_recv(handle, handle->socket_buf, sizeof(handle->socket_buf));
+
+ if (r < 0) {
+ strerror_r(handle->errnum, handle->err, sizeof(handle->err));
+ goto fail;
+ } else if (r == 0) {
+ if (++zc >= 100) {
+ goto fail;
+ }
+ continue;
+ }
+
+ zc = 0;
+
+ esl_buffer_write(handle->packet_buf, handle->socket_buf, r);
}
- sofar += r;
+
} while (sofar < len);
revent->body = body;
@@ -1123,6 +1138,8 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
fail:
+ esl_mutex_unlock(handle->mutex);
+
handle->connected = 0;
return ESL_FAIL;
@@ -1177,7 +1194,6 @@ ESL_DECLARE(esl_status_t) esl_send_recv_timed(esl_handle_t *handle, const char *
return ESL_FAIL;
}
- esl_event_safe_destroy(&handle->last_event);
esl_event_safe_destroy(&handle->last_sr_event);
*handle->last_sr_reply = '\0';
diff --git a/libs/esl/src/esl_buffer.c b/libs/esl/src/esl_buffer.c
new file mode 100644
index 0000000000..8032169fe3
--- /dev/null
+++ b/libs/esl/src/esl_buffer.c
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2010, Anthony Minessale II
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "esl_buffer.h"
+
+static unsigned buffer_id = 0;
+
+struct esl_buffer {
+ unsigned char *data;
+ unsigned char *head;
+ esl_size_t used;
+ esl_size_t actually_used;
+ esl_size_t datalen;
+ esl_size_t max_len;
+ esl_size_t blocksize;
+ unsigned id;
+ int loops;
+};
+
+
+ESL_DECLARE(esl_status_t) esl_buffer_create(esl_buffer_t **buffer, esl_size_t blocksize, esl_size_t start_len, esl_size_t max_len)
+{
+ esl_buffer_t *new_buffer;
+
+ new_buffer = malloc(sizeof(*new_buffer));
+ if (new_buffer) {
+ memset(new_buffer, 0, sizeof(*new_buffer));
+
+ if (start_len) {
+ new_buffer->data = malloc(start_len);
+ if (!new_buffer->data) {
+ free(new_buffer);
+ return ESL_FAIL;
+ }
+ memset(new_buffer->data, 0, start_len);
+ }
+
+ new_buffer->max_len = max_len;
+ new_buffer->datalen = start_len;
+ new_buffer->id = buffer_id++;
+ new_buffer->blocksize = blocksize;
+ new_buffer->head = new_buffer->data;
+
+ *buffer = new_buffer;
+ return ESL_SUCCESS;
+ }
+
+ return ESL_FAIL;
+}
+
+ESL_DECLARE(esl_size_t) esl_buffer_len(esl_buffer_t *buffer)
+{
+
+ assert(buffer != NULL);
+
+ return buffer->datalen;
+
+}
+
+
+ESL_DECLARE(esl_size_t) esl_buffer_freespace(esl_buffer_t *buffer)
+{
+ assert(buffer != NULL);
+
+
+ if (buffer->max_len) {
+ return (esl_size_t) (buffer->max_len - buffer->used);
+ }
+ return 1000000;
+
+}
+
+ESL_DECLARE(esl_size_t) esl_buffer_inuse(esl_buffer_t *buffer)
+{
+ assert(buffer != NULL);
+
+ return buffer->used;
+}
+
+ESL_DECLARE(esl_size_t) esl_buffer_seek(esl_buffer_t *buffer, esl_size_t datalen)
+{
+ esl_size_t reading = 0;
+
+ assert(buffer != NULL);
+
+ if (buffer->used < 1) {
+ buffer->used = 0;
+ return 0;
+ } else if (buffer->used >= datalen) {
+ reading = datalen;
+ } else {
+ reading = buffer->used;
+ }
+
+ buffer->used = buffer->actually_used - reading;
+ buffer->head = buffer->data + reading;
+
+ return reading;
+}
+
+ESL_DECLARE(esl_size_t) esl_buffer_toss(esl_buffer_t *buffer, esl_size_t datalen)
+{
+ esl_size_t reading = 0;
+
+ assert(buffer != NULL);
+
+ if (buffer->used < 1) {
+ buffer->used = 0;
+ return 0;
+ } else if (buffer->used >= datalen) {
+ reading = datalen;
+ } else {
+ reading = buffer->used;
+ }
+
+ buffer->used -= reading;
+ buffer->head += reading;
+
+ return buffer->used;
+}
+
+ESL_DECLARE(void) esl_buffer_set_loops(esl_buffer_t *buffer, int loops)
+{
+ buffer->loops = loops;
+}
+
+ESL_DECLARE(esl_size_t) esl_buffer_read_loop(esl_buffer_t *buffer, void *data, esl_size_t datalen)
+{
+ esl_size_t len;
+ if ((len = esl_buffer_read(buffer, data, datalen)) < datalen) {
+ if (buffer->loops == 0) {
+ return len;
+ }
+ buffer->head = buffer->data;
+ buffer->used = buffer->actually_used;
+ len = esl_buffer_read(buffer, (char*)data + len, datalen - len);
+ buffer->loops--;
+ }
+ return len;
+}
+
+ESL_DECLARE(esl_size_t) esl_buffer_read(esl_buffer_t *buffer, void *data, esl_size_t datalen)
+{
+ esl_size_t reading = 0;
+
+ assert(buffer != NULL);
+ assert(data != NULL);
+
+
+ if (buffer->used < 1) {
+ buffer->used = 0;
+ return 0;
+ } else if (buffer->used >= datalen) {
+ reading = datalen;
+ } else {
+ reading = buffer->used;
+ }
+
+ memcpy(data, buffer->head, reading);
+ buffer->used -= reading;
+ buffer->head += reading;
+
+ /* if (buffer->id == 4) printf("%u o %d = %d\n", buffer->id, (unsigned)reading, (unsigned)buffer->used); */
+ return reading;
+}
+
+
+ESL_DECLARE(esl_size_t) esl_buffer_packet_count(esl_buffer_t *buffer)
+{
+ char *pe, *p, *e, *head = (char *) buffer->head;
+ esl_size_t x = 0;
+
+ assert(buffer != NULL);
+
+ e = (head + buffer->used);
+
+ for (p = head; p && *p && p < e; p++) {
+ if (*p == '\n') {
+ pe = p+1;
+ if (*pe == '\r') pe++;
+ if (pe <= e && *pe == '\n') {
+ p = pe++;
+ x++;
+ }
+ }
+ }
+
+ return x;
+}
+
+ESL_DECLARE(esl_size_t) esl_buffer_read_packet(esl_buffer_t *buffer, void *data, esl_size_t maxlen)
+{
+ char *pe, *p, *e, *head = (char *) buffer->head;
+ esl_size_t datalen = 0;
+
+ assert(buffer != NULL);
+ assert(data != NULL);
+
+ e = (head + buffer->used);
+
+ for (p = head; p && *p && p < e; p++) {
+ if (*p == '\n') {
+ pe = p+1;
+ if (*pe == '\r') pe++;
+ if (pe <= e && *pe == '\n') {
+ pe++;
+ datalen = pe - head;
+ if (datalen > maxlen) {
+ datalen = maxlen;
+ }
+ break;
+ }
+ }
+ }
+
+ return esl_buffer_read(buffer, data, datalen);
+}
+
+ESL_DECLARE(esl_size_t) esl_buffer_write(esl_buffer_t *buffer, const void *data, esl_size_t datalen)
+{
+ esl_size_t freespace, actual_freespace;
+
+ assert(buffer != NULL);
+ assert(data != NULL);
+ assert(buffer->data != NULL);
+
+ if (!datalen) {
+ return buffer->used;
+ }
+
+ actual_freespace = buffer->datalen - buffer->actually_used;
+ if (actual_freespace < datalen && (!buffer->max_len || (buffer->used + datalen <= buffer->max_len))) {
+ memmove(buffer->data, buffer->head, buffer->used);
+ buffer->head = buffer->data;
+ buffer->actually_used = buffer->used;
+ }
+
+ freespace = buffer->datalen - buffer->used;
+
+ /*
+ if (buffer->data != buffer->head) {
+ memmove(buffer->data, buffer->head, buffer->used);
+ buffer->head = buffer->data;
+ }
+ */
+
+ if (freespace < datalen) {
+ esl_size_t new_size, new_block_size;
+ void *data1;
+
+ new_size = buffer->datalen + datalen;
+ new_block_size = buffer->datalen + buffer->blocksize;
+
+ if (new_block_size > new_size) {
+ new_size = new_block_size;
+ }
+ buffer->head = buffer->data;
+ data1 = realloc(buffer->data, new_size);
+ if (!data1) {
+ return 0;
+ }
+ buffer->data = data1;
+ buffer->head = buffer->data;
+ buffer->datalen = new_size;
+ }
+
+
+ freespace = buffer->datalen - buffer->used;
+
+ if (freespace < datalen) {
+ return 0;
+ } else {
+ memcpy(buffer->head + buffer->used, data, datalen);
+ buffer->used += datalen;
+ buffer->actually_used += datalen;
+ }
+ /* if (buffer->id == 4) printf("%u i %d = %d\n", buffer->id, (unsigned)datalen, (unsigned)buffer->used); */
+
+ return buffer->used;
+}
+
+ESL_DECLARE(void) esl_buffer_zero(esl_buffer_t *buffer)
+{
+ assert(buffer != NULL);
+ assert(buffer->data != NULL);
+
+ buffer->used = 0;
+ buffer->actually_used = 0;
+ buffer->head = buffer->data;
+}
+
+ESL_DECLARE(esl_size_t) esl_buffer_zwrite(esl_buffer_t *buffer, const void *data, esl_size_t datalen)
+{
+ esl_size_t w;
+
+ if (!(w = esl_buffer_write(buffer, data, datalen))) {
+ esl_buffer_zero(buffer);
+ return esl_buffer_write(buffer, data, datalen);
+ }
+
+ return w;
+}
+
+ESL_DECLARE(void) esl_buffer_destroy(esl_buffer_t **buffer)
+{
+ if (*buffer) {
+ free((*buffer)->data);
+ free(*buffer);
+ }
+
+ *buffer = NULL;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+ */
diff --git a/libs/esl/src/include/esl.h b/libs/esl/src/include/esl.h
index 9f28c3d925..99ab53ae95 100644
--- a/libs/esl/src/include/esl.h
+++ b/libs/esl/src/include/esl.h
@@ -251,6 +251,7 @@ typedef int esl_filehandle_t;
#include "esl_json.h"
typedef int16_t esl_port_t;
+typedef size_t esl_size_t;
typedef enum {
ESL_SUCCESS,
@@ -259,7 +260,11 @@ typedef enum {
ESL_DISCONNECTED
} esl_status_t;
+#define BUF_CHUNK 65536 * 50
+#define BUF_START 65536 * 100
+
#include
+#include
/*! \brief A handle that will hold the socket information and
different events received. */
@@ -273,7 +278,8 @@ typedef struct {
/*! The error number reported by the OS */
int errnum;
/*! The inner contents received by the socket. Used only internally. */
- char header_buf[4196];
+ esl_buffer_t *packet_buf;
+ char socket_buf[65536];
/*! Last command reply */
char last_reply[1024];
/*! Las command reply when called with esl_send_recv */
diff --git a/libs/esl/src/include/esl_buffer.h b/libs/esl/src/include/esl_buffer.h
new file mode 100644
index 0000000000..c7901e4ede
--- /dev/null
+++ b/libs/esl/src/include/esl_buffer.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2010, Anthony Minessale II
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "esl.h"
+#ifndef ESL_BUFFER_H
+#define ESL_BUFFER_H
+/**
+ * @defgroup esl_buffer Buffer Routines
+ * @ingroup buffer
+ * The purpose of this module is to make a plain buffering interface that can be used for read/write buffers
+ * throughout the application.
+ * @{
+ */
+struct esl_buffer;
+typedef struct esl_buffer esl_buffer_t;
+
+/*! \brief Allocate a new dynamic esl_buffer
+ * \param buffer returned pointer to the new buffer
+ * \param blocksize length to realloc by as data is added
+ * \param start_len ammount of memory to reserve initially
+ * \param max_len length the buffer is allowed to grow to
+ * \return status
+ */
+ESL_DECLARE(esl_status_t) esl_buffer_create(esl_buffer_t **buffer, esl_size_t blocksize, esl_size_t start_len, esl_size_t max_len);
+
+/*! \brief Get the length of a esl_buffer_t
+ * \param buffer any buffer of type esl_buffer_t
+ * \return int size of the buffer.
+ */
+ESL_DECLARE(esl_size_t) esl_buffer_len(esl_buffer_t *buffer);
+
+/*! \brief Get the freespace of a esl_buffer_t
+ * \param buffer any buffer of type esl_buffer_t
+ * \return int freespace in the buffer.
+ */
+ESL_DECLARE(esl_size_t) esl_buffer_freespace(esl_buffer_t *buffer);
+
+/*! \brief Get the in use amount of a esl_buffer_t
+ * \param buffer any buffer of type esl_buffer_t
+ * \return int ammount of buffer curently in use
+ */
+ESL_DECLARE(esl_size_t) esl_buffer_inuse(esl_buffer_t *buffer);
+
+/*! \brief Read data from a esl_buffer_t up to the ammount of datalen if it is available. Remove read data from buffer.
+ * \param buffer any buffer of type esl_buffer_t
+ * \param data pointer to the read data to be returned
+ * \param datalen amount of data to be returned
+ * \return int ammount of data actually read
+ */
+ESL_DECLARE(esl_size_t) esl_buffer_read(esl_buffer_t *buffer, void *data, esl_size_t datalen);
+
+ESL_DECLARE(esl_size_t) esl_buffer_read_packet(esl_buffer_t *buffer, void *data, esl_size_t maxlen);
+ESL_DECLARE(esl_size_t) esl_buffer_packet_count(esl_buffer_t *buffer);
+
+/*! \brief Read data endlessly from a esl_buffer_t
+ * \param buffer any buffer of type esl_buffer_t
+ * \param data pointer to the read data to be returned
+ * \param datalen amount of data to be returned
+ * \return int ammount of data actually read
+ * \note Once you have read all the data from the buffer it will loop around.
+ */
+ESL_DECLARE(esl_size_t) esl_buffer_read_loop(esl_buffer_t *buffer, void *data, esl_size_t datalen);
+
+/*! \brief Assign a number of loops to read
+ * \param buffer any buffer of type esl_buffer_t
+ * \param loops the number of loops (-1 for infinite)
+ */
+ESL_DECLARE(void) esl_buffer_set_loops(esl_buffer_t *buffer, int32_t loops);
+
+/*! \brief Write data into a esl_buffer_t up to the length of datalen
+ * \param buffer any buffer of type esl_buffer_t
+ * \param data pointer to the data to be written
+ * \param datalen amount of data to be written
+ * \return int amount of buffer used after the write, or 0 if no space available
+ */
+ESL_DECLARE(esl_size_t) esl_buffer_write(esl_buffer_t *buffer, const void *data, esl_size_t datalen);
+
+/*! \brief Remove data from the buffer
+ * \param buffer any buffer of type esl_buffer_t
+ * \param datalen amount of data to be removed
+ * \return int size of buffer, or 0 if unable to toss that much data
+ */
+ESL_DECLARE(esl_size_t) esl_buffer_toss(esl_buffer_t *buffer, esl_size_t datalen);
+
+/*! \brief Remove all data from the buffer
+ * \param buffer any buffer of type esl_buffer_t
+ */
+ESL_DECLARE(void) esl_buffer_zero(esl_buffer_t *buffer);
+
+/*! \brief Destroy the buffer
+ * \param buffer buffer to destroy
+ * \note only neccessary on dynamic buffers (noop on pooled ones)
+ */
+ESL_DECLARE(void) esl_buffer_destroy(esl_buffer_t **buffer);
+
+/*! \brief Seek to offset from the beginning of the buffer
+ * \param buffer buffer to seek
+ * \param datalen offset in bytes
+ * \return new position
+ */
+ESL_DECLARE(esl_size_t) esl_buffer_seek(esl_buffer_t *buffer, esl_size_t datalen);
+
+/** @} */
+
+ESL_DECLARE(esl_size_t) esl_buffer_zwrite(esl_buffer_t *buffer, const void *data, esl_size_t datalen);
+
+#endif
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+ */
diff --git a/libs/freetdm/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/configure.gnu b/libs/freetdm/configure.gnu
index 5785ffc0e7..d00cd18473 100755
--- a/libs/freetdm/configure.gnu
+++ b/libs/freetdm/configure.gnu
@@ -1,3 +1,3 @@
#! /bin/sh
-./configure "$@" --with-pic
-
+srcpath=$(dirname $0 2>/dev/null ) || srcpath="."
+$srcpath/configure "$@" --with-pic
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/docs/sigstatus.txt b/libs/freetdm/docs/sigstatus.txt
new file mode 100644
index 0000000000..10561bfb5b
--- /dev/null
+++ b/libs/freetdm/docs/sigstatus.txt
@@ -0,0 +1,59 @@
+FreeTDM can both notify and set signaling status changes in the different protocols thru a unified interface. More
+specific details on the C data types and function prototypes are found in freetdm.h
+
+The API provides the following functions and data types to do it:
+
+The signaling status in any channel/span is represented thru ftdm_signaling_status_t
+
+ /* The signaling link is down (no d-chans up in the span/group, MFC-R2 bit pattern unidentified) */
+ FTDM_SIG_STATE_DOWN,
+ /* The signaling link is suspended (MFC-R2 bit pattern blocked, PRI maintenance, ss7 blocked?) */
+ FTDM_SIG_STATE_SUSPENDED,
+ /* The signaling link is ready and calls can be placed (ie: d-chan up, MFC-R2 both rx and tx in IDLE) */
+ FTDM_SIG_STATE_UP,
+ /* Invalid status */
+ FTDM_SIG_STATE_INVALID
+
+Changes in the signaling status are notified to the user using the standard callback notification function provided
+during configuration using the sigevent type FTDM_SIGEVENT_SIGSTATUS_CHANGED which is sent when the line status changes.
+
+On startup the signalling status default is FTDM_SIG_STATE_DOWN, and no notification is provided until the state change,
+so applications must assume the status is down unless told otherwise.
+
+When ftdm_span_start is called, the signaling stack takes care of attempting to bring the status to UP
+but it will ultimately depend on the other side too.
+
+== Setting the signaling status ==
+
+Users can set the signaling status on a given channel/span thru FreeTDM the following API functions:
+
+ftdm_channel_set_sig_status
+ftdm_span_set_sig_status
+
+If the user calls ftdm_channel_set_sig_status(chan, FTDM_SIG_STATE_SUSPENDED), the signaling stack will try to set
+the status of the line to the one requested, if successful, it will result in a SIGEVENT_SIGSTATUS_CHANGED notification
+being sent with status FTDM_SIG_STATE_SUSPENDED.
+
+** MFC-R2 Signaling Notes **
+For MFC-R2, calling ftdm_span_start() results in setting the tx CAS bits to IDLE. However, if the rx bits are in BLOCKED state
+the signaling status will be reported as SUSPENDED.
+
+If the user calls ftdm_channel_set_sig_status(chan, SUSPENDED), the tx CAS bits will be set to BLOCKED and, if, the current rx bits
+are IDLE then a SIGEVENT_SIGSTATUS_CHANGED with state SUSPENDED will be sent. If the rx bits are already in blocked then no further
+SIGEVENT_SIGSTATUS_CHANGED notification is needed (because it was already sent when the rx bits were initially detected as BLOCKED).
+
+If the user calls ftdm_channel_set_sig_status(chan, UP), the tx CAS bits will be set to IDLE and, if, the current rx bits
+are IDLE, then SIGEVENT_SIGSTATUS_CHANGED with state UP will be sent. If the rx bits are BLOCKED, then no notification is
+sent at all until the rx bits change.
+
+Bottom line is, for MFC-R2, SIGEVENT_SIGSTATUS_CHANGED UP is only sent to the user when both the rx and tx bits are in IDLE, and
+SIGEVENT_SIGSTATUS_CHANGED SUSPENDED is only sent to the user when any of the rx or tx bits are in BLOCKED.
+
+== Getting the signaling status ==
+Users can get the signaling status on a given channel/span thru FreeTDM the following API functions:
+
+ftdm_channel_get_sig_status
+ftdm_span_get_sig_status
+
+The line status returned should be the same as the last time a SIGEVENT_SIGSTATUS_CHANGED was reported.
+
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..44431d675a
--- /dev/null
+++ b/libs/freetdm/freetdm.2010.sln
@@ -0,0 +1,133 @@
+
+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|x64.ActiveCfg = Debug|x64
+ {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.ActiveCfg = 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..9f01a3b1a1
--- /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
+
+
+ FreeSwitch.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
+
+
+ FreeSwitch.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..c459a57c11 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;
}
@@ -798,7 +802,7 @@ static switch_status_t channel_receive_message_cas(switch_core_session_t *sessio
phy_id = ftdm_channel_get_ph_id(tech_pvt->ftdmchan);
ftdm_log(FTDM_LOG_DEBUG, "Got Freeswitch message in R2 channel %d [%d]\n", phy_id, msg->message_id);
- if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
return SWITCH_STATUS_SUCCESS;
}
@@ -837,22 +841,22 @@ 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;
}
- if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
return SWITCH_STATUS_SUCCESS;
}
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,11 +888,11 @@ 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)) {
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
return SWITCH_STATUS_SUCCESS;
}
@@ -920,7 +924,7 @@ static switch_status_t channel_receive_message_fxs(switch_core_session_t *sessio
return SWITCH_STATUS_FALSE;
}
- if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_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;
@@ -977,7 +981,7 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_PROGRESS:
case SWITCH_MESSAGE_INDICATE_ANSWER:
- if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
if ((var = switch_channel_get_variable(channel, "freetdm_pre_buffer_size"))) {
int tmp = atoi(var);
if (tmp > -1) {
@@ -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);
}
}
}
@@ -1344,7 +1363,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
tech_pvt->caller_profile = caller_profile;
- switch_channel_set_flag(channel, CF_OUTBOUND);
switch_channel_set_state(channel, CS_INIT);
if (ftdm_channel_add_token(ftdmchan, switch_core_session_get_uuid(*new_session), ftdm_channel_get_token_count(ftdmchan)) != FTDM_SUCCESS) {
switch_core_session_destroy(new_session);
@@ -1398,6 +1416,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 +1457,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 +1527,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 +1561,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 +1664,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 +1671,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 +1698,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 +1722,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 +1777,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;
@@ -1775,7 +1810,9 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxs_signal)
switch_clear_flag_locked(tech_pvt, TFLAG_HOLD);
}
- if (channel_a && channel_b && !switch_channel_test_flag(channel_a, CF_OUTBOUND) && !switch_channel_test_flag(channel_b, CF_OUTBOUND)) {
+ if (channel_a && channel_b && switch_channel_direction(channel_a) == SWITCH_CALL_DIRECTION_INBOUND &&
+ switch_channel_direction(channel_b) == SWITCH_CALL_DIRECTION_INBOUND) {
+
cause = SWITCH_CAUSE_ATTENDED_TRANSFER;
if (br_a_uuid && br_b_uuid) {
switch_ivr_uuid_bridge(br_a_uuid, br_b_uuid);
@@ -1966,7 +2003,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 +2046,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 +2055,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 +2076,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->ev_data.sigstatus.status;
+ 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 +2117,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:
{
@@ -2106,6 +2168,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
}
break;
case FTDM_SIGEVENT_PROGRESS:
+ case FTDM_SIGEVENT_RINGING:
{
if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
channel = switch_core_session_get_channel(session);
@@ -2118,14 +2181,18 @@ 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;
+ ftdm_signaling_status_t sigstatus = sigmsg->raw_data ? *((ftdm_signaling_status_t*)(sigmsg->raw_data)) : sigmsg->ev_data.sigstatus.status;
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:
+ 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 +3260,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 +3272,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 +3302,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 +3333,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;
}
}
@@ -3558,7 +3544,83 @@ SWITCH_STANDARD_API(ft_function)
goto end;
}
- if (!strcasecmp(argv[0], "dump")) {
+ if (!strcasecmp(argv[0], "sigstatus")) {
+ ftdm_span_t *span = NULL;
+ ftdm_signaling_status_t sigstatus;
+
+ if (argc < 3) {
+ stream->write_function(stream, "-ERR Usage: ftdm sigstatus get|set [] [] []\n");
+ goto end;
+ }
+ if (!strcasecmp(argv[1], "get") && argc < 3) {
+ stream->write_function(stream, "-ERR sigstatus get usage: get \n");
+ goto end;
+ }
+ if (!strcasecmp(argv[1], "set") && argc != 5) {
+ stream->write_function(stream, "-ERR sigstatus set usage: set |all \n");
+ goto end;
+ }
+
+ ftdm_span_find_by_name(argv[2], &span);
+ if (!span) {
+ stream->write_function(stream, "-ERR invalid span\n");
+ goto end;
+ }
+
+ if (!strcasecmp(argv[1], "get")) {
+ if (argc == 4) {
+ uint32_t chan_id = atol(argv[3]);
+ ftdm_channel_t *fchan = ftdm_span_get_channel(span, chan_id);
+ if (!fchan) {
+ stream->write_function(stream, "-ERR failed to get channel id '%d'\n", chan_id);
+ goto end;
+ }
+
+ if ((FTDM_SUCCESS == ftdm_channel_get_sig_status(fchan, &sigstatus))) {
+ stream->write_function(stream, "channel %d signaling status: %s\n", chan_id, ftdm_signaling_status2str(sigstatus));
+ } else {
+ stream->write_function(stream, "-ERR failed to get channel sigstatus\n");
+ }
+ goto end;
+ } else {
+ if ((FTDM_SUCCESS == ftdm_span_get_sig_status(span, &sigstatus))) {
+ stream->write_function(stream, "signaling_status: %s\n", ftdm_signaling_status2str(sigstatus));
+ } else {
+ stream->write_function(stream, "-ERR failed to read span status: %s\n", ftdm_span_get_last_error(span));
+ }
+ }
+ goto end;
+ }
+ if (!strcasecmp(argv[1], "set")) {
+ sigstatus = ftdm_str2ftdm_signaling_status(argv[4]);
+
+ if (!strcasecmp(argv[3], "all")) {
+ if ((FTDM_SUCCESS == ftdm_span_set_sig_status(span, sigstatus))) {
+ stream->write_function(stream, "Signaling status of all channels from span %s set to %s\n",
+ ftdm_span_get_name(span), ftdm_signaling_status2str(sigstatus));
+ } else {
+ stream->write_function(stream, "-ERR failed to set span sigstatus to '%s'\n", ftdm_signaling_status2str(sigstatus));
+ }
+ goto end;
+ } else {
+ uint32_t chan_id = atol(argv[3]);
+ ftdm_channel_t *fchan = ftdm_span_get_channel(span, chan_id);
+ if (!fchan) {
+ stream->write_function(stream, "-ERR failed to get channel id '%d'\n", chan_id);
+ goto end;
+ }
+
+ if ((FTDM_SUCCESS == ftdm_channel_set_sig_status(fchan, sigstatus))) {
+ stream->write_function(stream, "Signaling status of channel %d set to %s\n", chan_id,
+ ftdm_signaling_status2str(sigstatus));
+ } else {
+ stream->write_function(stream, "-ERR failed to set span sigstatus to '%s'\n", ftdm_signaling_status2str(sigstatus));
+ }
+ goto end;
+ }
+ }
+
+ } else if (!strcasecmp(argv[0], "dump")) {
if (argc < 2) {
stream->write_function(stream, "-ERR Usage: ftdm dump []\n");
goto end;
@@ -3938,6 +4000,28 @@ SWITCH_STANDARD_API(ft_function)
}
}
stream->write_function(stream, "+OK gains set to Rx %f and Tx %f\n", rxgain, txgain);
+ } else if (!strcasecmp(argv[0], "restart")) {
+ uint32_t chan_id = 0;
+ ftdm_channel_t *chan;
+ ftdm_span_t *span = NULL;
+ if (argc < 3) {
+ stream->write_function(stream, "-ERR Usage: ftdm restart \n");
+ goto end;
+ }
+ ftdm_span_find_by_name(argv[1], &span);
+ if (!span) {
+ stream->write_function(stream, "-ERR invalid span\n");
+ goto end;
+ }
+
+ chan_id = atoi(argv[2]);
+ chan = ftdm_span_get_channel(span, chan_id);
+ if (!chan) {
+ stream->write_function(stream, "-ERR Could not find chan\n");
+ goto end;
+ }
+ stream->write_function(stream, "Resetting channel %s:%s\n", argv[2], argv[3]);
+ ftdm_channel_reset(chan);
} else {
char *rply = ftdm_api_execute(cmd);
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/patches/oz.diff b/libs/freetdm/patches/oz.diff
deleted file mode 100644
index 2e9c558b7c..0000000000
--- a/libs/freetdm/patches/oz.diff
+++ /dev/null
@@ -1,134 +0,0 @@
-Index: src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c
-===================================================================
---- src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c (revision 745)
-+++ src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c (working copy)
-@@ -98,19 +98,21 @@
- * so we can have one analong handler thread that will deal with all the idle analog channels for events
- * the alternative would be for the driver to provide one socket for all of the oob events for all analog channels
- */
--static __inline__ int tdmv_api_wait_socket(sng_fd_t fd, int timeout, int *flags)
-+static __inline__ int tdmv_api_wait_socket(zap_channel_t *zchan, int timeout, int *flags)
- {
-
- #ifdef LIBSANGOMA_VERSION
- int err;
-- sangoma_wait_obj_t sangoma_wait_obj;
-+ sangoma_wait_obj_t *sangoma_wait_obj = zchan->mod_data;
-
-- sangoma_init_wait_obj(&sangoma_wait_obj, fd, 1, 1, *flags, SANGOMA_WAIT_OBJ);
-+ sangoma_init_wait_obj(sangoma_wait_obj, zchan->sockfd, 1, 1, 0, SANGOMA_WAIT_OBJ);
-
-- err=sangoma_socket_waitfor_many(&sangoma_wait_obj,1 , timeout);
-+ err = sangoma_socket_waitfor_many(&sangoma_wait_obj, 1, timeout);
-+
- if (err > 0) {
-- *flags=sangoma_wait_obj.flags_out;
-+ *flags = sangoma_wait_obj.flags_out;
- }
-+
- return err;
-
- #else
-@@ -118,7 +120,7 @@
- int res;
-
- memset(&pfds[0], 0, sizeof(pfds[0]));
-- pfds[0].fd = fd;
-+ pfds[0].fd = zchan->sockfd;
- pfds[0].events = *flags;
- res = poll(pfds, 1, timeout);
- *flags = 0;
-@@ -200,6 +202,15 @@
-
- if (sockfd != WP_INVALID_SOCKET && zap_span_add_channel(span, sockfd, type, &chan) == ZAP_SUCCESS) {
- wanpipe_tdm_api_t tdm_api;
-+#ifdef LIBSANGOMA_VERSION
-+ sangoma_wait_obj_t *sangoma_wait_obj;
-+
-+ sangoma_wait_obj = malloc(sizeof(*sangoma_wait_obj));
-+ memset(sangoma_wait_obj, 0, sizeof(*sangoma_wait_obj));
-+ sangoma_init_wait_obj(sangoma_wait_obj, sockfd, 1, 1, 0, SANGOMA_WAIT_OBJ);
-+ chan->mod_data = sangoma_wait_obj;
-+#endif
-+
- memset(&tdm_api,0,sizeof(tdm_api));
-
- chan->physical_span_id = spanno;
-@@ -211,7 +222,7 @@
-
- dtmf = "software";
-
-- /* FIXME: Handle Error Conditino Check for return code */
-+ /* FIXME: Handle Error Condition Check for return code */
- err= sangoma_tdm_get_hw_coding(chan->sockfd, &tdm_api);
-
- if (tdm_api.wp_tdm_cmd.hw_tdm_coding) {
-@@ -606,7 +617,7 @@
- inflags |= POLLPRI;
- }
-
-- result = tdmv_api_wait_socket(zchan->sockfd, to, &inflags);
-+ result = tdmv_api_wait_socket(zchan, to, &inflags);
-
- *flags = ZAP_NO_FLAGS;
-
-@@ -643,26 +654,30 @@
- ZIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event)
- {
- #ifdef LIBSANGOMA_VERSION
-- sangoma_wait_obj_t pfds[ZAP_MAX_CHANNELS_SPAN];
-+ sangoma_wait_obj_t *pfds[ZAP_MAX_CHANNELS_SPAN] = { 0 };
- #else
- struct pollfd pfds[ZAP_MAX_CHANNELS_SPAN];
- #endif
-
- uint32_t i, j = 0, k = 0, l = 0;
-- int objects=0;
- int r;
-
- for(i = 1; i <= span->chan_count; i++) {
- zap_channel_t *zchan = span->channels[i];
-
-+
- #ifdef LIBSANGOMA_VERSION
-- sangoma_init_wait_obj(&pfds[j], zchan->sockfd , 1, 1, POLLPRI, SANGOMA_WAIT_OBJ);
-+ if (!zchan->mod_data) {
-+ continue;
-+ }
-+ pfds[j] = zchan->mod_data;
-+
- #else
- memset(&pfds[j], 0, sizeof(pfds[j]));
- pfds[j].fd = span->channels[i]->sockfd;
- pfds[j].events = POLLPRI;
- #endif
-- objects++;
-+
- /* The driver probably should be able to do this wink/flash/ringing by itself this is sort of a hack to make it work! */
-
- if (zap_test_flag(zchan, ZAP_CHANNEL_WINK) || zap_test_flag(zchan, ZAP_CHANNEL_FLASH)) {
-@@ -703,7 +718,7 @@
- ms = l;
- }
- #ifdef LIBSANGOMA_VERSION
-- r = sangoma_socket_waitfor_many(pfds,objects,ms);
-+ r = sangoma_socket_waitfor_many(pfds, j, ms);
- #else
- r = poll(pfds, j, ms);
- #endif
-@@ -935,6 +950,15 @@
- */
- static ZIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy)
- {
-+ sangoma_wait_obj_t *sangoma_wait_obj;
-+
-+ if (zchan->mod_data) {
-+ sangoma_wait_obj = zchan->mod_data;
-+ zchan->mod_data = NULL;
-+ sangoma_release_wait_obj(sangoma_wait_obj);
-+ free(sangoma_wait_obj);
-+ }
-+
- if (zchan->sockfd > -1) {
- close(zchan->sockfd);
- zchan->sockfd = WP_INVALID_SOCKET;
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 1dada451be..1750d6d7d9 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,11 +48,25 @@
#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
+#define MAX_CALLIDS 6000
+
+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 ftdm_status_t ftdm_call_set_call_id(ftdm_caller_data_t *caller_data);
+static ftdm_status_t ftdm_call_clear_call_id(ftdm_caller_data_t *caller_data);
+static ftdm_status_t ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan);
+static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan);
static int time_is_init = 0;
@@ -85,6 +97,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;
@@ -111,6 +240,10 @@ static struct {
ftdm_span_t *spans;
ftdm_group_t *groups;
cpu_monitor_t cpu_monitor;
+
+ ftdm_caller_data_t *call_ids[MAX_CALLIDS+1];
+ ftdm_mutex_t *call_id_mutex;
+ uint32_t last_call_id;
} globals;
enum ftdm_enum_cpu_alarm_action_flags
@@ -147,6 +280,27 @@ 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(TRACE_DIR_NAMES, TRACE_DIR_STRINGS)
+FTDM_STR2ENUM(ftdm_str2ftdm_trace_dir, ftdm_trace_dir2str, ftdm_trace_dir_t, TRACE_DIR_NAMES, FTDM_TRACE_INVALID)
+
+FTDM_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 +371,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 +379,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 +387,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 +449,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 +583,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 +1001,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 +1132,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;
@@ -1510,6 +1702,18 @@ static ftdm_status_t __inline__ get_best_rated(ftdm_channel_t **fchan, ftdm_chan
return FTDM_SUCCESS;
}
+
+FT_DECLARE(int) ftdm_channel_get_availability(ftdm_channel_t *ftdmchan)
+{
+ int availability = -1;
+ ftdm_channel_lock(ftdmchan);
+ if (ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_AV_RATE)) {
+ availability = ftdmchan->availability_rate;
+ }
+ ftdm_channel_unlock(ftdmchan);
+ return availability;
+}
+
FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_group(uint32_t group_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan)
{
ftdm_status_t status = FTDM_FAIL;
@@ -1687,45 +1891,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direc
return status;
}
-static ftdm_status_t ftdm_channel_reset(ftdm_channel_t *ftdmchan)
-{
- ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OPEN);
- ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT);
- ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF);
- ftdm_channel_done(ftdmchan);
- ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_HOLD);
-
- memset(ftdmchan->tokens, 0, sizeof(ftdmchan->tokens));
- ftdmchan->token_count = 0;
-
- ftdm_channel_flush_dtmf(ftdmchan);
-
- if (ftdmchan->gen_dtmf_buffer) {
- ftdm_buffer_zero(ftdmchan->gen_dtmf_buffer);
- }
-
- if (ftdmchan->digit_buffer) {
- ftdm_buffer_zero(ftdmchan->digit_buffer);
- }
-
- if (!ftdmchan->dtmf_on) {
- ftdmchan->dtmf_on = FTDM_DEFAULT_DTMF_ON;
- }
-
- if (!ftdmchan->dtmf_off) {
- ftdmchan->dtmf_off = FTDM_DEFAULT_DTMF_OFF;
- }
-
- memset(ftdmchan->dtmf_hangup_buf, '\0', ftdmchan->span->dtmf_hangup_len);
-
- if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE)) {
- ftdmchan->effective_codec = ftdmchan->native_codec;
- ftdmchan->packet_len = ftdmchan->native_interval * (ftdmchan->effective_codec == FTDM_CODEC_SLIN ? 16 : 8);
- ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE);
- }
-
- return FTDM_SUCCESS;
-}
FT_DECLARE(ftdm_status_t) ftdm_channel_init(ftdm_channel_t *ftdmchan)
{
@@ -1745,16 +1910,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)) {
- 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 +1938,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 +2196,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 +2248,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 +2369,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,26 +2389,26 @@ 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);
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_MEDIA);
} else {
- if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) {
- ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1);
- }
+ if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_SKIP_STATES)) {
+ 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;
+ /* 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;
+ }
}
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 +2421,37 @@ 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_reset(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan)
+{
+ ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel");
+
+ ftdm_channel_lock(ftdmchan);
+ ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_RESET, 1);
+ ftdm_channel_unlock(ftdmchan);
+ return FTDM_SUCCESS;
+}
+
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 +2476,9 @@ 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_call_set_call_id(&ftdmchan->caller_data);
ftdm_channel_unlock(ftdmchan);
return status;
@@ -2326,32 +2535,13 @@ 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)
+static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan)
{
ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel can't be done!\n");
-
ftdm_mutex_lock(ftdmchan->mutex);
-
- memset(&ftdmchan->caller_data, 0, sizeof(ftdmchan->caller_data));
-
+ ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OPEN);
+ ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT);
+ ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_INUSE);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_WINK);
@@ -2371,9 +2561,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,17 +2569,67 @@ 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);
+ ftdm_call_clear_call_id(&ftdmchan->caller_data);
+ }
+
+ if (ftdmchan->txdrops || ftdmchan->rxdrops) {
+ ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "channel dropped data: txdrops = %d, rxdrops = %d\n",
+ ftdmchan->txdrops, ftdmchan->rxdrops);
+ }
+
+ memset(&ftdmchan->caller_data, 0, sizeof(ftdmchan->caller_data));
+
+ ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_HOLD);
+
+ memset(ftdmchan->tokens, 0, sizeof(ftdmchan->tokens));
+ ftdmchan->token_count = 0;
+
+ ftdm_channel_flush_dtmf(ftdmchan);
+
+ if (ftdmchan->gen_dtmf_buffer) {
+ ftdm_buffer_zero(ftdmchan->gen_dtmf_buffer);
+ }
+
+ if (ftdmchan->digit_buffer) {
+ ftdm_buffer_zero(ftdmchan->digit_buffer);
+ }
+
+ if (!ftdmchan->dtmf_on) {
+ ftdmchan->dtmf_on = FTDM_DEFAULT_DTMF_ON;
+ }
+
+ if (!ftdmchan->dtmf_off) {
+ ftdmchan->dtmf_off = FTDM_DEFAULT_DTMF_OFF;
+ }
+
+ memset(ftdmchan->dtmf_hangup_buf, '\0', ftdmchan->span->dtmf_hangup_len);
+
+ if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE)) {
+ ftdmchan->effective_codec = ftdmchan->native_codec;
+ ftdmchan->packet_len = ftdmchan->native_interval * (ftdmchan->effective_codec == FTDM_CODEC_SLIN ? 16 : 8);
+ ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE);
+ }
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "channel done\n");
ftdm_mutex_unlock(ftdmchan->mutex);
-
return FTDM_SUCCESS;
}
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);
@@ -2415,8 +2652,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_close(ftdm_channel_t **ftdmchan)
if (ftdm_test_flag(check, FTDM_CHANNEL_OPEN)) {
status = check->fio->close(check);
if (status == FTDM_SUCCESS) {
- ftdm_clear_flag(check, FTDM_CHANNEL_INUSE);
- ftdm_channel_reset(check);
+ ftdm_channel_done(check);
*ftdmchan = NULL;
}
} else {
@@ -2466,8 +2702,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,12 +2730,13 @@ 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;
}
- if ((ftdmchan->fds[FTDM_READ_TRACE_INDEX] = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) > -1) {
+ if ((ftdmchan->fds[FTDM_READ_TRACE_INDEX] = open(path, O_WRONLY | O_CREAT | O_TRUNC
+ | FTDM_O_BINARY, S_IRUSR | S_IWUSR)) > -1) {
ftdm_log(FTDM_LOG_DEBUG, "Tracing channel %u:%u input to [%s]\n", ftdmchan->span_id, ftdmchan->chan_id, path);
GOTO_STATUS(done, FTDM_SUCCESS);
}
@@ -2515,7 +2752,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
close(ftdmchan->fds[FTDM_WRITE_TRACE_INDEX]);
ftdmchan->fds[FTDM_WRITE_TRACE_INDEX] = -1;
}
- if ((ftdmchan->fds[FTDM_WRITE_TRACE_INDEX] = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) > -1) {
+ if ((ftdmchan->fds[FTDM_WRITE_TRACE_INDEX] = open(path, O_WRONLY | O_CREAT | O_TRUNC
+ | FTDM_O_BINARY, S_IRUSR | S_IWUSR)) > -1) {
ftdm_log(FTDM_LOG_DEBUG, "Tracing channel %u:%u output to [%s]\n", ftdmchan->span_id, ftdmchan->chan_id, path);
GOTO_STATUS(done, FTDM_SUCCESS);
}
@@ -2537,6 +2775,136 @@ 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 %"FTDM_SIZE_FMT"\n", size);
+ GOTO_STATUS(done, FTDM_FAIL);
+ }
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Enabled input dump with size %"FTDM_SIZE_FMT"\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 %"FTDM_SIZE_FMT"\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 %"FTDM_SIZE_FMT"\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 %"FTDM_SIZE_FMT"\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 %"FTDM_SIZE_FMT" 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 +3176,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 +3373,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, "wb");
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,23 +3456,33 @@ 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);
+ ftdm_log(FTDM_LOG_WARNING, "Raw output trace failed to write all of the %"FTDM_SIZE_FMT" 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_log(FTDM_LOG_WARNING, "Raw input trace failed to write all of the %zd bytes\n", dlen);
+ ftdm_size_t dlen = *datalen;
+ if ((ftdm_size_t)write(ftdmchan->fds[FTDM_READ_TRACE_INDEX], data, (int)dlen) != dlen) {
+ ftdm_log(FTDM_LOG_WARNING, "Raw input trace failed to write all of the %"FTDM_SIZE_FMT" bytes\n", dlen);
}
}
@@ -3126,48 +3490,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, (int)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 +3639,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 +3850,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 +3858,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 +3896,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 +3912,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 +4069,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 +4234,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 +4333,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 +4369,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]);
}
@@ -3950,6 +4480,11 @@ static ftdm_status_t ftdm_set_channels_alarms(ftdm_span_t *span, int currindex)
ftdm_log(FTDM_LOG_ERROR, "%d:%d: Failed to get alarms\n", span->channels[chan_index]->physical_span_id, span->channels[chan_index]->physical_chan_id);
return FTDM_FAIL;
}
+ if (span->channels[chan_index]->alarm_flags) {
+ ftdm_set_flag_locked(span->channels[chan_index], FTDM_CHANNEL_IN_ALARM);
+ } else {
+ ftdm_clear_flag_locked(span->channels[chan_index], FTDM_CHANNEL_IN_ALARM);
+ }
}
return FTDM_SUCCESS;
}
@@ -3958,6 +4493,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");
@@ -3991,6 +4527,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;
}
@@ -4009,7 +4553,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;
@@ -4046,6 +4590,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;
@@ -4169,11 +4716,14 @@ 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) {
len = FTDM_MAX_NAME_STR_SZ - 1;
- ftdm_log(FTDM_LOG_WARNING, "Truncating group name %s to %zd length\n", val, len);
+ ftdm_log(FTDM_LOG_WARNING, "Truncating group name %s to %"FTDM_SIZE_FMT" length\n", val, len);
}
memcpy(chan_config.group_name, val, len);
chan_config.group_name[len] = '\0';
@@ -4753,15 +5303,18 @@ 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));
+ }
+ ftdm_safe_free(sigmsg->raw_data);
+ return status;
}
static ftdm_status_t ftdm_span_queue_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)
{
ftdm_sigmsg_t *new_sigmsg = NULL;
- ftdm_assert_return((sigmsg->raw_data == NULL), FTDM_FAIL, "No raw data should be used with asynchronous notification\n");
-
new_sigmsg = ftdm_calloc(1, sizeof(*sigmsg));
if (!new_sigmsg) {
return FTDM_FAIL;
@@ -4800,15 +5353,15 @@ static void execute_safety_hangup(void *data)
FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)
{
if (sigmsg->channel) {
- ftdm_mutex_lock(sigmsg->channel->mutex);
+ ftdm_mutex_lock(sigmsg->channel->mutex);
}
-
+
/* some core things to do on special events */
switch (sigmsg->event_id) {
case FTDM_SIGEVENT_SIGSTATUS_CHANGED:
{
- ftdm_signaling_status_t sigstatus = ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE) ? sigmsg->sigstatus : *((ftdm_signaling_status_t*)(sigmsg->raw_data));
+ ftdm_signaling_status_t sigstatus = ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE) ? sigmsg->ev_data.sigstatus.status : *((ftdm_signaling_status_t*)(sigmsg->raw_data));
if (sigstatus == FTDM_SIG_STATE_UP) {
ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_SIG_UP);
} else {
@@ -4819,7 +5372,11 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
case FTDM_SIGEVENT_START:
{
+ ftdm_call_set_call_id(&sigmsg->channel->caller_data);
ftdm_set_echocancel_call_begin(sigmsg->channel);
+ if (sigmsg->channel->dtmfdbg.requested) {
+ ftdm_channel_command(sigmsg->channel, FTDM_COMMAND_ENABLE_DEBUG_DTMF, NULL);
+ }
/* 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
@@ -4845,7 +5402,10 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
break;
}
-
+
+ if (sigmsg->channel) {
+ sigmsg->call_id = sigmsg->channel->caller_data.call_id;
+ }
/* if the signaling module uses a queue for signaling notifications, then enqueue it */
if (ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE)) {
ftdm_span_queue_signal(span, sigmsg);
@@ -4854,6 +5414,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);
}
@@ -4953,6 +5514,8 @@ FT_DECLARE(ftdm_status_t) ftdm_global_init(void)
ftdm_mutex_create(&globals.mutex);
ftdm_mutex_create(&globals.span_mutex);
ftdm_mutex_create(&globals.group_mutex);
+ ftdm_mutex_create(&globals.call_id_mutex);
+
ftdm_sched_global_init();
if (ftdm_sched_create(&globals.timingsched, "freetdm-master") != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed to create master timing schedule context\n");
@@ -4962,6 +5525,7 @@ FT_DECLARE(ftdm_status_t) ftdm_global_init(void)
ftdm_log(FTDM_LOG_CRIT, "Failed to run master timing schedule context\n");
return FTDM_FAIL;
}
+
globals.running = 1;
return FTDM_SUCCESS;
}
@@ -5065,6 +5629,7 @@ FT_DECLARE(ftdm_status_t) ftdm_global_destroy(void)
ftdm_mutex_destroy(&globals.mutex);
ftdm_mutex_destroy(&globals.span_mutex);
ftdm_mutex_destroy(&globals.group_mutex);
+ ftdm_mutex_destroy(&globals.call_id_mutex);
memset(&globals, 0, sizeof(globals));
return FTDM_SUCCESS;
@@ -5423,6 +5988,47 @@ FT_DECLARE(char *) ftdm_channel_get_history_str(const ftdm_channel_t *fchan)
return stream.data;
}
+static ftdm_status_t ftdm_call_set_call_id(ftdm_caller_data_t *caller_data)
+{
+ uint32_t current_call_id;
+ ftdm_assert_return(!caller_data->call_id, FTDM_FAIL, "Overwriting non-cleared call-id");
+
+ ftdm_mutex_lock(globals.call_id_mutex);
+ current_call_id = globals.last_call_id;
+
+ do {
+ if (++current_call_id > MAX_CALLIDS) {
+ current_call_id = 1;
+ }
+ if (globals.call_ids[current_call_id] != NULL) {
+ continue;
+ }
+ } while (0);
+
+ globals.last_call_id = current_call_id;
+ caller_data->call_id = current_call_id;
+
+ globals.call_ids[current_call_id] = caller_data;
+ ftdm_mutex_unlock(globals.call_id_mutex);
+ return FTDM_SUCCESS;
+}
+
+static ftdm_status_t ftdm_call_clear_call_id(ftdm_caller_data_t *caller_data)
+{
+ ftdm_assert_return((caller_data->call_id && caller_data->call_id <= MAX_CALLIDS), FTDM_FAIL, "Clearing call with invalid call-id\n");
+ ftdm_mutex_lock(globals.call_id_mutex);
+ if (globals.call_ids[caller_data->call_id]) {
+ caller_data->call_id = 0;
+ globals.call_ids[caller_data->call_id] = NULL;
+ } else {
+ ftdm_log(FTDM_LOG_CRIT, "call-id did not exist %u\n", caller_data->call_id);
+ }
+ ftdm_mutex_unlock(globals.call_id_mutex);
+ return FTDM_SUCCESS;
+}
+
+
+
/* For Emacs:
* Local Variables:
diff --git a/libs/freetdm/src/ftdm_m3ua.c b/libs/freetdm/src/ftdm_m3ua.c
index 31f4cd5c5e..8d3e00213a 100644
--- a/libs/freetdm/src/ftdm_m3ua.c
+++ b/libs/freetdm/src/ftdm_m3ua.c
@@ -156,7 +156,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
release_request_id((m3ua_request_id_t)ftdmchan->extra_id);
ftdmchan->extra_id = 0;
}
- ftdm_channel_done(ftdmchan);
+ ftdm_channel_close(&ftdmchan);
}
break;
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
@@ -484,7 +484,7 @@ static FIO_SPAN_NEXT_EVENT_FUNCTION(m3ua_next_event)
static FIO_SPAN_DESTROY_FUNCTION(m3ua_span_destroy)
{
- m3ua_span_data_t *span_data = (m3ua_span_data_t *) span->mod_data;
+ m3ua_span_data_t *span_data = (m3ua_span_data_t *) span->io_data;
if (span_data) {
ftdm_safe_free(span_data);
@@ -494,8 +494,8 @@ static FIO_SPAN_DESTROY_FUNCTION(m3ua_span_destroy)
}
static FIO_CHANNEL_DESTROY_FUNCTION(m3ua_channel_destroy)
{
- m3ua_chan_data_t *chan_data = (m3ua_chan_data_t *) ftdmchan->mod_data;
- m3ua_span_data_t *span_data = (m3ua_span_data_t *) ftdmchan->span->mod_data;
+ m3ua_chan_data_t *chan_data = (m3ua_chan_data_t *) ftdmchan->io_data;
+ m3ua_span_data_t *span_data = (m3ua_span_data_t *) ftdmchan->span->io_data;
if (!chan_data) {
return FTDM_FAIL;
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 d54d46ad99..5b4ce7196a 100644
--- a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c
+++ b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c
@@ -48,7 +48,6 @@
#define LINE "--------------------------------------------------------------------------------"
/* helper macros */
-#define FTDM_SPAN_IS_BRI(x) ((x)->trunk_type == FTDM_TRUNK_BRI || (x)->trunk_type == FTDM_TRUNK_BRI_PTMP)
#define FTDM_SPAN_IS_NT(x) (((ftdm_isdn_data_t *)(x)->signal_data)->mode == Q921_NT)
#define DEFAULT_NATIONAL_PREFIX "0"
@@ -1081,8 +1080,8 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
isdn_data->channels_remote_crv[gen->CRV] = ftdmchan;
memset(&ftdmchan->caller_data, 0, sizeof(ftdmchan->caller_data));
- if (ftdmchan->mod_data) {
- memset(ftdmchan->mod_data, 0, sizeof(ftdm_isdn_bchan_data_t));
+ if (ftdmchan->call_data) {
+ memset(ftdmchan->call_data, 0, sizeof(ftdm_isdn_bchan_data_t));
}
/* copy number readd prefix as needed */
@@ -1214,7 +1213,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
* overlap dial digit indication
*/
if (Q931IsIEPresent(gen->CalledNum)) {
- ftdm_isdn_bchan_data_t *data = (ftdm_isdn_bchan_data_t *)ftdmchan->mod_data;
+ ftdm_isdn_bchan_data_t *data = (ftdm_isdn_bchan_data_t *)ftdmchan->call_data;
Q931ie_CalledNum *callednum = Q931GetIEPtr(gen->CalledNum, gen->buf);
int pos;
@@ -1326,7 +1325,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
}
Q931ReleaseCRV(&isdn_data->q931, gen->CRV);
}
- ftdm_channel_done(ftdmchan);
+ ftdm_channel_close(&ftdmchan);
}
break;
case FTDM_CHANNEL_STATE_PROGRESS:
@@ -1370,7 +1369,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
break;
case FTDM_CHANNEL_STATE_DIALTONE:
{
- ftdm_isdn_bchan_data_t *data = (ftdm_isdn_bchan_data_t *)ftdmchan->mod_data;
+ ftdm_isdn_bchan_data_t *data = (ftdm_isdn_bchan_data_t *)ftdmchan->call_data;
if (data) {
data->digit_timeout = ftdm_time_now() + isdn_data->digit_timeout;
@@ -1862,7 +1861,7 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj)
switch (ftdm_channel_get_state(chan)) {
case FTDM_CHANNEL_STATE_DIALTONE:
{
- ftdm_isdn_bchan_data_t *data = (ftdm_isdn_bchan_data_t *)chan->mod_data;
+ ftdm_isdn_bchan_data_t *data = (ftdm_isdn_bchan_data_t *)chan->call_data;
ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
/* check overlap dial timeout first before generating tone */
@@ -2741,7 +2740,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(isdn_configure_span)
ftdm_channel_t *chan = ftdm_span_get_channel(span, i);
if (ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_B) {
- chan->mod_data = data;
+ chan->call_data = data;
memset(data, 0, sizeof(ftdm_isdn_bchan_data_t));
}
}
diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c
index 669e85218a..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)
{
@@ -536,6 +537,8 @@ static __inline__ void state_advance(ftdm_channel_t *chan)
break;
case FTDM_CHANNEL_STATE_PROGRESS:
+ /* RINGING is an alias for PROGRESS state in inbound calls ATM */
+ case FTDM_CHANNEL_STATE_RINGING:
{
if (ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) {
sig.event_id = FTDM_SIGEVENT_PROGRESS;
@@ -727,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);
}
}
}
@@ -991,7 +992,16 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event
if (!chan) {
ftdm_log(FTDM_LOG_ERROR, "-- Unable to get channel %d:%d\n", ftdm_span_get_id(span), pevent->ring.channel);
- goto done;
+ 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)) {
@@ -1051,9 +1061,10 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event
/* 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;
}
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_pika/ftmod_pika.c b/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.c
index f20cbc53a7..aaafdb33cc 100644
--- a/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.c
+++ b/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.c
@@ -266,7 +266,7 @@ PK_VOID PK_CALLBACK media_out_callback(PKH_TPikaEvent *event)
{
PK_STATUS pk_status;
ftdm_channel_t *ftdmchan = event->userData;
- pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->mod_data;
+ pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data;
//PK_CHAR event_text[PKH_EVENT_MAX_NAME_LENGTH];
//PKH_EVENT_GetText(event->id, event_text, sizeof(event_text));
@@ -345,8 +345,8 @@ static unsigned pika_open_range(ftdm_span_t *span, unsigned boardno, unsigned sp
}
- if (span->mod_data) {
- span_data = span->mod_data;
+ if (span->io_data) {
+ span_data = span->io_data;
} else {
span_data = ftdm_malloc(sizeof(*span_data));
assert(span_data != NULL);
@@ -364,7 +364,7 @@ static unsigned pika_open_range(ftdm_span_t *span, unsigned boardno, unsigned sp
//PKH_QUEUE_Attach(span_data->event_queue, globals.open_boards[boardno], NULL);
- span->mod_data = span_data;
+ span->io_data = span_data;
}
if (type == FTDM_CHAN_TYPE_FXS || type == FTDM_CHAN_TYPE_FXO) {
@@ -380,7 +380,7 @@ static unsigned pika_open_range(ftdm_span_t *span, unsigned boardno, unsigned sp
assert(chan_data);
memset(chan_data, 0, sizeof(*chan_data));
ftdm_span_add_channel(span, 0, type, &chan);
- chan->mod_data = chan_data;
+ chan->io_data = chan_data;
if ((type == FTDM_CHAN_TYPE_B || type == FTDM_CHAN_TYPE_DQ921) && !span_data->handle) {
PKH_TBoardConfig boardConfig;
@@ -680,7 +680,7 @@ static FIO_CONFIGURE_SPAN_FUNCTION(pika_configure_span)
*/
static FIO_OPEN_FUNCTION(pika_open)
{
- pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->mod_data;
+ pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data;
if (!chan_data && !ftdm_test_flag(chan_data, PK_FLAG_READY)) {
return FTDM_FAIL;
@@ -715,7 +715,7 @@ static FIO_CLOSE_FUNCTION(pika_close)
*/
static FIO_WAIT_FUNCTION(pika_wait)
{
- pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->mod_data;
+ pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data;
PK_STATUS status;
ftdm_wait_flag_t myflags = *flags;
PK_CHAR event_text[PKH_EVENT_MAX_NAME_LENGTH];
@@ -754,7 +754,7 @@ static FIO_WAIT_FUNCTION(pika_wait)
*/
static FIO_READ_FUNCTION(pika_read)
{
- pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->mod_data;
+ pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data;
PK_STATUS status;
PK_CHAR event_text[PKH_EVENT_MAX_NAME_LENGTH];
uint32_t len;
@@ -795,7 +795,7 @@ static FIO_READ_FUNCTION(pika_read)
*/
static FIO_WRITE_FUNCTION(pika_write)
{
- pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->mod_data;
+ pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data;
PK_STATUS status;
if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) {
@@ -821,8 +821,8 @@ static FIO_WRITE_FUNCTION(pika_write)
*/
static FIO_COMMAND_FUNCTION(pika_command)
{
- pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->mod_data;
- //pika_span_data_t *span_data = (pika_span_data_t *) ftdmchan->span->mod_data;
+ pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data;
+ //pika_span_data_t *span_data = (pika_span_data_t *) ftdmchan->span->io_data;
PK_STATUS pk_status;
ftdm_status_t status = FTDM_SUCCESS;
@@ -956,7 +956,7 @@ static FIO_COMMAND_FUNCTION(pika_command)
*/
static FIO_SPAN_POLL_EVENT_FUNCTION(pika_poll_event)
{
- pika_span_data_t *span_data = (pika_span_data_t *) span->mod_data;
+ pika_span_data_t *span_data = (pika_span_data_t *) span->io_data;
PK_STATUS status;
PK_CHAR event_text[PKH_EVENT_MAX_NAME_LENGTH];
@@ -1025,7 +1025,7 @@ static FIO_SPAN_POLL_EVENT_FUNCTION(pika_poll_event)
for(x = 1; x <= span->chan_count; x++) {
ftdmchan = span->channels[x];
assert(ftdmchan != NULL);
- chan_data = (pika_chan_data_t *) ftdmchan->mod_data;
+ chan_data = (pika_chan_data_t *) ftdmchan->io_data;
assert(chan_data != NULL);
@@ -1042,7 +1042,7 @@ static FIO_SPAN_POLL_EVENT_FUNCTION(pika_poll_event)
//ftdm_log(FTDM_LOG_DEBUG, "Event: %s\n", event_text);
if (ftdmchan) {
- pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->mod_data;
+ pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data;
assert(chan_data != NULL);
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_EVENT);
@@ -1068,7 +1068,7 @@ static FIO_SPAN_NEXT_EVENT_FUNCTION(pika_next_event)
for(i = 1; i <= span->chan_count; i++) {
if (ftdm_test_flag(span->channels[i], FTDM_CHANNEL_EVENT)) {
- pika_chan_data_t *chan_data = (pika_chan_data_t *) span->channels[i]->mod_data;
+ pika_chan_data_t *chan_data = (pika_chan_data_t *) span->channels[i]->io_data;
PK_CHAR event_text[PKH_EVENT_MAX_NAME_LENGTH];
ftdm_clear_flag(span->channels[i], FTDM_CHANNEL_EVENT);
@@ -1207,7 +1207,7 @@ static FIO_SPAN_NEXT_EVENT_FUNCTION(pika_next_event)
*/
static FIO_SPAN_DESTROY_FUNCTION(pika_span_destroy)
{
- pika_span_data_t *span_data = (pika_span_data_t *) span->mod_data;
+ pika_span_data_t *span_data = (pika_span_data_t *) span->io_data;
if (span_data) {
PKH_QUEUE_Destroy(span_data->event_queue);
@@ -1224,8 +1224,8 @@ static FIO_SPAN_DESTROY_FUNCTION(pika_span_destroy)
*/
static FIO_CHANNEL_DESTROY_FUNCTION(pika_channel_destroy)
{
- pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->mod_data;
- pika_span_data_t *span_data = (pika_span_data_t *) ftdmchan->span->mod_data;
+ pika_chan_data_t *chan_data = (pika_chan_data_t *) ftdmchan->io_data;
+ pika_span_data_t *span_data = (pika_span_data_t *) ftdmchan->span->io_data;
if (!chan_data) {
return FTDM_FAIL;
diff --git a/libs/freetdm/src/ftmod/ftmod_pritap/ftmod_pritap.c b/libs/freetdm/src/ftmod/ftmod_pritap/ftmod_pritap.c
index 220a96515b..27fbe2139f 100644
--- a/libs/freetdm/src/ftmod/ftmod_pritap/ftmod_pritap.c
+++ b/libs/freetdm/src/ftmod/ftmod_pritap/ftmod_pritap.c
@@ -280,12 +280,12 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_DOWN:
- {
- ftdm_channel_done(ftdmchan);
+ {
ftdmchan->call_data = NULL;
+ ftdm_channel_close(&ftdmchan);
- ftdm_channel_done(peerchan);
peerchan->call_data = NULL;
+ ftdm_channel_close(&peerchan);
}
break;
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 086656128e..14eca429e8 100644
--- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
+++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
@@ -29,13 +29,22 @@
* 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
+ *
*/
-#include
#ifdef __linux__
+#ifndef _BSD_SOURCE
+#define _BSD_SOURCE /* for strsep() */
+#endif
#include
#include
+#include
#endif
+#include
#include
#include "freetdm.h"
#include "private/ftdm_core.h"
@@ -46,32 +55,33 @@ static int32_t g_thread_count = 0;
typedef int openr2_call_status_t;
-/* when the users kills a span we clear this flag to kill the signaling thread */
+/* when the user stops a span, we clear FTDM_R2_SPAN_STARTED, so that the signaling thread
+ * knows it must stop, and we wait for FTDM_R2_RUNNING to be clear, which tells us the
+ * signaling thread is done. */
/* FIXME: what about the calls that are already up-and-running? */
typedef enum {
FTDM_R2_RUNNING = (1 << 0),
+ FTDM_R2_SPAN_STARTED = (1 << 1),
} 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 */
@@ -90,13 +100,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;
@@ -119,12 +129,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
@@ -132,6 +156,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 */
@@ -147,7 +172,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
@@ -216,6 +248,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.ev_data.sigstatus.status = 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) {
@@ -275,6 +324,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:
@@ -292,9 +342,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)
@@ -334,42 +396,45 @@ 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)
{
ftdm_r2_data_t *r2_data = span->signal_data;
- ftdm_set_flag(r2_data, FTDM_R2_RUNNING);
+ ftdm_set_flag(r2_data, FTDM_R2_SPAN_STARTED);
return ftdm_thread_create_detached(ftdm_r2_run, span);
}
static ftdm_status_t ftdm_r2_stop(ftdm_span_t *span)
{
ftdm_r2_data_t *r2_data = span->signal_data;
+ ftdm_clear_flag(r2_data, FTDM_R2_SPAN_STARTED);
while (ftdm_test_flag(r2_data, FTDM_R2_RUNNING)) {
ftdm_log(FTDM_LOG_DEBUG, "Waiting for R2 span %s\n", span->name);
ftdm_sleep(100);
@@ -377,44 +442,132 @@ 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)
+{
+ if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
+ *status = FTDM_SIG_STATE_UP;
+ } else {
+ *status = FTDM_SIG_STATE_DOWN;
+ }
+
+ return FTDM_SUCCESS;
+}
+
+static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_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);
+ switch(status) {
+ case FTDM_SIG_STATE_DOWN:
+ case FTDM_SIG_STATE_SUSPENDED:
+ openr2_chan_set_blocked(r2chan);
+ break;
+ case FTDM_SIG_STATE_UP:
+ openr2_chan_set_idle(r2chan);
+ break;
+ default:
+ ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%d'\n", status);
+ return FTDM_FAIL;
}
+ ftdm_r2_set_chan_sig_status(ftdmchan, status);
+ return FTDM_SUCCESS;
+}
+
+static FIO_SPAN_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_span_sig_status)
+{
+ ftdm_iterator_t *citer = NULL;
+ ftdm_iterator_t *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);
+ return FTDM_FAIL;
+ }
+ /* if ALL channels are non-idle, report SUSPENDED. UP otherwise. */
+ *status = FTDM_SIG_STATE_SUSPENDED;
+ for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) {
+ ftdm_channel_t *fchan = ftdm_iterator_current(citer);
+ if (ftdm_test_flag(fchan, FTDM_CHANNEL_SIG_UP)) {
+ *status = FTDM_SIG_STATE_UP;
+ break;
+ }
+ }
+ ftdm_iterator_free(chaniter);
+ return FTDM_SUCCESS;
+}
+
+static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_span_sig_status)
+{
+ ftdm_iterator_t *chaniter = NULL;
+ ftdm_iterator_t *citer = NULL;
+ uint32_t span_opr = -1;
+
+ /* we either set the channels to BLOCK or IDLE */
+ switch(status) {
+ case FTDM_SIG_STATE_DOWN:
+ case FTDM_SIG_STATE_SUSPENDED:
+ span_opr = 0;
+ break;
+ case FTDM_SIG_STATE_UP:
+ span_opr = 1;
+ break;
+ default:
+ ftdm_log(FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%d'\n", status);
+ return FTDM_FAIL;
+ }
+
+ 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);
+ return FTDM_FAIL;
+ }
+ /* iterate over all channels, setting them to the requested state */
+ for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) {
+ ftdm_channel_t *fchan = ftdm_iterator_current(citer);
+ openr2_chan_t *r2chan = R2CALL(fchan)->r2chan;
+ if (span_opr == 0) {
+ openr2_chan_set_blocked(r2chan);
+ ftdm_log_chan_msg(fchan, FTDM_LOG_NOTICE, "Channel blocked\n");
+ } else {
+ openr2_chan_set_idle(r2chan);
+ ftdm_log_chan_msg(fchan, FTDM_LOG_NOTICE, "Channel idle\n");
+ }
+ ftdm_r2_set_chan_sig_status(fchan, status);
+ }
+ ftdm_iterator_free(chaniter);
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;
}
@@ -424,46 +577,130 @@ 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, "wb");
+ ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO input in file %s\n", dfile);
+ ftdm_channel_command(ftdmchan, FTDM_COMMAND_DUMP_INPUT, f);
+ fclose(f);
+
+ snprintf(dfile, sizeof(dfile), logname ? "%s.s%dc%d.output.alaw" : "%s/s%dc%d.output.alaw",
+ logname ? logname : r2data->logdir, ftdmchan->span_id, ftdmchan->chan_id);
+ f = fopen(dfile, "wb");
+ ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO output in file %s\n", dfile);
+ ftdm_channel_command(ftdmchan, FTDM_COMMAND_DUMP_OUTPUT, f);
+ fclose(f);
+ }
}
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_r2_data_t *r2data = ftdmchan->span->signal_data;
+
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);
+ /* 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);
+ }
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
}
}
@@ -473,47 +710,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)
@@ -522,10 +742,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)
@@ -538,7 +758,7 @@ static void ftdm_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf
static void ftdm_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
{
ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
- ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Alarm notification: %d\n", alarm);
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Alarm notification: %d\n", alarm);
}
static void ftdm_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
@@ -547,59 +767,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)
@@ -644,14 +864,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)
@@ -709,6 +928,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,
@@ -729,7 +958,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)
@@ -770,7 +1000,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)
@@ -781,7 +1011,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)
@@ -790,7 +1020,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) {
@@ -803,9 +1033,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;
}
@@ -849,8 +1080,40 @@ 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;
+ }
+
+ if (fevent->e_type != FTDM_EVENT_OOB) {
+ return 0;
+ }
+
+ 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;
}
@@ -867,53 +1130,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;
- 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,
+#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,
- /* .allow_collect_calls */ -1,
+ /* .mf_dump_size */ 0,
/* .immediate_accept */ -1,
/* .skip_category */ -1,
- /* .forced_release */ -1,
- /* .charge_calls */ -1,
/* .get_ani_first */ -1,
/* .call_files */ 0,
- /* .mf_files */ 0,
- /* .logdir */ NULL,
- /* .advanced_protocol_file */ NULL
+ /* .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)) {
@@ -928,7 +1320,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)) {
@@ -943,97 +1335,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");
- /*
- * TODO: investigate this
- *
- * despite the fact advanced_protocol_file was initialized as NULL, it's now a bad
- * pointer - hence, this workaround.
- * this seems to happen only on windows.
- *
- */
- r2conf.advanced_protocol_file = NULL;
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;
@@ -1045,6 +1420,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.");
@@ -1073,10 +1452,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);
}
@@ -1088,7 +1467,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;
@@ -1096,11 +1475,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));
@@ -1117,8 +1491,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;
@@ -1127,12 +1502,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;
span->signal_cb = sig_cb;
span->signal_type = FTDM_SIGTYPE_R2;
span->signal_data = r2data;
span->outgoing_call = r2_outgoing_call;
+ span->get_span_sig_status = ftdm_r2_get_span_sig_status;
+ span->set_span_sig_status = ftdm_r2_set_span_sig_status;
+ span->get_channel_sig_status = ftdm_r2_get_channel_sig_status;
+ span->set_channel_sig_status = ftdm_r2_set_channel_sig_status;
+
+ 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;
@@ -1155,7 +1545,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;
@@ -1164,25 +1556,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);
@@ -1198,6 +1592,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;
@@ -1209,6 +1604,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;
@@ -1218,13 +1614,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;
@@ -1233,16 +1624,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;
@@ -1252,60 +1644,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));
@@ -1324,19 +1728,40 @@ 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);
+
+ /* as long as this thread is running, this flag is set */
+ ftdm_set_flag(r2data, FTDM_R2_RUNNING);
#ifdef __linux__
r2data->monitor_thread_id = syscall(SYS_gettid);
@@ -1344,39 +1769,68 @@ 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++;
+ while (ftdm_running() && ftdm_test_flag(r2data, FTDM_R2_SPAN_STARTED)) {
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++;
}
-#ifndef WIN32
+ /* 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);
+
/* 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] = FTDM_EVENTS;
+ if (openr2_chan_get_read_enabled(r2chan)) {
+ poll_events[i] |= FTDM_READ;
+ }
}
-
status = ftdm_span_poll_event(span, waitms, poll_events);
-#else
- status = ftdm_span_poll_event(span, waitms, NULL);
-#endif
+
+ /* run any span timers */
+ ftdm_sched_run(r2data->sched);
res = gettimeofday(&start, NULL);
if (res) {
@@ -1388,69 +1842,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");
@@ -1506,8 +1953,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;
@@ -1590,7 +2037,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;
@@ -1601,36 +2048,25 @@ static FIO_API_FUNCTION(ftdm_r2_api)
"Max DNIS: %d\n"
"ANI First: %s\n"
"Immediate Accept: %s\n"
- "Side: %s\n"
+ "Job Thread: %u\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 %6s %6s %6s %6s\n", "Channel", "Tx CAS", "Rx CAS",
- "Rx Avg", "Tx Avg", "Rx", "Tx");
+ stream->write_function(stream, "%4s %-12.12s %-12.12s\n", "Channel", "Tx CAS", "Rx CAS");
for (i = 1; i <= span->chan_count; i++) {
- char rx_str[25];
- char tx_str[25];
- char rxavg_str[25];
- char txavg_str[25];
r2chan = R2CALL(span->channels[i])->r2chan;
- stream->write_function(stream, "%4d %-12.12s %-12.12s %6s %6s %6s %6s\n",
+ stream->write_function(stream, "%4d %-12.12s %-12.12s\n",
span->channels[i]->chan_id,
openr2_chan_get_tx_cas_string(r2chan),
- openr2_chan_get_rx_cas_string(r2chan),
- rxavg_str,
- txavg_str,
- rx_str,
- tx_str);
+ openr2_chan_get_rx_cas_string(r2chan));
}
stream->write_function(stream, "\n");
stream->write_function(stream, "+OK.\n");
@@ -1641,6 +2077,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) {
@@ -1722,6 +2208,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);
@@ -1730,12 +2217,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..f59b3b8c4f 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];
@@ -839,7 +839,7 @@ static void handle_call_released(ftdm_span_t *span, sangomabc_connection_t *mcon
if ((ftdmchan = find_ftdmchan(span, event, 1))) {
ftdm_log(FTDM_LOG_DEBUG, "Releasing completely chan s%dc%d\n", BOOST_EVENT_SPAN(mcon->sigmod, event),
BOOST_EVENT_CHAN(mcon->sigmod, event));
- ftdm_channel_done(ftdmchan);
+ ftdm_channel_close(&ftdmchan);
} else {
ftdm_log(FTDM_LOG_CRIT, "Odd, We could not find chan: s%dc%d to release the call completely!!\n",
BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
@@ -1105,8 +1105,9 @@ static void handle_call_loop_start(ftdm_span_t *span, sangomabc_connection_t *mc
ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP, res);
if (res != FTDM_SUCCESS) {
+ ftdm_channel_t *toclose = ftdmchan;
ftdm_log(FTDM_LOG_CRIT, "yay, could not set the state of the channel to IN_LOOP, loop will fail\n");
- ftdm_channel_done(ftdmchan);
+ ftdm_channel_close(&toclose);
return;
}
ftdm_log(FTDM_LOG_DEBUG, "%d:%d starting loop\n", ftdmchan->span_id, ftdmchan->chan_id);
@@ -1426,11 +1427,12 @@ static __inline__ ftdm_status_t state_advance(ftdm_channel_t *ftdmchan)
ftdmchan->sflags = 0;
memset(ftdmchan->call_data, 0, sizeof(sangoma_boost_call_t));
if (sangoma_boost_data->sigmod && call_stopped_ack_sent) {
- /* we dont want to call ftdm_channel_done just yet until call released is received */
+ /* we dont want to call ftdm_channel_close just yet until call released is received */
ftdm_log(FTDM_LOG_DEBUG, "Waiting for call release confirmation before declaring chan %d:%d as available \n",
ftdmchan->span_id, ftdmchan->chan_id);
} else {
- ftdm_channel_done(ftdmchan);
+ ftdm_channel_t *toclose = ftdmchan;
+ ftdm_channel_close(&toclose);
}
}
break;
@@ -1557,11 +1559,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 +2584,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 a7656267f2..bb29b4f4a5 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,21 +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 = {
{
@@ -62,7 +65,13 @@ ftdm_state_map_t sangoma_isdn_state_map = {
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_ANY_STATE, FTDM_END},
- {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END}
+ {FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_RESTART, FTDM_END}
+ },
+ {
+ ZSD_INBOUND,
+ ZSM_UNACCEPTABLE,
+ {FTDM_CHANNEL_STATE_RESET, FTDM_END},
+ {FTDM_CHANNEL_STATE_DOWN, FTDM_END}
},
{
ZSD_INBOUND,
@@ -112,7 +121,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,
@@ -154,7 +176,13 @@ ftdm_state_map_t sangoma_isdn_state_map = {
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{FTDM_ANY_STATE, FTDM_END},
- {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
+ {FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
+ },
+ {
+ ZSD_OUTBOUND,
+ ZSM_UNACCEPTABLE,
+ {FTDM_CHANNEL_STATE_RESET, FTDM_END},
+ {FTDM_CHANNEL_STATE_DOWN, FTDM_END}
},
{
ZSD_OUTBOUND,
@@ -186,8 +214,16 @@ 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_RINGING, 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_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
},
{
ZSD_OUTBOUND,
@@ -195,6 +231,12 @@ ftdm_state_map_t sangoma_isdn_state_map = {
{FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
},
+ {
+ ZSD_OUTBOUND,
+ ZSM_UNACCEPTABLE,
+ {FTDM_CHANNEL_STATE_RINGING, FTDM_END},
+ {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
+ },
{
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
@@ -235,9 +277,139 @@ 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;
+
+ 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) {
+ ftdm_sangoma_isdn_process_phy_events(span, event->enum_id);
+ }
+ }
+ break;
+ case FTDM_TIMEOUT:
+ /* No events pending */
+ break;
+ default:
+ ftdm_log(FTDM_LOG_WARNING, "%s:Failed to poll span event\n", span->name);
+ }
+}
+
+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;
@@ -255,8 +427,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;
}
@@ -265,8 +442,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 */
@@ -282,7 +465,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 */
@@ -297,26 +479,7 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
}
/* Poll for events, e.g HW DTMF */
- 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);
- }
- break;
- case FTDM_TIMEOUT:
- /* No events pending */
- break;
- default:
- ftdm_log(FTDM_LOG_WARNING, "%s:Failed to poll span event\n", span->name);
- }
-
- 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;
- }
- }
+ ftdm_sangoma_isdn_poll_events(span);
}
/* clear the IN_THREAD flag so that we know the thread is done */
@@ -480,13 +643,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*/
@@ -495,8 +663,52 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
}
break;
case FTDM_CHANNEL_STATE_DIALING: /* outgoing call request */
+ {
+ if (FTDM_SPAN_IS_BRI(ftdmchan->span) &&
+ ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM) &&
+ ftdm_test_flag(ftdmchan->span, FTDM_SPAN_PWR_SAVING)) {
+
+ 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);
+ 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:
{
- sngisdn_snd_setup(ftdmchan);
+ 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:
+ {
+ if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
+ /* OUTBOUND...so we were told by the line of this so notify the user */
+ sigev.event_id = FTDM_SIGEVENT_RINGING;
+ ftdm_span_send_signal(ftdmchan->span, &sigev);
+ if (sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY)) {
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
+ }
+ } else {
+ 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:
@@ -506,9 +718,10 @@ 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 {
+ /* 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;
@@ -518,7 +731,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;
@@ -589,7 +804,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_span_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
}
} else {
sngisdn_snd_disconnect(ftdmchan);
@@ -614,9 +829,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);
@@ -649,6 +862,11 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
/* IMPLEMENT ME */
}
break;
+ case FTDM_CHANNEL_STATE_RESET:
+ {
+ sngisdn_snd_restart(ftdmchan);
+ }
+ break;
default:
{
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "unsupported sngisdn_rcvd state %s\n", ftdm_channel_state2str(ftdmchan->state));
@@ -668,6 +886,22 @@ 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_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;
@@ -742,9 +976,10 @@ 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)
-{
+{
+ sngisdn_span_data_t *signal_data = span->signal_data;
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;
}
@@ -752,12 +987,26 @@ static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
ftdm_clear_flag(span, FTDM_SPAN_STOP_THREAD);
ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
+ if (signal_data->raw_trace_q921 == SNGISDN_OPT_TRUE) {
+ sngisdn_activate_trace(span, SNGISDN_TRACE_Q921);
+ }
+
+ if (signal_data->raw_trace_q931 == SNGISDN_OPT_TRUE) {
+ sngisdn_activate_trace(span, SNGISDN_TRACE_Q931);
+ }
+
/*start the span monitor thread*/
if (ftdm_thread_create_detached(ftdm_sangoma_isdn_run, span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT,"Failed to start Sangoma ISDN Span Monitor Thread!\n");
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;
}
@@ -779,7 +1028,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);
}
@@ -831,7 +1080,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;
}
@@ -841,6 +1090,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;
@@ -850,12 +1100,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) {
-
- ftdm_set_flag(span, FTDM_SPAN_USE_AV_RATE);
- sng_isdn_set_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING);
+
+ sngisdn_set_span_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING);
}
/* Initialize scheduling context */
@@ -874,7 +1125,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;
@@ -903,15 +1154,18 @@ 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);
}
/* initalize sng_isdn library */
- ftdm_assert_return(!sng_isdn_init(&g_sngisdn_event_interface), FTDM_FAIL, "Failed to initialize stack\n");
+ ftdm_assert_return(!sng_isdn_init(&g_sngisdn_event_interface), FTDM_FAIL, "Failed to initialize stack\n");
return FTDM_SUCCESS;
}
@@ -947,6 +1201,7 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
goto done;
}
+ /* TODO: Move functions to table + function pointers */
if (!strcasecmp(argv[0], "trace")) {
char *trace_opt;
@@ -964,15 +1219,16 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
stream->write_function(stream, "-ERR failed to find span by name %s\n", argv[2]);
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");
- }
+ }
}
if (!strcasecmp(argv[0], "l1_stats")) {
ftdm_span_t *span;
@@ -990,7 +1246,7 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
}
sngisdn_print_phy_stats(stream, span);
}
-
+
if (!strcasecmp(argv[0], "show_spans")) {
ftdm_span_t *span = NULL;
if (argc == 2) {
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 336ffe9538..6a440e4f66 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),
@@ -73,7 +101,11 @@ typedef enum {
FLAG_GLARE = (1 << 6),
FLAG_DELAYED_REL = (1 << 7),
FLAG_SENT_PROCEED = (1 << 8),
- FLAG_SEND_DISC = (1 << 9),
+ FLAG_SEND_DISC = (1 << 9),
+ /* Used for BRI only, flag is set after we request line CONNECTED */
+ FLAG_ACTIVATING = (1 << 10),
+ /* Used when we receive an ALERT msg + inband tones ready */
+ FLAG_MEDIA_READY = (1 << 11),
} sngisdn_flag_t;
@@ -133,6 +165,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 */
@@ -167,6 +244,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 */
@@ -178,9 +256,15 @@ 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 raw_trace_q931;
+ uint8_t raw_trace_q921;
+ uint8_t timer_t3;
+ uint8_t restart_opt;
char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS];
ftdm_sched_t *sched;
ftdm_queue_t *event_queue;
@@ -266,60 +350,62 @@ 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_span_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail);
+ftdm_status_t sngisdn_set_chan_avail_rate(ftdm_channel_t *chan, sngisdn_avail_t avail);
+void sngisdn_set_span_sig_status(ftdm_span_t *ftdmspan, ftdm_signaling_status_t status);
+void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status);
+
+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_restart(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);
@@ -343,8 +429,11 @@ void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event);
void sngisdn_rcv_phy_ind(SuId suId, Reason reason);
void sngisdn_rcv_q921_ind(BdMngmt *status);
-void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len);
-void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len);
+void sngisdn_trace_interpreted_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len);
+void sngisdn_trace_interpreted_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len);
+void sngisdn_trace_raw_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len);
+void sngisdn_trace_raw_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len);
+
void get_memory_info(void);
ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt);
@@ -357,6 +446,31 @@ 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_bear_cap_ie(ftdm_channel_t *ftdmchan, BearCap *bearCap);
+ftdm_status_t set_chan_id_ie(ftdm_channel_t *ftdmchan, ChanId *chanId);
+ftdm_status_t set_restart_ind_ie(ftdm_channel_t *ftdmchan, RstInd *rstInd);
+ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr);
+ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t *data_len);
+
+
uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability);
uint8_t sngisdn_get_usrInfoLyr1Prot_from_stack(ftdm_user_layer1_prot_t layer1_prot);
ftdm_bearer_cap_t sngisdn_get_infoTranCap_from_user(uint8_t bearer_capability);
@@ -382,16 +496,18 @@ 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);
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 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 64d7a2403f..c979000223 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") ||
@@ -98,6 +111,8 @@ ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span)
ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported switchtype %s for trunktype:%s\n", span->name, switch_name, ftdm_trunk_type2str(span->trunk_type));
return FTDM_FAIL;
}
+ ftdm_set_flag(span, FTDM_SPAN_USE_AV_RATE);
+ ftdm_set_flag(span, FTDM_SPAN_PWR_SAVING);
/* can be > 1 for some BRI variants */
break;
default:
@@ -122,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++;
@@ -136,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") ||
@@ -179,6 +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;
@@ -189,19 +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++) {
@@ -233,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;
@@ -276,6 +292,14 @@ 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 if (!strcasecmp(var, "q931-raw-trace")) {
+ parse_yesno(var, val, &signal_data->raw_trace_q931);
+ } else if (!strcasecmp(var, "q921-raw-trace")) {
+ parse_yesno(var, val, &signal_data->raw_trace_q921);
} else {
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_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c
index 5060cb6bba..668b63006c 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c
@@ -47,7 +47,7 @@ void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status
sig.span_id = ftdmchan->span_id;
sig.channel = ftdmchan;
sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
- sig.sigstatus = status;
+ sig.ev_data.sigstatus.status = status;
ftdm_span_send_signal(ftdmchan->span, &sig);
return;
}
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 27c16c2a51..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,7 +112,7 @@ ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span)
}
-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 */
@@ -121,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;
@@ -155,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;
@@ -190,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) {
@@ -199,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");
}
}
@@ -207,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");
}
}
@@ -217,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");
}
}
@@ -227,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");
}
}
@@ -237,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;
@@ -276,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..7e9e360c6d 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,8 @@
*/
#include "ftmod_sangoma_isdn.h"
+static ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn);
+static void sngisdn_process_restart_confirm(ftdm_channel_t *ftdmchan);
/* Remote side transmit a SETUP */
void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
@@ -122,15 +124,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 +145,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 {
@@ -226,6 +233,9 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
}
break;
+ case FTDM_CHANNEL_STATE_RESET:
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
+ break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing SETUP in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
break;
@@ -243,11 +253,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,15 +277,22 @@ 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_RINGING:
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:
case FTDM_CHANNEL_STATE_HANGUP:
/* Race condition, we just hung up the call - ignore this message */
break;
+ case FTDM_CHANNEL_STATE_RESET:
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
+ break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
@@ -294,6 +309,9 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
/* Race condition, We just hung up an incoming call right after we sent a CONNECT - ignore this message */
break;
+ case FTDM_CHANNEL_STATE_RESET:
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
+ break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
@@ -318,8 +336,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,56 +351,61 @@ 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)) {
- ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
- } else {
- ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
- }
- break;
+ case FTDM_CHANNEL_STATE_DIALING:
+ case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
- if (evntType == MI_PROGRESS ||
- (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL)) {
- ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
+ case FTDM_CHANNEL_STATE_RINGING:
+ if (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL) {
+ sngisdn_set_flag(sngisdn_info, FLAG_MEDIA_READY);
+ }
+ switch (evntType) {
+ case MI_CALLPROC:
+ if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) {
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROCEED);
+ }
+ break;
+ case MI_ALERTING:
+ if (ftdmchan->state == FTDM_CHANNEL_STATE_PROCEED) {
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RINGING);
+ }
+ break;
+ case MI_PROGRESS:
+ if (sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY)) {
+
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
+ } else if (ftdmchan->state != FTDM_CHANNEL_STATE_PROGRESS) {
+
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
+ }
+ break;
+ default:
+ /* We should never reach this section !*/
+ ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle this event %d\n", evntType);
}
break;
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
/* We are already in progress media, we can't go to any higher state except up */
/* Do nothing */
break;
+ case FTDM_CHANNEL_STATE_RESET:
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
+ break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing ALERT/PROCEED/PROGRESS in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
@@ -406,7 +427,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,11 +438,16 @@ 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:
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Receiving more digits %s, but we already proceeded with call\n", cnStEvnt->cdPtyNmb.nmbDigits.val);
break;
+ case FTDM_CHANNEL_STATE_RESET:
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
+ break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "\n", suId, suInstId, spInstId);
break;
@@ -454,12 +480,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 {
@@ -481,6 +511,9 @@ void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event)
/* This is a race condition. We just sent a DISCONNECT, on this channel */
/* Do nothing */
break;
+ case FTDM_CHANNEL_STATE_RESET:
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
+ break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received DISCONNECT in an invalid state (%s)\n",
ftdm_channel_state2str(ftdmchan->state));
@@ -535,18 +568,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_span_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);
@@ -580,6 +618,9 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
/* set abort flag so that we do not transmit another release complete on this channel once FS core is done */
}
break;
+ case FTDM_CHANNEL_STATE_RESET:
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
+ break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received RELEASE in an invalid state (%s)\n",
ftdm_channel_state2str(ftdmchan->state));
@@ -725,15 +766,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 +793,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 +922,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 +941,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 +980,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:
@@ -1028,18 +1090,91 @@ void sngisdn_process_srv_cfm (sngisdn_event_data_t *sngisdn_event)
return;
}
+static void sngisdn_process_restart_confirm(ftdm_channel_t *ftdmchan)
+{
+ switch (ftdmchan->state) {
+ case FTDM_CHANNEL_STATE_RESET:
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+ break;
+ case FTDM_CHANNEL_STATE_DOWN:
+ /* Do nothing */
+ break;
+ default:
+ ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received RESTART CFM in an invalid state (%s)\n",
+ ftdm_channel_state2str(ftdmchan->state));
+ }
+
+ return;
+}
+
+
void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
{
int16_t suId = sngisdn_event->suId;
int16_t dChan = sngisdn_event->dChan;
uint8_t ces = sngisdn_event->ces;
uint8_t evntType = sngisdn_event->evntType;
-
- ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-
- /* Function does not require any info from ssHlEvnt struct for now */
- /*Rst *rstEvnt = &sngisdn_event->event.rstEvnt;*/
+ uint8_t chan_no = 0;
+ Rst *rstEvnt = &sngisdn_event->event.rstEvnt;
+ sngisdn_span_data_t *signal_data = g_sngisdn_data.dchans[dChan].spans[1];
+ if (!signal_data) {
+ ftdm_log(FTDM_LOG_CRIT, "Received RESTART on unconfigured span (suId:%d)\n", suId);
+ return;
+ }
+
+ if (!rstEvnt->rstInd.eh.pres || !rstEvnt->rstInd.rstClass.pres) {
+ ftdm_log(FTDM_LOG_DEBUG, "Receved RESTART, but Restart Indicator IE not present\n");
+ return;
+ }
+
+ switch(rstEvnt->rstInd.rstClass.val) {
+ case IN_CL_INDCHAN: /* Indicated b-channel */
+ if (rstEvnt->chanId.eh.pres) {
+ if (rstEvnt->chanId.intType.val == IN_IT_BASIC) {
+ if (rstEvnt->chanId.infoChanSel.pres == PRSNT_NODEF) {
+ chan_no = rstEvnt->chanId.infoChanSel.val;
+ }
+ } else if (rstEvnt->chanId.intType.val == IN_IT_OTHER) {
+ if (rstEvnt->chanId.chanNmbSlotMap.pres == PRSNT_NODEF) {
+ chan_no = rstEvnt->chanId.chanNmbSlotMap.val[0];
+ }
+ }
+ }
+ if (!chan_no) {
+ ftdm_log(FTDM_LOG_CRIT, "Failed to determine channel from RESTART\n");
+ return;
+ }
+ break;
+ case IN_CL_SNGINT: /* Single interface */
+ case IN_CL_ALLINT: /* All interfaces */
+ /* In case restart class indicates all interfaces, we will duplicate
+ this event on each span associated to this d-channel in sngisdn_rcv_rst_cfm,
+ so treat it as a single interface anyway */
+ break;
+ default:
+ ftdm_log(FTDM_LOG_CRIT, "Invalid restart indicator class:%d\n", rstEvnt->rstInd.rstClass.val);
+ return;
+ }
+
+ if (chan_no) { /* For a single channel */
+ if (chan_no > ftdm_span_get_chan_count(signal_data->ftdm_span)) {
+ ftdm_log(FTDM_LOG_CRIT, "Received RESTART on invalid channel:%d\n", chan_no);
+ } else {
+ ftdm_channel_t *ftdmchan = ftdm_span_get_channel(signal_data->ftdm_span, chan_no);
+ sngisdn_process_restart_confirm(ftdmchan);
+ }
+ } else { /* for all channels */
+ ftdm_iterator_t *chaniter = NULL;
+ ftdm_iterator_t *curr = NULL;
+
+ chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
+ for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
+ sngisdn_process_restart_confirm((ftdm_channel_t*)ftdm_iterator_current(curr));
+ }
+ ftdm_iterator_free(chaniter);
+ }
+
ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART CFM (suId:%u dChan:%d ces:%d type:%d)\n", suId, dChan, ces, evntType);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
@@ -1062,8 +1197,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;
}
+
+static 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 124cd965b4..bb04f887ab 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,19 +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");
@@ -58,80 +51,6 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
ftdm_mutex_unlock(g_sngisdn_data.ccs[signal_data->cc_id].mutex);
memset(&conEvnt, 0, sizeof(conEvnt));
-
- conEvnt.bearCap[0].eh.pres = PRSNT_NODEF;
- conEvnt.bearCap[0].infoTranCap.pres = PRSNT_NODEF;
- conEvnt.bearCap[0].infoTranCap.val = sngisdn_get_infoTranCap_from_user(ftdmchan->caller_data.bearer_capability);
-
- conEvnt.bearCap[0].codeStand0.pres = PRSNT_NODEF;
- conEvnt.bearCap[0].codeStand0.val = IN_CSTD_CCITT;
- conEvnt.bearCap[0].infoTranRate0.pres = PRSNT_NODEF;
- conEvnt.bearCap[0].infoTranRate0.val = IN_ITR_64KBIT;
- conEvnt.bearCap[0].tranMode.pres = PRSNT_NODEF;
- conEvnt.bearCap[0].tranMode.val = IN_TM_CIRCUIT;
-
- conEvnt.chanId.eh.pres = PRSNT_NODEF;
- conEvnt.chanId.prefExc.pres = PRSNT_NODEF;
- conEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
- conEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
- conEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
- conEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
- conEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
- conEvnt.chanId.intIdent.pres = NOTPRSNT;
-
- if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
- ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
- /* Trillium stack rejests lyr1Ident on BRI, but Netbricks always sends it.
- Check with Trillium if this ever causes calls to fail in the field */
-
- /* BRI only params */
- conEvnt.chanId.intType.pres = PRSNT_NODEF;
- conEvnt.chanId.intType.val = IN_IT_BASIC;
- conEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
- conEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
- } else {
- /* PRI only params */
- conEvnt.bearCap[0].usrInfoLyr1Prot.pres = PRSNT_NODEF;
- conEvnt.bearCap[0].usrInfoLyr1Prot.val = sngisdn_get_usrInfoLyr1Prot_from_user(ftdmchan->caller_data.bearer_layer1);
-
- if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN &&
- conEvnt.bearCap[0].usrInfoLyr1Prot.val == IN_UIL1_G711ULAW) {
-
- /* We are bridging a call from T1 */
- conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ALAW;
-
- } else if (conEvnt.bearCap[0].usrInfoLyr1Prot.val == IN_UIL1_G711ALAW) {
-
- /* We are bridging a call from E1 */
- conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ULAW;
- }
-
- conEvnt.bearCap[0].lyr1Ident.pres = PRSNT_NODEF;
- conEvnt.bearCap[0].lyr1Ident.val = IN_L1_IDENT;
-
- conEvnt.chanId.intType.pres = PRSNT_NODEF;
- conEvnt.chanId.intType.val = IN_IT_OTHER;
- conEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
- conEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
- conEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
- conEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
- conEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
- conEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
- conEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
- conEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
- conEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
- conEvnt.chanId.chanNmbSlotMap.len = 1;
- 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;
}
@@ -141,10 +60,16 @@ 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_chan_id_ie(ftdmchan, &conEvnt.chanId);
+ set_bear_cap_ie(ftdmchan, &conEvnt.bearCap[0]);
+ 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);
@@ -172,38 +97,7 @@ void sngisdn_snd_setup_ack(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;
- cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
- cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
- cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
- cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
-
- if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
- ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
-
- /* BRI only params */
- cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
- cnStEvnt.chanId.intType.val = IN_IT_BASIC;
- cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
- cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
- } else {
- cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
- cnStEvnt.chanId.intType.val = IN_IT_OTHER;
- cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
- cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
- cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
- cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
- cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
- cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
- cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
- cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
- cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
- cnStEvnt.chanId.chanNmbSlotMap.len = 1;
- cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
- }
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP ACK (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);
@@ -232,38 +126,7 @@ void sngisdn_snd_con_complete(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;
- cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
- cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
- cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
- cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
-
- if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
- ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
-
- /* BRI only params */
- cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
- cnStEvnt.chanId.intType.val = IN_IT_BASIC;
- cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
- cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
- } else {
- cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
- cnStEvnt.chanId.intType.val = IN_IT_OTHER;
- cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
- cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
- cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
- cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
- cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
- cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
- cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
- cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
- cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
- cnStEvnt.chanId.chanNmbSlotMap.len = 1;
- cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
- }
-
+ set_chan_id_ie(ftdmchan, &cnStEvnt.chanId);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT COMPL (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);
@@ -274,10 +137,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;
@@ -289,39 +151,12 @@ void sngisdn_snd_proceed(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;
- cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
- cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
- cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
- cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
-
- if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
- ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
-
- /* BRI only params */
- cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
- cnStEvnt.chanId.intType.val = IN_IT_BASIC;
- cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
- cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
- } else {
- cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
- cnStEvnt.chanId.intType.val = IN_IT_OTHER;
- cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
- cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
- cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
- cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
- cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
- cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
- cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
- cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
- cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
- cnStEvnt.chanId.chanNmbSlotMap.len = 1;
- cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
- }
+ set_chan_id_ie(ftdmchan, &cnStEvnt.chanId);
+ 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);
@@ -331,14 +166,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);
@@ -352,14 +187,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)) {
@@ -368,14 +198,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);
@@ -384,13 +214,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);
@@ -402,10 +228,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,47 +241,11 @@ 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;
- cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
- cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
- cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
- cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
- if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
- ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
-
- /* BRI only params */
- cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
- cnStEvnt.chanId.intType.val = IN_IT_BASIC;
- cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
- cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
- } else {
- cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
- cnStEvnt.chanId.intType.val = IN_IT_OTHER;
- cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
- cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
- cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
- cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
- cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
- cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
- cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
- cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
- cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
- 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_chan_id_ie(ftdmchan, &cnStEvnt.chanId);
+ 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)) {
@@ -464,6 +254,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)
{
@@ -483,6 +306,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)) {
@@ -503,6 +328,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");
@@ -518,7 +345,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);
@@ -528,7 +355,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;
@@ -539,12 +367,16 @@ 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");
}
return;
}
+
void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
{
RelEvnt relEvnt;
@@ -563,7 +395,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;
@@ -583,6 +415,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 +432,92 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
return;
}
+void sngisdn_snd_restart(ftdm_channel_t *ftdmchan)
+{
+ Rst rstEvnt;
+ sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
+
+ memset(&rstEvnt, 0, sizeof(rstEvnt));
+
+ set_chan_id_ie(ftdmchan, &rstEvnt.chanId);
+ set_restart_ind_ie(ftdmchan, &rstEvnt.rstInd);
+
+ ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RESTART (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, signal_data->dchan_id, CES_MNGMNT);
+
+ if (sng_isdn_restart_request(signal_data->cc_id, &rstEvnt, signal_data->dchan_id, CES_MNGMNT, IN_SND_RST)) {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused RESTART request\n");
+ }
+ return;
+}
+
+
+/* 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:
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..3afdaa599e 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
@@ -34,9 +34,6 @@
#include "ftmod_sangoma_isdn.h"
-#define MAX_DECODE_STR_LEN 2000
-
-
void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces)
{
uint8_t bchan_no = 0;
@@ -630,8 +627,9 @@ void sngisdn_rcv_rst_cfm (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+
ftdm_log(FTDM_LOG_INFO, "Received RESTART CFM (dChan:%d ces:%u type:%u)\n", dChan, ces, evntType);
-
+
/* Enqueue the event to each span within the dChan */
for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) {
signal_data = g_sngisdn_data.dchans[dChan].spans[i];
@@ -725,14 +723,25 @@ void sngisdn_rcv_q931_ind(InMngmt *status)
ftdmspan = signal_data->ftdm_span;
if (status->t.usta.alarm.event == LCM_EVENT_UP) {
+ uint32_t chan_no = status->t.usta.evntParm[2];
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
status->t.usta.suId,
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
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);
+
+ if (chan_no) {
+ ftdm_channel_t *ftdmchan = ftdm_span_get_channel(ftdmspan, chan_no);
+ if (ftdmchan) {
+ sngisdn_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP);
+ sngisdn_set_chan_avail_rate(ftdmchan, SNGISDN_AVAIL_UP);
+ } else {
+ ftdm_log(FTDM_LOG_CRIT, "stack alarm event on invalid channel :%d\n", chan_no);
+ }
+ } else {
+ sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_UP);
+ sngisdn_set_span_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 +750,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_span_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING);
}
}
break;
@@ -765,9 +774,6 @@ void sngisdn_rcv_cc_ind(CcMngmt *status)
return;
}
-#define Q931_TRC_EVENT(event) (event == TL3PKTTX)?"TX": \
- (event == TL3PKTRX)?"RX":"UNKNOWN"
-
void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
{
MsgLen mlen;
@@ -776,13 +782,20 @@ void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
Buffer *tmp;
Data *cptr;
uint8_t data;
+ ftdm_trace_dir_t dir;
uint8_t tdata[1000];
- char *data_str = ftdm_calloc(1,MAX_DECODE_STR_LEN); /* TODO Find a proper size */
-
+ sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[trc->t.trc.suId];
+
ftdm_assert(mBuf != NULLP, "Received a Q931 trace with no buffer");
mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
-
- if (mlen != 0) {
+
+ if (trc->t.trc.evnt == TL3PKTTX) {
+ dir = FTDM_TRACE_OUTGOING;
+ } else {
+ dir = FTDM_TRACE_INCOMING;
+ }
+
+ if (mlen) {
tmp = mBuf->b_cont;
cptr = tmp->b_rptr;
data = *cptr++;
@@ -797,41 +810,40 @@ void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
}
data = *cptr++;
}
-
- sngisdn_trace_q931(data_str, tdata, mlen);
- ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] s%d FRAME %s:%s\n", trc->t.trc.suId, Q931_TRC_EVENT(trc->t.trc.evnt), data_str);
+ if (signal_data->raw_trace_q931 == SNGISDN_OPT_TRUE) {
+ sngisdn_trace_raw_q931(signal_data, dir, tdata, mlen);
+ } else {
+ sngisdn_trace_interpreted_q931(signal_data, dir, tdata, mlen);
+ }
}
-
- ftdm_safe_free(data_str);
- /* We do not need to free mBuf in this case because stack does it */
- /* SPutMsg(mBuf); */
return;
}
-#define Q921_TRC_EVENT(event) (event == TL2FRMRX)?"RX": \
- (event == TL2FRMTX)?"TX": \
- (event == TL2TMR)?"TMR EXPIRED":"UNKNOWN"
-
void sngisdn_rcv_q921_trace(BdMngmt *trc, Buffer *mBuf)
{
MsgLen mlen;
+ Buffer *tmp;
MsgLen i;
int16_t j;
- Buffer *tmp;
Data *cptr;
uint8_t data;
- uint8_t tdata[16];
- char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */
-
+ ftdm_trace_dir_t dir;
+ uint8_t tdata[1000];
+ sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[trc->t.trc.lnkNmb];
if (trc->t.trc.evnt == TL2TMR) {
- goto end_of_trace;
+ return;
}
+ if (trc->t.trc.evnt == TL2FRMTX) {
+ dir = FTDM_TRACE_OUTGOING;
+ } else {
+ dir = FTDM_TRACE_INCOMING;
+ }
+
ftdm_assert(mBuf != NULLP, "Received a Q921 trace with no buffer");
mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
-
if (mlen != 0) {
tmp = mBuf->b_cont;
cptr = tmp->b_rptr;
@@ -853,15 +865,91 @@ void sngisdn_rcv_q921_trace(BdMngmt *trc, Buffer *mBuf)
}
}
- sngisdn_trace_q921(data_str, tdata, mlen);
- ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] s%d FRAME %s:%s\n", trc->t.trc.lnkNmb, Q921_TRC_EVENT(trc->t.trc.evnt), data_str);
+ if (signal_data->raw_trace_q921 == SNGISDN_OPT_TRUE) {
+ sngisdn_trace_raw_q921(signal_data, dir, tdata, mlen);
+ } else {
+ sngisdn_trace_interpreted_q921(signal_data, dir, tdata, mlen);
+ }
}
-end_of_trace:
- ftdm_safe_free(data_str);
- SPutMsg(mBuf);
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 e8e27687b4..28768a1f09 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,97 +136,142 @@ 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_chan_avail_rate(ftdm_channel_t *chan, sngisdn_avail_t avail)
{
-
- if (span->trunk_type == FTDM_TRUNK_BRI ||
- span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
+ if (FTDM_SPAN_IS_BRI(chan->span)) {
+ ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Setting availability rate to:%d\n", avail);
+ chan->availability_rate = avail;
+ }
+ return FTDM_SUCCESS;
+}
+ftdm_status_t sngisdn_set_span_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail)
+{
+ if (FTDM_SPAN_IS_BRI(span)) {
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)) {
ftdm_log_chan(((ftdm_channel_t*)ftdm_iterator_current(curr)), FTDM_LOG_DEBUG, "Setting availability rate to:%d\n", avail);
- ((ftdm_channel_t*)ftdm_iterator_current(curr))->availability_rate = avail;
+ sngisdn_set_chan_avail_rate(((ftdm_channel_t*)ftdm_iterator_current(curr)), avail);
}
ftdm_iterator_free(chaniter);
}
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 +279,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 +587,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 +631,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 +649,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 +662,259 @@ 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;
+}
+
+ftdm_status_t set_chan_id_ie(ftdm_channel_t *ftdmchan, ChanId *chanId)
+{
+ if (!ftdmchan) {
+ return FTDM_SUCCESS;
+ }
+ chanId->eh.pres = PRSNT_NODEF;
+ chanId->prefExc.pres = PRSNT_NODEF;
+ chanId->prefExc.val = IN_PE_EXCLSVE;
+ chanId->dChanInd.pres = PRSNT_NODEF;
+ chanId->dChanInd.val = IN_DSI_NOTDCHAN;
+ chanId->intIdentPres.pres = PRSNT_NODEF;
+ chanId->intIdentPres.val = IN_IIP_IMPLICIT;
+
+ if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
+ ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
+
+ /* BRI only params */
+ chanId->intType.pres = PRSNT_NODEF;
+ chanId->intType.val = IN_IT_BASIC;
+ chanId->infoChanSel.pres = PRSNT_NODEF;
+ chanId->infoChanSel.val = ftdmchan->physical_chan_id;
+ } else {
+ chanId->intType.pres = PRSNT_NODEF;
+ chanId->intType.val = IN_IT_OTHER;
+ chanId->infoChanSel.pres = PRSNT_NODEF;
+ chanId->infoChanSel.val = IN_ICS_B1CHAN;
+ chanId->chanMapType.pres = PRSNT_NODEF;
+ chanId->chanMapType.val = IN_CMT_BCHAN;
+ chanId->nmbMap.pres = PRSNT_NODEF;
+ chanId->nmbMap.val = IN_NM_CHNNMB;
+ chanId->codeStand1.pres = PRSNT_NODEF;
+ chanId->codeStand1.val = IN_CSTD_CCITT;
+ chanId->chanNmbSlotMap.pres = PRSNT_NODEF;
+ chanId->chanNmbSlotMap.len = 1;
+ chanId->chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
+ }
+ return FTDM_SUCCESS;
+}
+
+ftdm_status_t set_bear_cap_ie(ftdm_channel_t *ftdmchan, BearCap *bearCap)
+{
+ sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
+
+ bearCap->eh.pres = PRSNT_NODEF;
+ bearCap->infoTranCap.pres = PRSNT_NODEF;
+ bearCap->infoTranCap.val = sngisdn_get_infoTranCap_from_user(ftdmchan->caller_data.bearer_capability);
+
+ bearCap->codeStand0.pres = PRSNT_NODEF;
+ bearCap->codeStand0.val = IN_CSTD_CCITT;
+ bearCap->infoTranRate0.pres = PRSNT_NODEF;
+ bearCap->infoTranRate0.val = IN_ITR_64KBIT;
+ bearCap->tranMode.pres = PRSNT_NODEF;
+ bearCap->tranMode.val = IN_TM_CIRCUIT;
+
+ if (!FTDM_SPAN_IS_BRI(ftdmchan->span)) {
+ /* Trillium stack rejests lyr1Ident on BRI, but Netbricks always sends it.
+ Check with Trillium if this ever causes calls to fail in the field */
+
+ /* PRI only params */
+ bearCap->usrInfoLyr1Prot.pres = PRSNT_NODEF;
+ bearCap->usrInfoLyr1Prot.val = sngisdn_get_usrInfoLyr1Prot_from_user(ftdmchan->caller_data.bearer_layer1);
+
+ if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN &&
+ bearCap->usrInfoLyr1Prot.val == IN_UIL1_G711ULAW) {
+
+ /* We are bridging a call from T1 */
+ bearCap->usrInfoLyr1Prot.val = IN_UIL1_G711ALAW;
+
+ } else if (bearCap->usrInfoLyr1Prot.val == IN_UIL1_G711ALAW) {
+
+ /* We are bridging a call from E1 */
+ bearCap->usrInfoLyr1Prot.val = IN_UIL1_G711ULAW;
+ }
+
+ bearCap->lyr1Ident.pres = PRSNT_NODEF;
+ bearCap->lyr1Ident.val = IN_L1_IDENT;
+ }
+ return FTDM_SUCCESS;
+}
+
+ftdm_status_t set_restart_ind_ie(ftdm_channel_t *ftdmchan, RstInd *rstInd)
+{
+ rstInd->eh.pres = PRSNT_NODEF;
+ rstInd->rstClass.pres = PRSNT_NODEF;
+ rstInd->rstClass.val = IN_CL_INDCHAN;
+ return FTDM_SUCCESS;
+}
+
+void sngisdn_t3_timeout(void* p_sngisdn_info)
+{
+ sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;
+ ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
+ sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
+
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Timer T3 expired (suId:%d suInstId:%u spInstId:%u)\n",
+ signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId);
+ ftdm_mutex_lock(ftdmchan->mutex);
+ if (ftdm_test_flag(sngisdn_info, FLAG_ACTIVATING)){
+ /* PHY layer timed-out, need to clear the call */
+ ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Failed to Wake-Up line (suId:%d suInstId:%u spInstId:%u)\n",
+ signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId);
+
+ ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NO_ROUTE_DESTINATION;
+ ftdm_clear_flag(sngisdn_info, FLAG_ACTIVATING);
+ ftdm_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
+ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+ }
+ 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;
@@ -495,13 +1038,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;
@@ -512,13 +1054,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..c03976a1c2 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
@@ -36,14 +36,15 @@
#include "ftmod_sangoma_isdn_trace.h"
#define OCTET(x) (ieData[x-1] & 0xFF)
+#define MAX_DECODE_STR_LEN 2000
void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_start, uint32_t index_end);
-void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len);
-void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len);
uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset, uint8_t *data, uint16_t index_start);
uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi);
char* get_code_2_str(int code, struct code2str *pCodeTable);
+void sngisdn_decode_q921(char* str, uint8_t* data, uint32_t data_len);
+void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len);
char* get_code_2_str(int code, struct code2str *pCodeTable)
{
@@ -97,7 +98,42 @@ uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi)
return 0;
}
-void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len)
+void sngisdn_trace_interpreted_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
+{
+ char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */
+ sngisdn_decode_q921(data_str, data, data_len);
+ ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] s%d FRAME %s:%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str);
+ ftdm_safe_free(data_str);
+}
+
+void sngisdn_trace_raw_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
+{
+ uint8_t *raw_data;
+ ftdm_sigmsg_t sigev;
+
+ memset(&sigev, 0, sizeof(sigev));
+
+ sigev.span_id = signal_data->ftdm_span->span_id;
+ sigev.chan_id = signal_data->dchan->chan_id;
+ sigev.channel = signal_data->dchan;
+ sigev.event_id = FTDM_SIGEVENT_TRACE_RAW;
+
+ sigev.ev_data.logevent.dir = dir;
+ sigev.ev_data.logevent.level = 2;
+
+ /* TODO: Map trace to call ID here */
+ sigev.call_id = 0;
+
+ raw_data = ftdm_malloc(data_len);
+ ftdm_assert(raw_data, "Failed to malloc");
+
+ memcpy(raw_data, data, data_len);
+ sigev.raw_data = raw_data;
+ sigev.raw_data_len = data_len;
+ ftdm_span_send_signal(signal_data->ftdm_span, &sigev);
+}
+
+void sngisdn_decode_q921(char* str, uint8_t* data, uint32_t data_len)
{
int str_len;
uint32_t i;
@@ -169,7 +205,42 @@ void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len)
return;
}
-void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len)
+
+void sngisdn_trace_interpreted_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
+{
+ char *data_str = ftdm_calloc(1,MAX_DECODE_STR_LEN); /* TODO Find a proper size */
+ sngisdn_decode_q931(data_str, data, data_len);
+ ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] %s FRAME %s:%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str);
+ ftdm_safe_free(data_str);
+}
+
+void sngisdn_trace_raw_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
+{
+ uint8_t *raw_data;
+ ftdm_sigmsg_t sigev;
+
+ memset(&sigev, 0, sizeof(sigev));
+
+ sigev.span_id = signal_data->ftdm_span->span_id;
+ sigev.chan_id = signal_data->dchan->chan_id;
+ sigev.channel = signal_data->dchan;
+ sigev.event_id = FTDM_SIGEVENT_TRACE_RAW;
+
+ sigev.ev_data.logevent.dir = dir;
+ sigev.ev_data.logevent.level = 3;
+
+ /* TODO: Map trace to call ID here */
+
+ raw_data = ftdm_malloc(data_len);
+ ftdm_assert(raw_data, "Failed to malloc");
+
+ memcpy(raw_data, data, data_len);
+ sigev.raw_data = raw_data;
+ sigev.raw_data_len = data_len;
+ ftdm_span_send_signal(signal_data->ftdm_span, &sigev);
+}
+
+void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len)
{
uint32_t str_len;
uint8_t prot_disc, callRefFlag;
@@ -613,6 +684,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_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c
index 87d80f18a4..e7378bf2ea 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c
@@ -1347,7 +1347,7 @@ int ftmod_ss7_isup_isap_config(int id)
cfg.t.cfg.s.siSap.natAddrInd = ADDR_NOTPRSNT; /* SID Nature of Addres Indicator */
cfg.t.cfg.s.siSap.sidNPlan = NP_ISDN; /* SID Numbering Plan */
cfg.t.cfg.s.siSap.sidPresInd = FALSE; /* default presentation indicator */
- cfg.t.cfg.s.siSap.incSidPresRes = TRUE; /* Presentation Restriction of incoming SID */
+ cfg.t.cfg.s.siSap.incSidPresRes = FALSE; /* Presentation Restriction of incoming SID */
cfg.t.cfg.s.siSap.sidPresRes = 0; /* Presentation Restriction */
}
cfg.t.cfg.s.siSap.reqOpt = FALSE; /* Request option */
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c
index 38d3723061..dc2d24f42a 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c
@@ -1482,7 +1482,7 @@ static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int c
sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
ftdmchan = sngss7_info->ftdmchan;
- sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span = ftdmchan->span->signal_data;
if ((ftdmchan->physical_span_id == span) &&
((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) {
@@ -1529,7 +1529,7 @@ static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int c
sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
ftdmchan = sngss7_info->ftdmchan;
- sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span = ftdmchan->span->signal_data;
if ((ftdmchan->physical_span_id == span) &&
((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) {
@@ -1572,7 +1572,7 @@ static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int c
/* extract the channel and span info for this circuit */
sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
ftdmchan = sngss7_info->ftdmchan;
- sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span = ftdmchan->span->signal_data;
/* check if this circuit is part of the block */
if ((ftdmchan->physical_span_id == span) &&
@@ -1589,7 +1589,7 @@ static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int c
sigev.span_id = ftdmchan->span_id;
sigev.channel = ftdmchan;
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
- sigev.sigstatus = FTDM_SIG_STATE_DOWN;
+ sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* if this is the first channel in the range */
@@ -1628,7 +1628,7 @@ static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int c
sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
ftdmchan = sngss7_info->ftdmchan;
- sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span = ftdmchan->span->signal_data;
if ((ftdmchan->physical_span_id == span) &&
((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) {
@@ -1672,7 +1672,7 @@ static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int c
/* extract the channel and span info for this circuit */
sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
ftdmchan = sngss7_info->ftdmchan;
- sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span = ftdmchan->span->signal_data;
/* check if this circuit is part of the block */
if ((ftdmchan->physical_span_id == span) &&
@@ -1689,7 +1689,7 @@ static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int c
sigev.span_id = ftdmchan->span_id;
sigev.channel = ftdmchan;
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
- sigev.sigstatus = FTDM_SIG_STATE_UP;
+ sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* if this is the first channel in the range */
@@ -1728,7 +1728,7 @@ static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int c
sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
ftdmchan = sngss7_info->ftdmchan;
- sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span = ftdmchan->span->signal_data;
if ((ftdmchan->physical_span_id == span) &&
((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) {
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 af3b9edbae..dcfb7f79e0 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 */
@@ -1722,7 +1722,7 @@ ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
}
/* fill in the span structure for this circuit */
- sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span = ftdmchan->span->signal_data;
sngss7_span->rx_grs.circuit = circuit;
sngss7_span->rx_grs.range = range;
@@ -1758,7 +1758,7 @@ ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ
}
/* fill in the span structure for this circuit */
- sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span = ftdmchan->span->signal_data;
sngss7_span->rx_gra.circuit = circuit;
sngss7_span->rx_gra.range = range;
@@ -1866,7 +1866,7 @@ ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit
}
/* check if we just sent a GRS request...*/
- sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span = ftdmchan->span->signal_data;
if (sngss7_span->tx_grs.circuit > 0) {
/* we need to put all circuits on this UCIC */
sngss7_span->ucic.circuit = sngss7_span->tx_grs.circuit;
@@ -1917,7 +1917,7 @@ ftdm_status_t handle_cgb_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
}
/* grab the span info */
- sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span = ftdmchan->span->signal_data;
/* figure out what type of block needs to be applied */
if ((siStaEvnt->cgsmti.eh.pres == PRSNT_NODEF) && (siStaEvnt->cgsmti.typeInd.pres == PRSNT_NODEF)) {
@@ -2004,7 +2004,7 @@ ftdm_status_t handle_cgb_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* bring the sig status down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
- sigev.sigstatus = FTDM_SIG_STATE_DOWN;
+ sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* unlock the channel again before we exit */
@@ -2058,7 +2058,7 @@ ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
}
/* grab the span info */
- sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span = ftdmchan->span->signal_data;
/* figure out what type of block needs to be applied */
if ((siStaEvnt->cgsmti.eh.pres == PRSNT_NODEF) && (siStaEvnt->cgsmti.typeInd.pres == PRSNT_NODEF)) {
@@ -2135,7 +2135,7 @@ ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* bring the sig status down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
- sigev.sigstatus = FTDM_SIG_STATE_UP;
+ sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* unlock the channel again before we exit */
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c
index 06fae0cd37..72bd1c3fb2 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c
@@ -90,7 +90,7 @@ void sngss7_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCo
memcpy(&sngss7_event->event.siConEvnt, siConEvnt, sizeof(*siConEvnt));
/* enqueue this event */
- ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event);
+ ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
}
@@ -128,7 +128,7 @@ void sngss7_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCo
memcpy(&sngss7_event->event.siConEvnt, siConEvnt, sizeof(*siConEvnt));
/* enqueue this event */
- ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event);
+ ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
}
@@ -167,7 +167,7 @@ void sngss7_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCn
memcpy(&sngss7_event->event.siCnStEvnt, siCnStEvnt, sizeof(*siCnStEvnt));
/* enqueue this event */
- ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event);
+ ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
}
@@ -205,7 +205,7 @@ void sngss7_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRe
memcpy(&sngss7_event->event.siRelEvnt, siRelEvnt, sizeof(*siRelEvnt));
/* enqueue this event */
- ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event);
+ ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
}
@@ -243,7 +243,7 @@ void sngss7_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRe
memcpy(&sngss7_event->event.siRelEvnt, siRelEvnt, sizeof(*siRelEvnt));
/* enqueue this event */
- ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event);
+ ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
}
@@ -281,7 +281,7 @@ void sngss7_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiIn
memcpy(&sngss7_event->event.siInfoEvnt, siInfoEvnt, sizeof(*siInfoEvnt));
/* enqueue this event */
- ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event);
+ ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
}
@@ -320,7 +320,7 @@ void sngss7_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint
memcpy(&sngss7_event->event.siFacEvnt, siFacEvnt, sizeof(*siFacEvnt));
/* enqueue this event */
- ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event);
+ ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
}
@@ -359,7 +359,7 @@ void sngss7_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint
memcpy(&sngss7_event->event.siFacEvnt, siFacEvnt, sizeof(*siFacEvnt));
/* enqueue this event */
- ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event);
+ ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
}
@@ -396,7 +396,7 @@ void sngss7_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit)
sngss7_event->event_id = SNGSS7_UMSG_IND_EVENT;
/* enqueue this event */
- ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event);
+ ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
@@ -438,7 +438,7 @@ void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint
}
/* enqueue this event */
- ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event);
+ ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
}
@@ -478,7 +478,7 @@ void sngss7_susp_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiS
}
/* enqueue this event */
- ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event);
+ ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
@@ -519,7 +519,7 @@ void sngss7_resm_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiR
}
/* enqueue this event */
- ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event);
+ ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
@@ -560,7 +560,7 @@ void sngss7_ssp_sta_cfm(uint32_t infId)
}
/* enqueue this event */
- ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event);
+ ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event);
#endif
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
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 7612f3dd74..05a325b913 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
@@ -275,7 +275,7 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
ftdm_span_t *ftdmspan = (ftdm_span_t *) obj;
ftdm_channel_t *ftdmchan = NULL;
sngss7_event_data_t *sngss7_event = NULL;
- sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->mod_data;
+ sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
ftdm_log (FTDM_LOG_INFO, "ftmod_sangoma_ss7 monitor thread for span=%u started.\n", ftdmspan->span_id);
@@ -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 */
@@ -788,7 +790,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* check if this is the base circuit and send out the GRA
* we insure that this is the last circuit to have the state change queued
*/
- sngss7_span_data_t *span = ftdmchan->span->mod_data;
+ sngss7_span_data_t *span = ftdmchan->span->signal_data;
if (span->rx_grs.circuit == sngss7_info->circuit->id) {
/* send out the GRA */
ft_to_sngss7_gra(ftdmchan);
@@ -839,7 +841,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
SS7_DEBUG_CHAN(ftdmchan,"All reset flags cleared %s\n", "");
/* all flags are down so we can bring up the sig status */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
- sigev.sigstatus = FTDM_SIG_STATE_UP;
+ sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
ftdm_span_send_signal (ftdmchan->span, &sigev);
} /* if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) */
} /* if !blocked */
@@ -947,7 +949,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* if the sig_status is up...bring it down */
if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) {
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
- sigev.sigstatus = FTDM_SIG_STATE_DOWN;
+ sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal (ftdmchan->span, &sigev);
}
@@ -1031,7 +1033,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* bring the sig status back up */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
- sigev.sigstatus = FTDM_SIG_STATE_UP;
+ sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(ftdmchan->span, &sigev);
}
@@ -1044,7 +1046,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* bring the sig status down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
- sigev.sigstatus = FTDM_SIG_STATE_DOWN;
+ sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* go back to the last state */
@@ -1056,7 +1058,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* bring the sig status down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
- sigev.sigstatus = FTDM_SIG_STATE_DOWN;
+ sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* send a BLA */
@@ -1074,7 +1076,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* bring the sig status up */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
- sigev.sigstatus = FTDM_SIG_STATE_UP;
+ sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* send a uba */
@@ -1090,7 +1092,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* bring the sig status down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
- sigev.sigstatus = FTDM_SIG_STATE_DOWN;
+ sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* send a blo */
@@ -1108,7 +1110,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* bring the sig status up */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
- sigev.sigstatus = FTDM_SIG_STATE_UP;
+ sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* send a ubl */
@@ -1147,7 +1149,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* bring the channel signaling status to down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
- sigev.sigstatus = FTDM_SIG_STATE_DOWN;
+ sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal (ftdmchan->span, &sigev);
/* remove any reset flags */
@@ -1350,7 +1352,7 @@ static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span)
ftdmchan = span->channels[x];
if (ftdmchan->call_data == NULL) continue;
sngss7_info = ftdmchan->call_data;
- sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span = ftdmchan->span->signal_data;
sngss7_intf = &g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId];
@@ -1474,7 +1476,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_ss7_span_config)
span->get_channel_sig_status = ftdm_sangoma_ss7_get_sig_status;
span->set_channel_sig_status = ftdm_sangoma_ss7_set_sig_status;
span->state_map = &sangoma_ss7_state_map;
- span->mod_data = ss7_span_info;
+ span->signal_data = ss7_span_info;
/* set the flag to indicate that this span uses channel state change queues */
ftdm_set_flag (span, FTDM_SPAN_USE_CHAN_QUEUE);
@@ -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 970d006756..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;
}
@@ -619,7 +620,7 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
- sngss7_span_data_t *sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
SiStaEvnt gra;
@@ -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;
}
@@ -663,7 +665,7 @@ void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
- sngss7_span_data_t *sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
SiStaEvnt grs;
@@ -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;
}
@@ -696,7 +699,7 @@ void ft_to_sngss7_cgba(ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
- sngss7_span_data_t *sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
int x = 0;
@@ -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;
}
@@ -745,7 +748,7 @@ void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
- sngss7_span_data_t *sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
int x = 0;
@@ -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;
}
@@ -794,7 +798,7 @@ void ft_to_sngss7_cgb(ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
- sngss7_span_data_t *sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
SiStaEvnt cgb;
int x = 0;
@@ -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;
}
@@ -844,7 +849,7 @@ void ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
- sngss7_span_data_t *sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
SiStaEvnt cgu;
int x = 0;
@@ -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_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c
index 4d497b599d..23617c9147 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c
@@ -513,7 +513,7 @@ ftdm_status_t check_if_rx_grs_started(ftdm_span_t *ftdmspan)
{
ftdm_channel_t *ftdmchan = NULL;
sngss7_chan_data_t *sngss7_info = NULL;
- sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->mod_data;
+ sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
int i;
for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
@@ -575,7 +575,7 @@ ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan)
{
ftdm_channel_t *ftdmchan = NULL;
sngss7_chan_data_t *sngss7_info = NULL;
- sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->mod_data;
+ sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
int i;
int byte = 0;
int bit = 0;
@@ -667,7 +667,7 @@ ftdm_status_t check_if_rx_gra_started(ftdm_span_t *ftdmspan)
{
ftdm_channel_t *ftdmchan = NULL;
sngss7_chan_data_t *sngss7_info = NULL;
- sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->mod_data;
+ sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
int i;
for (i = sngss7_span->rx_gra.circuit; i < (sngss7_span->rx_gra.circuit + sngss7_span->rx_gra.range + 1); i++) {
@@ -817,7 +817,7 @@ ftdm_status_t process_span_ucic(ftdm_span_t *ftdmspan)
{
ftdm_channel_t *ftdmchan = NULL;
sngss7_chan_data_t *sngss7_info = NULL;
- sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->mod_data;
+ sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
int i;
for (i = sngss7_span->ucic.circuit; i < (sngss7_span->ucic.circuit + sngss7_span->ucic.range + 1); i++) {
@@ -869,7 +869,7 @@ ftdm_status_t clear_rx_grs_flags(sngss7_chan_data_t *sngss7_info)
ftdm_status_t clear_rx_grs_data(sngss7_chan_data_t *sngss7_info)
{
ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan;
- sngss7_span_data_t *sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data;
/* clear the rx_grs data fields */
memset(&sngss7_span->rx_grs, 0x0, sizeof(sngss7_group_data_t));
@@ -881,7 +881,7 @@ ftdm_status_t clear_rx_grs_data(sngss7_chan_data_t *sngss7_info)
ftdm_status_t clear_rx_gra_data(sngss7_chan_data_t *sngss7_info)
{
ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan;
- sngss7_span_data_t *sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data;
/* clear the rx_grs data fields */
memset(&sngss7_span->rx_gra, 0x0, sizeof(sngss7_group_data_t));
@@ -904,7 +904,7 @@ ftdm_status_t clear_tx_grs_flags(sngss7_chan_data_t *sngss7_info)
ftdm_status_t clear_tx_grs_data(sngss7_chan_data_t *sngss7_info)
{
ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan;
- sngss7_span_data_t *sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data;
/* clear the rx_grs data fields */
memset(&sngss7_span->tx_grs, 0x0, sizeof(sngss7_group_data_t));
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 74d37b53d1..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;
@@ -2121,7 +2134,7 @@ static int ftmod_ss7_fill_in_circuits(sng_isupCkt_t *isupCkt)
ftdmchan->call_data = ss7_info;
/* prepare the timer structures */
- ss7_info->t35.sched = ((sngss7_span_data_t *)isupCkt->span->mod_data)->sched;
+ ss7_info->t35.sched = ((sngss7_span_data_t *)isupCkt->span->signal_data)->sched;
ss7_info->t35.counter = 1;
ss7_info->t35.beat = g_ftdm_sngss7_data.cfg.isupIntf[isupCkt->isupInf].t35*100; /* beat is in ms, t35 is in 100ms */
ss7_info->t35.callback = handle_isup_t35;
@@ -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 d2da1ac07a..2db4326847 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,30 +117,34 @@ 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->mod_data;
+ 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) {
- *flags = outflags;
- err = 1; /* ideally should be the number of file descriptors with something to read */
- }
- if (err == SANG_STATUS_APIPOLL_TIMEOUT) {
- err = 0;
- }
- return err;
+ if (err == SANG_STATUS_SUCCESS) {
+ *flags = outflags;
+ err = 1; /* ideally should be the number of file descriptors with something to read */
+ }
+ if (err == SANG_STATUS_APIPOLL_TIMEOUT) {
+ err = 0;
+ }
+ return err;
#else
struct pollfd pfds[1];
- int res;
+ int res;
- memset(&pfds[0], 0, sizeof(pfds[0]));
- pfds[0].fd = ftdmchan->sockfd;
- pfds[0].events = *flags;
- res = poll(pfds, 1, timeout);
+ memset(&pfds[0], 0, sizeof(pfds[0]));
+ pfds[0].fd = ftdmchan->sockfd;
+ pfds[0].events = *flags;
+ res = poll(pfds, 1, timeout);
*flags = 0;
if (pfds[0].revents & POLLERR) {
@@ -149,7 +155,7 @@ static __inline__ int tdmv_api_wait_socket(ftdm_channel_t *ftdmchan, int timeout
*flags = pfds[0].revents;
}
- return res;
+ return res;
#endif
}
@@ -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;
@@ -252,7 +258,7 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
ftdm_log(FTDM_LOG_ERROR, "failure create waitable object for s%dc%d\n", spanno, x);
continue;
}
- chan->mod_data = sangoma_wait_obj;
+ chan->io_data = sangoma_wait_obj;
#endif
chan->physical_span_id = spanno;
@@ -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;
@@ -541,7 +547,7 @@ static FIO_OPEN_FUNCTION(wanpipe_open)
static FIO_CLOSE_FUNCTION(wanpipe_close)
{
#ifdef LIBSANGOMA_VERSION
- sangoma_wait_obj_t *waitobj = ftdmchan->mod_data;
+ sangoma_wait_obj_t *waitobj = ftdmchan->io_data;
/* kick any I/O waiters */
sangoma_wait_obj_signal(waitobj);
#endif
@@ -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;
}
@@ -894,16 +1051,34 @@ FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event)
for(i = 1; i <= span->chan_count; i++) {
ftdm_channel_t *ftdmchan = span->channels[i];
+ uint32_t chan_events = 0;
+
+ /* translate events from ftdm to libsnagoma. if the user don't specify which events to poll the
+ * channel for, we just use SANG_WAIT_OBJ_HAS_EVENTS */
+ if (poll_events) {
+ if (poll_events[j] & FTDM_READ) {
+ chan_events = SANG_WAIT_OBJ_HAS_INPUT;
+ }
+ if (poll_events[j] & FTDM_WRITE) {
+ chan_events |= SANG_WAIT_OBJ_HAS_OUTPUT;
+ }
+ if (poll_events[j] & FTDM_EVENTS) {
+ chan_events |= SANG_WAIT_OBJ_HAS_EVENTS;
+ }
+ } else {
+ chan_events = SANG_WAIT_OBJ_HAS_EVENTS;
+ }
+
#ifdef LIBSANGOMA_VERSION
- if (!ftdmchan->mod_data) {
+ if (!ftdmchan->io_data) {
continue; /* should never happen but happens when shutting down */
}
- pfds[j] = ftdmchan->mod_data;
- inflags[j] = poll_events ? poll_events[j] : POLLPRI;
+ pfds[j] = ftdmchan->io_data;
+ inflags[j] = chan_events;
#else
memset(&pfds[j], 0, sizeof(pfds[j]));
pfds[j].fd = span->channels[i]->sockfd;
- pfds[j].events = poll_events ? poll_events[j] : POLLPRI;
+ pfds[j].events = chan_events;
#endif
/* The driver probably should be able to do this wink/flash/ringing by itself this is sort of a hack to make it work! */
@@ -1011,13 +1186,15 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms)
}
alarms = tdm_api.wp_tdm_cmd.fe_alarms;
#endif
-#if 1
- /* DAVIDY - Temporary fix: in the current trunk of libsangoma, for BRI,
+#ifdef WIN32
+ /* Temporary fix: in the current trunk of libsangoma, for BRI,
WAN_TE_BIT_ALARM_RED bit is set if the card is in disconnected state, but this has
not been ported to Windows-libsangoma yet */
- if (alarms) {
- ftdmchan->alarm_flags |= FTDM_ALARM_RED;
- alarms = 0;
+ if (FTDM_SPAN_IS_BRI(ftdmchan->span)) {
+ if (alarms) {
+ ftdmchan->alarm_flags |= FTDM_ALARM_RED;
+ alarms = 0;
+ }
}
#endif
@@ -1027,6 +1204,7 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms)
ftdmchan->alarm_flags |= FTDM_ALARM_RED;
alarms &= ~WAN_TE_BIT_ALARM_RED;
}
+
if (alarms & WAN_TE_BIT_ALARM_AIS) {
ftdmchan->alarm_flags |= FTDM_ALARM_BLUE;
@@ -1046,13 +1224,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;
@@ -1231,10 +1551,10 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event)
static FIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy)
{
#ifdef LIBSANGOMA_VERSION
- if (ftdmchan->mod_data) {
+ if (ftdmchan->io_data) {
sangoma_wait_obj_t *sangoma_wait_obj;
- sangoma_wait_obj = ftdmchan->mod_data;
- ftdmchan->mod_data = NULL;
+ sangoma_wait_obj = ftdmchan->io_data;
+ ftdmchan->io_data = NULL;
sangoma_wait_obj_delete(&sangoma_wait_obj);
}
#endif
@@ -1284,7 +1604,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 9247edc72e..f40196499c 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
*/
@@ -48,42 +53,48 @@ static struct {
float txgain;
} zt_globals;
+#if defined(__FreeBSD__)
+typedef unsigned long ioctlcmd;
+#else
+typedef int ioctlcmd;
+#endif
+
/**
* \brief General IOCTL codes
*/
struct ioctl_codes {
- int GET_BLOCKSIZE;
- int SET_BLOCKSIZE;
- int FLUSH;
- int SYNC;
- int GET_PARAMS;
- int SET_PARAMS;
- int HOOK;
- int GETEVENT;
- int IOMUX;
- int SPANSTAT;
- int MAINT;
- int GETCONF;
- int SETCONF;
- int CONFLINK;
- int CONFDIAG;
- int GETGAINS;
- int SETGAINS;
- int SPANCONFIG;
- int CHANCONFIG;
- int SET_BUFINFO;
- int GET_BUFINFO;
- int AUDIOMODE;
- int ECHOCANCEL;
- int HDLCRAWMODE;
- int HDLCFCSMODE;
- int SPECIFY;
- int SETLAW;
- int SETLINEAR;
- int GETCONFMUTE;
- int ECHOTRAIN;
- int SETTXBITS;
- int GETRXBITS;
+ ioctlcmd GET_BLOCKSIZE;
+ ioctlcmd SET_BLOCKSIZE;
+ ioctlcmd FLUSH;
+ ioctlcmd SYNC;
+ ioctlcmd GET_PARAMS;
+ ioctlcmd SET_PARAMS;
+ ioctlcmd HOOK;
+ ioctlcmd GETEVENT;
+ ioctlcmd IOMUX;
+ ioctlcmd SPANSTAT;
+ ioctlcmd MAINT;
+ ioctlcmd GETCONF;
+ ioctlcmd SETCONF;
+ ioctlcmd CONFLINK;
+ ioctlcmd CONFDIAG;
+ ioctlcmd GETGAINS;
+ ioctlcmd SETGAINS;
+ ioctlcmd SPANCONFIG;
+ ioctlcmd CHANCONFIG;
+ ioctlcmd SET_BUFINFO;
+ ioctlcmd GET_BUFINFO;
+ ioctlcmd AUDIOMODE;
+ ioctlcmd ECHOCANCEL;
+ ioctlcmd HDLCRAWMODE;
+ ioctlcmd HDLCFCSMODE;
+ ioctlcmd SPECIFY;
+ ioctlcmd SETLAW;
+ ioctlcmd SETLINEAR;
+ ioctlcmd GETCONFMUTE;
+ ioctlcmd ECHOTRAIN;
+ ioctlcmd SETTXBITS;
+ ioctlcmd GETRXBITS;
};
/**
@@ -1081,7 +1092,6 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event)
}
return FTDM_FAIL;
-
}
/**
@@ -1100,12 +1110,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) {
@@ -1113,7 +1130,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..56a9dc0577 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,18 @@ 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; /*! 0 if availability is supported
+ * \retval -1 if availability is not supported
+ */
+FT_DECLARE(int) ftdm_channel_get_availability(ftdm_channel_t *ftdmchan);
+
/*! \brief Answer call */
#define ftdm_channel_call_answer(ftdmchan) _ftdm_channel_call_answer(__FILE__, __FUNCTION__, __LINE__, (ftdmchan))
@@ -616,6 +723,12 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char
/*! \brief Indicate a new condition in an incoming call recording the source code point where it was called (see ftdm_channel_call_indicate for an easy to use macro) */
FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication);
+/*! \brief Send a message on a call */
+#define ftdm_channel_call_send_msg(ftdmchan, sigmsg) _ftdm_channel_call_send_msg(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (sigmsg))
+
+/*! \brief Send a signal on a call recording the source code point where it was called (see ftdm_channel_call_send_msg for an easy to use macro) */
+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);
+
/*! \brief Hangup the call without cause */
#define ftdm_channel_call_hangup(ftdmchan) _ftdm_channel_call_hangup(__FILE__, __FUNCTION__, __LINE__, (ftdmchan))
@@ -628,6 +741,14 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup(const char *file, const char
/*! \brief Hangup the call with cause recording the source code point where it was called (see ftdm_channel_call_hangup_with_cause for an easy to use macro) */
FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup_with_cause(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_call_cause_t);
+/*! \brief Reset the channel */
+#define ftdm_channel_reset(ftdmchan) _ftdm_channel_reset(__FILE__, __FUNCTION__, __LINE__, (ftdmchan))
+
+/*! \brief Reset the channel (see _ftdm_channel_reset for an easy to use macro)
+ * \note if there was a call on this channel, call will be cleared without any notifications to the user
+ */
+FT_DECLARE(ftdm_status_t) _ftdm_channel_reset(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan);
+
/*! \brief Put a call on hold (if supported by the signaling stack) */
#define ftdm_channel_call_hold(ftdmchan) _ftdm_channel_call_hold(__FILE__, __FUNCTION__, __LINE__, (ftdmchan))
@@ -667,6 +788,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_set_sig_status(ftdm_span_t *span, ftdm_signa
/*! \brief Get span signaling status (ie: whether protocol layer is up or down) */
FT_DECLARE(ftdm_status_t) ftdm_span_get_sig_status(ftdm_span_t *span, ftdm_signaling_status_t *status);
+
/*!
* \brief Set user private data in the channel
*
@@ -880,6 +1002,23 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_add_to_group(const char* name, ftdm_chann
/*! \brief Remove the channel from a hunt group */
FT_DECLARE(ftdm_status_t) ftdm_channel_remove_from_group(ftdm_group_t* group, ftdm_channel_t* ftdmchan);
+/*!
+ * \brief Retrieves an event from the span
+ *
+ * \note
+ * This function is non-reentrant and not thread-safe.
+ * The event returned may be modified if the function is called again
+ * from a different thread or even the same. It is recommended to
+ * handle events from the same span in a single thread.
+ *
+ * \param ftdmchan The channel to retrieve the event from
+ * \param event Pointer to store the pointer to the event
+ *
+ * \retval FTDM_SUCCESS success (at least one event available)
+ * \retval FTDM_FAIL failure
+ */
+FT_DECLARE(ftdm_status_t) ftdm_channel_read_event(ftdm_channel_t *ftdmchan, ftdm_event_t **event);
+
/*! \brief Find a hunt group by id */
FT_DECLARE(ftdm_status_t) ftdm_group_find(uint32_t id, ftdm_group_t **group);
@@ -1055,6 +1194,45 @@ FT_DECLARE(ftdm_iterator_t *) ftdm_iterator_next(ftdm_iterator_t *iter);
*/
FT_DECLARE(ftdm_status_t) ftdm_iterator_free(ftdm_iterator_t *iter);
+/*! \brief Add a custom variable to the call
+ * \note This variables may be used by signaling modules to override signaling parameters
+ * \todo Document which signaling variables are available
+ * */
+FT_DECLARE(ftdm_status_t) ftdm_call_add_var(ftdm_caller_data_t *caller_data, const char *var_name, const char *value);
+
+/*! \brief Get a custom variable from the call.
+ * \note The variable pointer returned is only valid during the callback receiving SIGEVENT. */
+FT_DECLARE(const char *) ftdm_call_get_var(ftdm_caller_data_t *caller_data, const char *var_name);
+
+/*! \brief Get an iterator to iterate over the channel variables
+ * \param caller_data The signal msg structure containing the variables
+ * \param iter Optional iterator. You can reuse an old iterator (not previously freed) to avoid the extra allocation of a new iterator.
+ * \note The iterator pointer returned is only valid while the signal message and it'll be destroyed when the signal message is processed.
+ * This iterator is completely non-thread safe, if you are adding variables or removing variables while iterating
+ * results are unpredictable
+ */
+FT_DECLARE(ftdm_iterator_t *) ftdm_call_get_var_iterator(const ftdm_caller_data_t *caller_data, ftdm_iterator_t *iter);
+
+/*! \brief Get variable name and value for the current iterator position */
+FT_DECLARE(ftdm_status_t) ftdm_call_get_current_var(ftdm_iterator_t *iter, const char **var_name, const char **var_val);
+
+/*! \brief Clear all variables attached to the call
+ * \note Variables are cleared at the end of each call back, so it is not necessary for the user to call this function.
+ * \todo Document which signaling variables are available
+ * */
+FT_DECLARE(ftdm_status_t) ftdm_call_clear_vars(ftdm_caller_data_t *caller_data);
+
+/*! \brief Remove a variable attached to the call
+ * \note Removes a variable that was attached to the call.
+ * \todo Document which call variables are available
+ * */
+FT_DECLARE(ftdm_status_t) ftdm_call_remove_var(ftdm_caller_data_t *caller_data, const char *var_name);
+
+/*! \brief Clears all the temporary data attached to this call
+ * \note Clears caller_data->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..bfec448253 100644
--- a/libs/freetdm/src/include/ftdm_declare.h
+++ b/libs/freetdm/src/include/ftdm_declare.h
@@ -158,12 +158,16 @@ typedef __int64 int64_t;
typedef __int32 int32_t;
typedef __int16 int16_t;
typedef __int8 int8_t;
+#define FTDM_O_BINARY O_BINARY
+#define FTDM_SIZE_FMT "Id"
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
#else
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
#endif /* _MSC_VER */
#else /* __WINDOWS__ */
+#define FTDM_O_BINARY 0
+#define FTDM_SIZE_FMT "zd"
#define FTDM_INVALID_SOCKET -1
typedef int ftdm_socket_t;
#include
@@ -171,6 +175,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 8bdbdd60f8..9222da3a42 100644
--- a/libs/freetdm/src/include/private/ftdm_core.h
+++ b/libs/freetdm/src/include/private/ftdm_core.h
@@ -222,6 +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)
/*!
\brief Copy flags from one arbitrary object to another
\command dest the object to copy the flags to
@@ -341,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;
@@ -365,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 {
@@ -422,7 +456,9 @@ struct ftdm_channel {
ftdm_fsk_data_state_t fsk;
uint8_t fsk_buf[80];
uint32_t ring_count;
- void *mod_data;
+ /* Private I/O data. Do not touch unless you are an I/O module */
+ void *io_data;
+ /* Private signaling data. Do not touch unless you are a signaling module */
void *call_data;
struct ftdm_caller_data caller_data;
struct ftdm_span *span;
@@ -437,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 {
@@ -454,6 +493,7 @@ struct ftdm_span {
ftdm_trunk_type_t trunk_type;
ftdm_analog_start_type_t start_type;
ftdm_signal_type_t signal_type;
+ /* Private signaling data. Do not touch unless you are a signaling module */
void *signal_data;
fio_signal_cb_t signal_cb;
ftdm_event_t event_header;
@@ -463,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;
@@ -471,7 +512,9 @@ struct ftdm_span {
ftdm_span_start_t start;
ftdm_span_stop_t stop;
ftdm_channel_sig_read_t sig_read;
- void *mod_data;
+ 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;
char *dtmf_hangup;
size_t dtmf_hangup_len;
@@ -556,7 +599,6 @@ FT_DECLARE(void) ftdm_channel_rotate_tokens(ftdm_channel_t *ftdmchan);
FT_DECLARE(int) ftdm_load_module(const char *name);
FT_DECLARE(int) ftdm_load_module_assume(const char *name);
FT_DECLARE(int) ftdm_vasprintf(char **ret, const char *fmt, va_list ap);
-FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan);
FT_DECLARE(ftdm_status_t) ftdm_span_close_all(void);
FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan);
@@ -631,10 +673,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 bddefd9be6..f03c060e5a 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
@@ -176,10 +177,16 @@ typedef enum {
FTDM_SPAN_USE_CHAN_QUEUE = (1 << 6),
FTDM_SPAN_SUGGEST_CHAN_ID = (1 << 7),
FTDM_SPAN_USE_AV_RATE = (1 << 8),
+ FTDM_SPAN_PWR_SAVING = (1 << 9),
/* If you use this flag, you MUST call ftdm_span_trigger_signals to deliver the user signals
* 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 << 9),
+ 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 */
@@ -193,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 {
@@ -202,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,
@@ -209,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,
@@ -218,12 +228,13 @@ typedef enum {
FTDM_CHANNEL_STATE_HANGUP,
FTDM_CHANNEL_STATE_HANGUP_COMPLETE,
FTDM_CHANNEL_STATE_IN_LOOP,
+ FTDM_CHANNEL_STATE_RESET,
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", \
- "HANGUP", "HANGUP_COMPLETE", "IN_LOOP", "INVALID"
+ "RING", "RINGING", "BUSY", "ATTN", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \
+ "RESTART", "PROCEED", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "CANCEL", \
+ "HANGUP", "HANGUP_COMPLETE", "IN_LOOP", "RESET", "INVALID"
FTDM_STR2ENUM_P(ftdm_str2ftdm_channel_state, ftdm_channel_state2str, ftdm_channel_state_t)
typedef enum {
@@ -257,6 +268,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
@@ -373,6 +387,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..b254a08bb8 100644
--- a/libs/freetdm/src/testsangomaboost.c
+++ b/libs/freetdm/src/testsangomaboost.c
@@ -45,10 +45,16 @@
#include
-#include "freetdm.h"
#include
#include
#include
+#if defined(__linux__) && !defined(__USE_BSD)
+#define __USE_BSD
+#endif
+#ifndef WIN32
+#include
+#endif
+#include "freetdm.h"
/* arbitrary limit for max calls in this sample program */
@@ -338,9 +344,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/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/openzap/mod_openzap/mod_openzap.c b/libs/openzap/mod_openzap/mod_openzap.c
index 8425372ef5..6a75dc85ff 100644
--- a/libs/openzap/mod_openzap/mod_openzap.c
+++ b/libs/openzap/mod_openzap/mod_openzap.c
@@ -821,7 +821,7 @@ static switch_status_t channel_receive_message_cas(switch_core_session_t *sessio
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_RINGING:
{
- if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS);
} else {
zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS);
@@ -830,7 +830,7 @@ static switch_status_t channel_receive_message_cas(switch_core_session_t *sessio
break;
case SWITCH_MESSAGE_INDICATE_PROGRESS:
{
- if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS);
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_MEDIA);
} else {
@@ -841,7 +841,7 @@ static switch_status_t channel_receive_message_cas(switch_core_session_t *sessio
break;
case SWITCH_MESSAGE_INDICATE_ANSWER:
{
- if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_ANSWERED);
} else {
/* lets make the ozmod_r2 module life easier by moving thru each
@@ -888,7 +888,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session,
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_RINGING:
{
- if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
zap_set_flag(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS);
} else {
zap_set_state_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS);
@@ -897,7 +897,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session,
break;
case SWITCH_MESSAGE_INDICATE_PROGRESS:
{
- if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
zap_set_flag(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS);
zap_set_flag(tech_pvt->zchan, ZAP_CHANNEL_MEDIA);
} else {
@@ -914,7 +914,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session,
break;
case SWITCH_MESSAGE_INDICATE_ANSWER:
{
- if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
zap_set_flag(tech_pvt->zchan, ZAP_CHANNEL_ANSWERED);
} else {
/* Don't skip messages in the ISDN call setup
@@ -957,7 +957,7 @@ static switch_status_t channel_receive_message_fxo(switch_core_session_t *sessio
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_PROGRESS:
case SWITCH_MESSAGE_INDICATE_ANSWER:
- if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_ANSWERED);
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS);
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_MEDIA);
@@ -991,7 +991,7 @@ static switch_status_t channel_receive_message_fxs(switch_core_session_t *sessio
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_PROGRESS:
case SWITCH_MESSAGE_INDICATE_ANSWER:
- if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_ANSWERED);
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS);
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_MEDIA);
@@ -1000,7 +1000,7 @@ static switch_status_t channel_receive_message_fxs(switch_core_session_t *sessio
}
break;
case SWITCH_MESSAGE_INDICATE_RINGING:
- if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
if (!switch_channel_test_flag(channel, CF_ANSWERED) &&
!switch_channel_test_flag(channel, CF_EARLY_MEDIA) &&
@@ -1052,7 +1052,7 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_PROGRESS:
case SWITCH_MESSAGE_INDICATE_ANSWER:
- if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
if ((var = switch_channel_get_variable(channel, "openzap_pre_buffer_size"))) {
int tmp = atoi(var);
if (tmp > -1) {
@@ -1327,7 +1327,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
tech_pvt->caller_profile = caller_profile;
- switch_channel_set_flag(channel, CF_OUTBOUND);
switch_channel_set_state(channel, CS_INIT);
if (zap_channel_add_token(zchan, switch_core_session_get_uuid(*new_session), zchan->token_count) != ZAP_SUCCESS) {
switch_core_session_destroy(new_session);
@@ -1678,7 +1677,9 @@ static ZIO_SIGNAL_CB_FUNCTION(on_fxs_signal)
switch_clear_flag_locked(tech_pvt, TFLAG_HOLD);
}
- if (channel_a && channel_b && !switch_channel_test_flag(channel_a, CF_OUTBOUND) && !switch_channel_test_flag(channel_b, CF_OUTBOUND)) {
+ if (channel_a && channel_b && switch_channel_direction(channel_a) == SWITCH_CALL_DIRECTION_INBOUND &&
+ switch_channel_direction(channel_b) == SWITCH_CALL_DIRECTION_INBOUND) {
+
cause = SWITCH_CAUSE_ATTENDED_TRANSFER;
if (br_a_uuid && br_b_uuid) {
switch_ivr_uuid_bridge(br_a_uuid, br_b_uuid);
diff --git a/libs/spandsp/src/spandsp.h.in b/libs/spandsp/src/spandsp.h.in
index 9167c1c2cc..eaed548c97 100644
--- a/libs/spandsp/src/spandsp.h.in
+++ b/libs/spandsp/src/spandsp.h.in
@@ -39,8 +39,9 @@
#include
#include
@INSERT_MATH_HEADER@
+#if !defined(SPANDSP_NO_TIFF)
#include
-
+#endif
#include
#include
#include
diff --git a/libs/stfu/stfu.c b/libs/stfu/stfu.c
index 7c30ab2ad4..b7df8ea870 100644
--- a/libs/stfu/stfu.c
+++ b/libs/stfu/stfu.c
@@ -27,57 +27,162 @@
*/
#include "stfu.h"
+//#define DB_JB 1
+
+#ifndef UINT_MAX
+# define UINT_MAX 4294967295U
+#endif
+
+#ifndef UINT16_MAX
+# define UINT16_MAX 65535
+#endif
+
#ifdef _MSC_VER
/* warning C4706: assignment within conditional expression*/
#pragma warning(disable: 4706)
+/* warning C4996: 'strdup': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strdup. See online help for details. */
+#pragma warning(disable:4996)
#endif
+#define least1(_z) (_z ? _z : 1)
+
+static int stfu_log_level = 7;
+
struct stfu_queue {
struct stfu_frame *array;
struct stfu_frame int_frame;
+ uint32_t real_array_size;
uint32_t array_size;
uint32_t array_len;
uint32_t wr_len;
+ uint32_t last_index;
+ int32_t last_jitter;
};
typedef struct stfu_queue stfu_queue_t;
struct stfu_instance {
struct stfu_queue a_queue;
struct stfu_queue b_queue;
+ struct stfu_queue c_queue;
struct stfu_queue *in_queue;
struct stfu_queue *out_queue;
+ struct stfu_queue *old_queue;
struct stfu_frame *last_frame;
+ uint32_t cur_ts;
uint32_t last_wr_ts;
uint32_t last_rd_ts;
- uint32_t interval;
+ uint32_t samples_per_packet;
+ uint32_t samples_per_second;
uint32_t miss_count;
uint32_t max_plc;
+ uint32_t qlen;
+ uint32_t max_qlen;
+ uint32_t orig_qlen;
+ uint32_t packet_count;
+ uint32_t consecutive_good_count;
+ uint32_t consecutive_bad_count;
+ uint32_t period_good_count;
+ uint32_t period_bad_count;
+ uint32_t period_packet_in_count;
+ uint32_t period_packet_out_count;
+ uint32_t period_missing_count;
+
+ uint32_t period_need_range;
+ uint32_t period_need_range_avg;
+ uint32_t period_clean_count;
+
+ uint32_t session_clean_count;
+ uint32_t session_missing_count;
+
+ uint32_t session_packet_in_count;
+ uint32_t session_packet_out_count;
+
+ uint32_t sync_out;
+ uint32_t sync_in;
+
+
+ int32_t ts_diff;
+ int32_t last_ts_diff;
+ int32_t same_ts;
+
+ uint32_t period_time;
+ uint32_t decrement_time;
+
+ uint32_t plc_len;
+ uint32_t plc_pt;
+ uint32_t diff;
+ uint32_t diff_total;
+ uint8_t ready;
+ uint8_t debug;
+
+ char *name;
+ stfu_n_call_me_t callback;
+ void *udata;
};
+static void stfu_n_reset_counters(stfu_instance_t *i);
+static void null_logger(const char *file, const char *func, int line, int level, const char *fmt, ...);
+static void default_logger(const char *file, const char *func, int line, int level, const char *fmt, ...);
+
+stfu_logger_t stfu_log = null_logger;
+
+void stfu_global_set_logger(stfu_logger_t logger)
+{
+ if (logger) {
+ stfu_log = logger;
+ } else {
+ stfu_log = null_logger;
+ }
+}
+
+void stfu_global_set_default_logger(int level)
+{
+ if (level < 0 || level > 7) {
+ level = 7;
+ }
+
+ stfu_log = default_logger;
+ stfu_log_level = level;
+}
+
+
static stfu_status_t stfu_n_resize_aqueue(stfu_queue_t *queue, uint32_t qlen)
{
unsigned char *m;
- if (qlen <= queue->array_size) {
- return STFU_IT_FAILED;;
+ if (qlen <= queue->real_array_size) {
+ queue->array_size = qlen;
+ if (queue->array_len > qlen) {
+ queue->array_len = qlen;
+ }
+ } else {
+ m = realloc(queue->array, qlen * sizeof(struct stfu_frame));
+ assert(m);
+ memset(m + queue->array_size * sizeof(struct stfu_frame), 0, (qlen * sizeof(struct stfu_frame)) - (queue->array_size * sizeof(struct stfu_frame)));
+ queue->array = (struct stfu_frame *) m;
+ queue->real_array_size = queue->array_size = qlen;
}
- m = realloc(queue->array, qlen * sizeof(struct stfu_frame));
- assert(m);
- memset(m + queue->array_size, 0, qlen * sizeof(struct stfu_frame) - queue->array_size);
- queue->array = (struct stfu_frame *) m;
- queue->array_size = qlen;
return STFU_IT_WORKED;
}
static void stfu_n_init_aqueue(stfu_queue_t *queue, uint32_t qlen)
{
+
queue->array = calloc(qlen, sizeof(struct stfu_frame));
assert(queue->array != NULL);
memset(queue->array, 0, sizeof(struct stfu_frame) * qlen);
- queue->array_size = qlen;
+ queue->real_array_size = queue->array_size = qlen;
queue->int_frame.plc = 1;
+ memset(queue->int_frame.data, 255, sizeof(queue->int_frame.data));
+}
+
+
+void stfu_n_call_me(stfu_instance_t *i, stfu_n_call_me_t callback, void *udata)
+{
+ i->callback = callback;
+ i->udata = udata;
}
void stfu_n_destroy(stfu_instance_t **i)
@@ -87,33 +192,66 @@ void stfu_n_destroy(stfu_instance_t **i)
if (i && *i) {
ii = *i;
*i = NULL;
+ if (ii->name) free(ii->name);
free(ii->a_queue.array);
free(ii->b_queue.array);
+ free(ii->c_queue.array);
free(ii);
}
}
+void stfu_n_debug(stfu_instance_t *i, const char *name)
+{
+ if (i->name) free(i->name);
+
+ if (name) {
+ i->name = strdup(name);
+ i->debug = 1;
+ } else {
+ i->name = strdup("none");
+ i->debug = 0;
+ }
+}
+
void stfu_n_report(stfu_instance_t *i, stfu_report_t *r)
{
assert(i);
- r->in_len = i->in_queue->array_len;
- r->in_size = i->in_queue->array_size;
- r->out_len = i->out_queue->array_len;
- r->out_size = i->out_queue->array_size;
+ r->qlen = i->qlen;
+ r->packet_in_count = i->period_packet_in_count;
+ r->clean_count = i->period_clean_count;
+ r->consecutive_good_count = i->consecutive_good_count;
+ r->consecutive_bad_count = i->consecutive_bad_count;
}
stfu_status_t stfu_n_resize(stfu_instance_t *i, uint32_t qlen)
{
stfu_status_t s;
+ if (i->qlen == i->max_qlen) {
+ return STFU_IT_FAILED;
+ }
+
+ if (i->max_qlen && qlen > i->max_qlen) {
+ if (i->qlen < i->max_qlen) {
+ qlen = i->max_qlen;
+ } else {
+ return STFU_IT_FAILED;
+ }
+ }
+
if ((s = stfu_n_resize_aqueue(&i->a_queue, qlen)) == STFU_IT_WORKED) {
s = stfu_n_resize_aqueue(&i->b_queue, qlen);
+ s = stfu_n_resize_aqueue(&i->c_queue, qlen);
+
+ i->qlen = qlen;
+ i->max_plc = 5;
+ i->last_frame = NULL;
}
return s;
}
-stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_plc)
+stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_per_packet, uint32_t samples_per_second)
{
struct stfu_instance *i;
@@ -122,116 +260,259 @@ stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_plc)
return NULL;
}
memset(i, 0, sizeof(*i));
+
+ i->qlen = qlen;
+ i->max_qlen = max_qlen;
+ i->orig_qlen = qlen;
+ i->samples_per_packet = samples_per_packet;
+
stfu_n_init_aqueue(&i->a_queue, qlen);
stfu_n_init_aqueue(&i->b_queue, qlen);
+ stfu_n_init_aqueue(&i->c_queue, qlen);
+
i->in_queue = &i->a_queue;
i->out_queue = &i->b_queue;
+ i->old_queue = &i->c_queue;
+ i->name = strdup("none");
+
+ i->max_plc = i->qlen / 2;
- if (max_plc) {
- i->max_plc = max_plc;
- } else {
- i->max_plc = qlen / 2;
- }
+ i->samples_per_second = samples_per_second ? samples_per_second : 8000;
+
+ i->period_time = ((i->samples_per_second * 20) / i->samples_per_packet);
+ i->decrement_time = ((i->samples_per_second * 15) / i->samples_per_packet);
return i;
}
+static void stfu_n_reset_counters(stfu_instance_t *i)
+{
+ if (stfu_log != null_logger && i->debug) {
+ stfu_log(STFU_LOG_EMERG, "%s COUNTER RESET........\n", i->name);
+ }
+
+ if (i->callback) {
+ i->callback(i, i->udata);
+ }
+
+ i->consecutive_good_count = 0;
+ i->consecutive_bad_count = 0;
+ i->period_good_count = 0;
+ i->period_clean_count = 0;
+ i->period_bad_count = 0;
+ i->period_packet_in_count = 0;
+ i->period_packet_out_count = 0;
+ i->period_missing_count = 0;
+
+ i->period_need_range = 0;
+ i->period_need_range_avg = 0;
+
+ i->diff = 0;
+ i->diff_total = 0;
+
+}
+
void stfu_n_reset(stfu_instance_t *i)
{
+ if (stfu_log != null_logger && i->debug) {
+ stfu_log(STFU_LOG_EMERG, "%s RESET\n", i->name);
+ }
+
+ i->ready = 0;
i->in_queue = &i->a_queue;
i->out_queue = &i->b_queue;
+ i->old_queue = &i->c_queue;
+
i->in_queue->array_len = 0;
i->out_queue->array_len = 0;
i->out_queue->wr_len = 0;
i->last_frame = NULL;
- i->miss_count = 0;
+ i->in_queue->last_jitter = 0;
+ i->out_queue->last_jitter = 0;
+
+
+ stfu_n_reset_counters(i);
+ stfu_n_sync(i, 1);
+
+ i->cur_ts = 0;
i->last_wr_ts = 0;
- i->miss_count = 0;
- i->interval = 0;
+ i->last_rd_ts = 0;
+ i->miss_count = 0;
+ i->packet_count = 0;
+
+
}
-static int32_t stfu_n_measure_interval(stfu_queue_t *queue)
+stfu_status_t stfu_n_sync(stfu_instance_t *i, uint32_t packets)
{
- uint32_t index;
- int32_t d, most = 0, last = 0, this, track[STFU_MAX_TRACK] = {0};
- for(index = 0; index < queue->array_len; index++) {
- this = queue->array[index].ts;
- if (last) {
+ if (packets > i->qlen) {
+ stfu_n_reset(i);
+ } else {
+ i->sync_out = packets;
+ i->sync_in = packets;
+ }
- if ((d = this - last) > 0 && d / 10 < STFU_MAX_TRACK) {
- track[(d/10)]++;
- }
- }
-
- last = this;
- }
-
- for(index = 0; index < STFU_MAX_TRACK; index++) {
- if (track[index] > track[most]) {
- most = index;
- }
- }
-
- return most * 10;
+ return STFU_IT_WORKED;
}
-static int16_t stfu_n_process(stfu_instance_t *i, stfu_queue_t *queue)
-{
- if (!i->interval && !(i->interval = stfu_n_measure_interval(queue))) {
- return -1;
- }
- return 0;
+static void stfu_n_swap(stfu_instance_t *i)
+{
+ stfu_queue_t *last_in = i->in_queue, *last_out = i->out_queue, *last_old = i->old_queue;
+
+ i->ready = 1;
+
+ i->in_queue = last_out;
+ i->out_queue = last_old;
+ i->old_queue = last_in;
+
+ i->in_queue->array_len = 0;
+ i->out_queue->wr_len = 0;
+ i->last_frame = NULL;
+ i->miss_count = 0;
+ i->in_queue->last_index = 0;
+ i->out_queue->last_index = 0;
+ i->out_queue->last_jitter = 0;
}
stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void *data, size_t datalen, int last)
{
- uint32_t index;
+ uint32_t index = 0;
stfu_frame_t *frame;
size_t cplen = 0;
+ int good_ts = 0;
+
+ if (!i->samples_per_packet && ts && i->last_rd_ts) {
+ i->ts_diff = ts - i->last_rd_ts;
+
+ if (i->last_ts_diff == i->ts_diff) {
+ if (++i->same_ts == 5) {
+ i->samples_per_packet = i->ts_diff;
+ }
+ } else {
+ i->same_ts = 0;
+ }
+
+ i->last_ts_diff = i->ts_diff;
+
+ if (!i->samples_per_packet) {
+ i->last_rd_ts = ts;
+ return STFU_IT_FAILED;
+ }
+ }
+
+ if (i->sync_in) {
+ good_ts = 1;
+ i->sync_in = 0;
+ } else {
+
+ if ((ts && ts == i->last_rd_ts + i->samples_per_packet) || (i->last_rd_ts > 4294900000 && ts < 5000)) {
+ good_ts = 1;
+ }
+
+ if (i->last_wr_ts) {
+ if ((ts <= i->last_wr_ts && (i->last_wr_ts != UINT_MAX || ts == i->last_wr_ts))) {
+ if (stfu_log != null_logger && i->debug) {
+ stfu_log(STFU_LOG_EMERG, "%s TOO LATE !!! %u \n\n\n", i->name, ts);
+ }
+ if (i->in_queue->array_len < i->in_queue->array_size) {
+ i->in_queue->array_len++;
+ }
+ return STFU_ITS_TOO_LATE;
+ }
+ }
+ }
+
+ if (good_ts) {
+ i->period_clean_count++;
+ i->session_clean_count++;
+ }
+
+ i->period_packet_in_count++;
+ i->session_packet_in_count++;
+
+ i->period_need_range_avg = i->period_need_range / least1(i->period_missing_count);
+
+ if (i->period_missing_count > i->qlen * 2) {
+ if (stfu_log != null_logger && i->debug) {
+ stfu_log(STFU_LOG_EMERG, "%s resize %u %u\n", i->name, i->qlen, i->qlen + 1);
+ }
+ stfu_n_resize(i, i->qlen + 1);
+ stfu_n_reset_counters(i);
+ } else {
+ if (i->qlen > i->orig_qlen && (i->consecutive_good_count > i->decrement_time || i->period_clean_count > i->decrement_time)) {
+ stfu_n_resize(i, i->qlen - 1);
+ stfu_n_reset_counters(i);
+ stfu_n_sync(i, i->qlen);
+ }
+ }
+
+
+ i->diff = 0;
+
+ if (i->last_wr_ts) {
+ if (ts < 1000 && i->last_wr_ts > (UINT_MAX - 1000)) {
+ i->diff = abs(((UINT_MAX - i->last_wr_ts) + ts) / i->samples_per_packet);
+ } else if (ts) {
+ i->diff = abs(i->last_wr_ts - ts) / i->samples_per_packet;
+ }
+ }
+
+ i->diff_total += i->diff;
+
+ if ((i->period_packet_in_count > i->period_time)) {
+ uint32_t avg;
+
+ avg = i->diff_total / least1(i->period_packet_in_count);
+
+ i->period_packet_in_count = 0;
+
+ if (i->period_missing_count == 0 && i->qlen > i->orig_qlen) {
+ stfu_n_resize(i, i->qlen - 1);
+ stfu_n_sync(i, i->qlen);
+ }
+
+ stfu_n_reset_counters(i);
+ }
+
+
+
+
+ if (stfu_log != null_logger && i->debug) {
+ stfu_log(STFU_LOG_EMERG, "%s %u i=%u/%u - g:%u/%u c:%u/%u b:%u - %u:%u - %u %d %u %u %d %d\n", i->name,
+ i->qlen, i->period_packet_in_count, i->period_time, i->consecutive_good_count,
+ i->decrement_time, i->period_clean_count, i->decrement_time, i->consecutive_bad_count,
+ ts, ts / i->samples_per_packet,
+ i->period_missing_count, i->period_need_range_avg,
+ i->last_wr_ts, ts, i->diff, i->diff_total / least1(i->period_packet_in_count));
+ }
if (last || i->in_queue->array_len == i->in_queue->array_size) {
- stfu_queue_t *other_queue;
-
- if (i->out_queue->wr_len < i->out_queue->array_len) {
- return STFU_IT_FAILED;
- }
-
- other_queue = i->in_queue;
- i->in_queue = i->out_queue;
- i->out_queue = other_queue;
-
- i->in_queue->array_len = 0;
- i->out_queue->wr_len = 0;
- i->last_frame = NULL;
- i->miss_count = 0;
-
- if (stfu_n_process(i, i->out_queue) < 0) {
- if (i->in_queue->array_len == i->in_queue->array_size && i->out_queue->array_len == i->out_queue->array_size) {
- stfu_n_resize(i, i->out_queue->array_size * 2);
- }
- //return STFU_IT_FAILED;
- }
- for(index = 0; index < i->out_queue->array_len; index++) {
- i->out_queue->array[index].was_read = 0;
- }
- }
+ stfu_n_swap(i);
+ }
if (last) {
return STFU_IM_DONE;
}
- index = i->in_queue->array_len++;
+ index = i->in_queue->array_len++;
+ assert(index < i->in_queue->array_size);
frame = &i->in_queue->array[index];
+ if (i->in_queue->array_len == i->in_queue->array_size) {
+ stfu_n_swap(i);
+ }
+
if ((cplen = datalen) > sizeof(frame->data)) {
cplen = sizeof(frame->data);
}
i->last_rd_ts = ts;
+ i->packet_count++;
memcpy(frame->data, data, cplen);
+
frame->pt = pt;
frame->ts = ts;
frame->dlen = cplen;
@@ -240,23 +521,51 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void
return STFU_IT_WORKED;
}
-static int stfu_n_find_frame(stfu_queue_t *queue, uint32_t ts, stfu_frame_t **r_frame, uint32_t *index)
+static int stfu_n_find_any_frame(stfu_instance_t *in, stfu_queue_t *queue, stfu_frame_t **r_frame)
{
uint32_t i = 0;
stfu_frame_t *frame = NULL;
assert(r_frame);
- assert(index);
*r_frame = NULL;
- for(i = 0; i < queue->array_len; i++) {
+ for(i = 0; i < queue->real_array_size; i++) {
+ frame = &queue->array[i];
+ if (!frame->was_read) {
+ *r_frame = frame;
+ queue->last_index = i;
+ frame->was_read = 1;
+ in->period_packet_out_count++;
+ in->session_packet_out_count++;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+static int stfu_n_find_frame(stfu_instance_t *in, stfu_queue_t *queue, uint32_t ts, stfu_frame_t **r_frame)
+{
+ uint32_t i = 0;
+ stfu_frame_t *frame = NULL;
+
+ if (r_frame) {
+ *r_frame = NULL;
+ }
+
+ for(i = 0; i < queue->array_size; i++) {
frame = &queue->array[i];
if (frame->ts == ts) {
- *r_frame = frame;
- *index = i;
- frame->was_read = 1;
+ if (r_frame) {
+ *r_frame = frame;
+ queue->last_index = i;
+ frame->was_read = 1;
+ in->period_packet_out_count++;
+ in->session_packet_out_count++;
+ }
return 1;
}
}
@@ -266,49 +575,300 @@ 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;
+ int found = 0;
- if (((i->out_queue->wr_len == i->out_queue->array_len) || !i->out_queue->array_len)) {
- return NULL;
- }
+ if (!i->samples_per_packet) {
+ return NULL;
+ }
+
+ if (!i->ready) {
+ if (stfu_log != null_logger && i->debug) {
+ stfu_log(STFU_LOG_EMERG, "%s XXXSKIP\n", i->name);
+ }
+ 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 (stfu_n_find_frame(i->out_queue, should_have, &rframe, &index) || stfu_n_find_frame(i->in_queue, should_have, &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;
+ if (i->cur_ts == 0 && i->last_wr_ts < 1000) {
+ uint32_t x = 0;
+ for (x = 0; x < i->out_queue->array_len; x++) {
+ if (!i->out_queue->array[x].was_read) {
+ i->cur_ts = i->out_queue->array[x].ts;
+ break;
+ }
+ if (i->cur_ts == 0) {
+ if (stfu_log != null_logger && i->debug) {
+ stfu_log(STFU_LOG_EMERG, "%s XXXPUNT\n", i->name);
+ return NULL;
+ }
+ }
+ }
} else {
- i->last_wr_ts = should_have;
- rframe = &i->out_queue->int_frame;
+ i->cur_ts = i->cur_ts + i->samples_per_packet;
+ }
+
+ found = stfu_n_find_frame(i, i->out_queue, i->cur_ts, &rframe);
- if (i->last_frame && i->last_frame != rframe) {
- rframe->dlen = i->last_frame->dlen;
- /* poor man's plc.. Copy the last frame, but we flag it so you can use a better one if you wish */
- memcpy(rframe->data, i->last_frame->data, rframe->dlen);
+ if (found) {
+ if (i->out_queue->array_len) {
+ i->out_queue->array_len--;
+ }
+ } else {
+ found = stfu_n_find_frame(i, i->in_queue, i->cur_ts, &rframe);
+
+ if (!found) {
+ found = stfu_n_find_frame(i, i->old_queue, i->cur_ts, &rframe);
+ }
+ }
+
+ if (i->sync_out) {
+ if (!found) {
+ if ((found = stfu_n_find_any_frame(i, i->out_queue, &rframe))) {
+ i->cur_ts = rframe->ts;
+ }
+
+ if (stfu_log != null_logger && i->debug) {
+ stfu_log(STFU_LOG_EMERG, "%s SYNC %u %u:%u\n", i->name, i->sync_out, i->cur_ts, i->cur_ts / i->samples_per_packet);
+ }
+
+ }
+ i->sync_out = 0;
+ }
+
+ if (!i->cur_ts) {
+ if (stfu_log != null_logger && i->debug) {
+ stfu_log(STFU_LOG_EMERG, "%s NO TS\n", i->name);
+ }
+ return NULL;
+ }
+
+
+ if (!found && i->samples_per_packet) {
+ uint32_t y;
+ stfu_frame_t *frame = NULL;
+
+ int32_t delay = i->last_rd_ts - i->cur_ts;
+ uint32_t need = abs(i->last_rd_ts - i->cur_ts) / i->samples_per_packet;
+
+
+ i->period_missing_count++;
+ i->session_missing_count++;
+ i->period_need_range += need;
+
+ if (stfu_log != null_logger && i->debug) {
+ stfu_log(STFU_LOG_EMERG, "%s MISSING %u:%u %u %u %d %u %d\n", i->name,
+ i->cur_ts, i->cur_ts / i->samples_per_packet, i->packet_count, i->last_rd_ts, delay, i->qlen, need);
}
- rframe->ts = should_have;
+ if (i->packet_count > i->orig_qlen * 100 && delay > 0 && need > i->qlen && need < (i->qlen + 5)) {
+ i->packet_count = 0;
+ }
- 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;
+ if (stfu_log != null_logger && i->debug) {
+ stfu_log(STFU_LOG_EMERG, "%s ", i->name);
+ for(y = 0; y < i->out_queue->array_size; y++) {
+ if ((y % 5) == 0) stfu_log(STFU_LOG_EMERG, "\n%s ", i->name);
+ frame = &i->out_queue->array[y];
+ stfu_log(STFU_LOG_EMERG, "%u:%u\t", frame->ts, frame->ts / i->samples_per_packet);
+ }
+ stfu_log(STFU_LOG_EMERG, "\n%s ", i->name);
+
+
+ for(y = 0; y < i->in_queue->array_size; y++) {
+ if ((y % 5) == 0) stfu_log(STFU_LOG_EMERG, "\n%s ", i->name);
+ frame = &i->in_queue->array[y];
+ stfu_log(STFU_LOG_EMERG, "%u:%u\t", frame->ts, frame->ts / i->samples_per_packet);
+ }
+ stfu_log(STFU_LOG_EMERG, "\n%s\n\n\n", i->name);
+
+ }
+
+ if (delay < 0) {
+ stfu_n_reset(i);
+ return NULL;
+ }
+ }
+
+ if (stfu_log != null_logger && i->debug) {
+ if (found) {
+ stfu_log(STFU_LOG_EMERG, "%s O: %u:%u %u\n", i->name, rframe->ts, rframe->ts / i->samples_per_packet, rframe->plc);
+ }
+ }
+
+ if (found) {
+ i->consecutive_good_count++;
+ i->period_good_count++;
+ i->consecutive_bad_count = 0;
+ } else {
+ i->consecutive_bad_count++;
+ i->period_bad_count++;
+ i->consecutive_good_count = 0;
+ }
+
+ if (found) {
+ i->last_frame = rframe;
+ i->out_queue->wr_len++;
+ i->last_wr_ts = rframe->ts;
+
+ i->miss_count = 0;
+ if (rframe->dlen) {
+ i->plc_len = rframe->dlen;
+ }
+
+ i->plc_pt = rframe->pt;
+
+ } else {
+ i->last_wr_ts = i->cur_ts;
+ rframe = &i->out_queue->int_frame;
+ rframe->dlen = i->plc_len;
+ rframe->pt = i->plc_pt;
+ rframe->ts = i->cur_ts;
+ i->miss_count++;
+
+ if (stfu_log != null_logger && i->debug) {
+ stfu_log(STFU_LOG_EMERG, "%s PLC %d %d %ld %u:%u\n", i->name,
+ i->miss_count, rframe->plc, rframe->dlen, rframe->ts, rframe->ts / i->samples_per_packet);
+ }
+
+ if (i->miss_count > i->max_plc) {
+ stfu_n_reset(i);
rframe = NULL;
}
}
- return rframe;
+ return rframe;
}
+#ifdef WIN32
+#ifndef vsnprintf
+#define vsnprintf _vsnprintf
+#endif
+#endif
+
+
+int vasprintf(char **ret, const char *format, va_list ap);
+
+int stfu_vasprintf(char **ret, const char *fmt, va_list ap)
+{
+#if !defined(WIN32) && !defined(__sun)
+ return vasprintf(ret, fmt, ap);
+#else
+ char *buf;
+ int len;
+ size_t buflen;
+ va_list ap2;
+ char *tmp = NULL;
+
+#ifdef _MSC_VER
+#if _MSC_VER >= 1500
+ /* hack for incorrect assumption in msvc header files for code analysis */
+ __analysis_assume(tmp);
+#endif
+ ap2 = ap;
+#else
+ va_copy(ap2, ap);
+#endif
+
+ len = vsnprintf(tmp, 0, fmt, ap2);
+
+ if (len > 0 && (buf = malloc((buflen = (size_t) (len + 1)))) != NULL) {
+ len = vsnprintf(buf, buflen, fmt, ap);
+ *ret = buf;
+ } else {
+ *ret = NULL;
+ len = -1;
+ }
+
+ va_end(ap2);
+ return len;
+#endif
+}
+
+
+
+
+int stfu_snprintf(char *buffer, size_t count, const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = vsnprintf(buffer, count-1, fmt, ap);
+ if (ret < 0)
+ buffer[count-1] = '\0';
+ va_end(ap);
+ return ret;
+}
+
+static void null_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
+{
+ if (file && func && line && level && fmt) {
+ return;
+ }
+ return;
+}
+
+
+
+static const char *LEVEL_NAMES[] = {
+ "EMERG",
+ "ALERT",
+ "CRIT",
+ "ERROR",
+ "WARNING",
+ "NOTICE",
+ "INFO",
+ "DEBUG",
+ NULL
+};
+
+static const char *cut_path(const char *in)
+{
+ const char *p, *ret = in;
+ char delims[] = "/\\";
+ char *i;
+
+ for (i = delims; *i; i++) {
+ p = in;
+ while ((p = strchr(p, *i)) != 0) {
+ ret = ++p;
+ }
+ }
+ return ret;
+}
+
+
+static void default_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
+{
+ const char *fp;
+ char *data;
+ va_list ap;
+ int ret;
+
+ if (level < 0 || level > 7) {
+ level = 7;
+ }
+ if (level > stfu_log_level) {
+ return;
+ }
+
+ fp = cut_path(file);
+
+ va_start(ap, fmt);
+
+ ret = stfu_vasprintf(&data, fmt, ap);
+
+ if (ret != -1) {
+ fprintf(stderr, "[%s] %s:%d %s() %s", LEVEL_NAMES[level], file, line, func, data);
+ free(data);
+ }
+
+ va_end(ap);
+
+}
+
+
/* For Emacs:
* Local Variables:
* mode:c
diff --git a/libs/stfu/stfu.h b/libs/stfu/stfu.h
index 900db6f9ac..ad769c62e2 100644
--- a/libs/stfu/stfu.h
+++ b/libs/stfu/stfu.h
@@ -38,6 +38,8 @@ extern "C" {
#include
#include
#include
+#include
+
#ifdef _MSC_VER
#ifndef uint32_t
@@ -62,6 +64,85 @@ typedef unsigned long in_addr_t;
#endif
#include
+
+
+#ifdef WIN32
+#include
+#include
+typedef SOCKET stfu_socket_t;
+typedef unsigned __int64 uint64_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int8 uint8_t;
+typedef __int64 int64_t;
+typedef __int32 int32_t;
+typedef __int16 int16_t;
+typedef __int8 int8_t;
+typedef intptr_t stfu_ssize_t;
+typedef int stfu_filehandle_t;
+#define STFU_SOCK_INVALID INVALID_SOCKET
+#define strerror_r(num, buf, size) strerror_s(buf, size, num)
+#if defined(STFU_DECLARE_STATIC)
+#define STFU_DECLARE(type) type __stdcall
+#define STFU_DECLARE_NONSTD(type) type __cdecl
+#define STFU_DECLARE_DATA
+#elif defined(STFU_EXPORTS)
+#define STFU_DECLARE(type) __declspec(dllexport) type __stdcall
+#define STFU_DECLARE_NONSTD(type) __declspec(dllexport) type __cdecl
+#define STFU_DECLARE_DATA __declspec(dllexport)
+#else
+#define STFU_DECLARE(type) __declspec(dllimport) type __stdcall
+#define STFU_DECLARE_NONSTD(type) __declspec(dllimport) type __cdecl
+#define STFU_DECLARE_DATA __declspec(dllimport)
+#endif
+#else
+#define STFU_DECLARE(type) type
+#define STFU_DECLARE_NONSTD(type) type
+#define STFU_DECLARE_DATA
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#define STFU_SOCK_INVALID -1
+typedef int stfu_socket_t;
+typedef ssize_t stfu_ssize_t;
+typedef int stfu_filehandle_t;
+#endif
+
+
+#define STFU_PRE __FILE__, __FUNCTION__, __LINE__
+#define STFU_LOG_LEVEL_DEBUG 7
+#define STFU_LOG_LEVEL_INFO 6
+#define STFU_LOG_LEVEL_NOTICE 5
+#define STFU_LOG_LEVEL_WARNING 4
+#define STFU_LOG_LEVEL_ERROR 3
+#define STFU_LOG_LEVEL_CRIT 2
+#define STFU_LOG_LEVEL_ALERT 1
+#define STFU_LOG_LEVEL_EMERG 0
+
+#define STFU_LOG_DEBUG STFU_PRE, STFU_LOG_LEVEL_DEBUG
+#define STFU_LOG_INFO STFU_PRE, STFU_LOG_LEVEL_INFO
+#define STFU_LOG_NOTICE STFU_PRE, STFU_LOG_LEVEL_NOTICE
+#define STFU_LOG_WARNING STFU_PRE, STFU_LOG_LEVEL_WARNING
+#define STFU_LOG_ERROR STFU_PRE, STFU_LOG_LEVEL_ERROR
+#define STFU_LOG_CRIT STFU_PRE, STFU_LOG_LEVEL_CRIT
+#define STFU_LOG_ALERT STFU_PRE, STFU_LOG_LEVEL_ALERT
+#define STFU_LOG_EMERG STFU_PRE, STFU_LOG_LEVEL_EMERG
+typedef void (*stfu_logger_t)(const char *file, const char *func, int line, int level, const char *fmt, ...);
+
+
+int stfu_vasprintf(char **ret, const char *fmt, va_list ap);
+
+extern stfu_logger_t stfu_log;
+
+/*! Sets the logger for libstfu. Default is the null_logger */
+void stfu_global_set_logger(stfu_logger_t logger);
+/*! Sets the default log level for libstfu */
+void stfu_global_set_default_logger(int level);
+
#define STFU_DATALEN 16384
#define STFU_QLEN 300
#define STFU_MAX_TRACK 256
@@ -69,7 +150,8 @@ typedef unsigned long in_addr_t;
typedef enum {
STFU_IT_FAILED,
STFU_IT_WORKED,
- STFU_IM_DONE
+ STFU_IM_DONE,
+ STFU_ITS_TOO_LATE
} stfu_status_t;
struct stfu_frame {
@@ -86,21 +168,25 @@ struct stfu_instance;
typedef struct stfu_instance stfu_instance_t;
typedef struct {
- uint32_t in_len;
- uint32_t in_size;
- uint32_t out_len;
- uint32_t out_size;
-
+ uint32_t qlen;
+ uint32_t packet_in_count;
+ uint32_t clean_count;
+ uint32_t consecutive_good_count;
+ uint32_t consecutive_bad_count;
} stfu_report_t;
+typedef void (*stfu_n_call_me_t)(stfu_instance_t *i, void *);
void stfu_n_report(stfu_instance_t *i, stfu_report_t *r);
void stfu_n_destroy(stfu_instance_t **i);
-stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_plc);
+stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_per_packet, uint32_t samples_per_second);
stfu_status_t stfu_n_resize(stfu_instance_t *i, uint32_t qlen);
stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void *data, size_t datalen, int last);
stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i);
void stfu_n_reset(stfu_instance_t *i);
+stfu_status_t stfu_n_sync(stfu_instance_t *i, uint32_t packets);
+void stfu_n_call_me(stfu_instance_t *i, stfu_n_call_me_t callback, void *udata);
+void stfu_n_debug(stfu_instance_t *i, const char *name);
#define stfu_im_done(i) stfu_n_add_data(i, 0, NULL, 0, 1)
#define stfu_n_eat(i,t,p,d,l) stfu_n_add_data(i, t, p, d, l, 0)
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..422d5f2930 100644
--- a/src/include/private/switch_core_pvt.h
+++ b/src/include/private/switch_core_pvt.h
@@ -31,7 +31,8 @@
* this file does not exist!!!!
*
*/
-
+#define SPANDSP_NO_TIFF 1
+#include "spandsp.h"
#include "switch_profile.h"
#ifndef WIN32
@@ -135,6 +136,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;
@@ -168,6 +170,7 @@ struct switch_core_session {
switch_log_level_t loglevel;
uint32_t soft_lock;
switch_ivr_dmachine_t *dmachine;
+ plc_state_t *plc;
};
struct switch_media_bug {
diff --git a/src/include/switch_apr.h b/src/include/switch_apr.h
index f82b81a7f8..d89a13bb30 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
*
@@ -1094,6 +1110,8 @@ SWITCH_DECLARE(int) switch_sockaddr_equal(const switch_sockaddr_t *sa1, const sw
SWITCH_DECLARE(switch_status_t) switch_sockaddr_info_get(switch_sockaddr_t ** sa, const char *hostname,
int32_t family, switch_port_t port, int32_t flags, switch_memory_pool_t *pool);
+SWITCH_DECLARE(switch_status_t) switch_sockaddr_create(switch_sockaddr_t **sa, switch_memory_pool_t *pool);
+
/**
* Send data over a network.
* @param sock The socket to send the data over.
diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h
index a1f13edd85..e726554d81 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
*/
@@ -312,6 +312,8 @@ SWITCH_DECLARE(switch_status_t) switch_channel_caller_extension_masquerade(switc
*/
SWITCH_DECLARE(void) switch_channel_set_caller_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension);
+SWITCH_DECLARE(void) switch_channel_sort_cid(switch_channel_t *channel, switch_bool_t in);
+
/*!
\brief Retrieve caller extension from a given channel
\param channel channel to retrieve extension from
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/include/switch_rtp.h b/src/include/switch_rtp.h
index 7269a2b8d9..c48a40e6d1 100644
--- a/src/include/switch_rtp.h
+++ b/src/include/switch_rtp.h
@@ -229,7 +229,14 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_rtcp(switch_rtp_t *rtp_sessi
\param queue_frames the number of frames to delay
\return SWITCH_STATUS_SUCCESS
*/
-SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t *rtp_session, uint32_t queue_frames);
+SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t *rtp_session,
+ uint32_t queue_frames,
+ uint32_t max_queue_frames,
+ uint32_t samples_per_packet, uint32_t samples_per_second);
+
+SWITCH_DECLARE(switch_status_t) switch_rtp_debug_jitter_buffer(switch_rtp_t *rtp_session, const char *name);
+
+SWITCH_DECLARE(switch_status_t) switch_rtp_deactivate_jitter_buffer(switch_rtp_t *rtp_session);
/*!
\brief Set an RTP Flag
diff --git a/src/include/switch_types.h b/src/include/switch_types.h
index c01638089f..e04f437eb3 100644
--- a/src/include/switch_types.h
+++ b/src/include/switch_types.h
@@ -790,6 +790,7 @@ typedef enum {
SWITCH_MESSAGE_INDICATE_T38_DESCRIPTION,
SWITCH_MESSAGE_INDICATE_UDPTL_MODE,
SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS,
+ SWITCH_MESSAGE_INDICATE_JITTER_BUFFER,
SWITCH_MESSAGE_INVALID
} switch_core_session_message_types_t;
@@ -1093,6 +1094,8 @@ typedef enum {
CF_PASSTHRU_PTIME_MISMATCH,
CF_BRIDGE_NOWRITE,
CF_RECOVERED,
+ CF_JITTERBUFFER,
+ CF_DIALPLAN,
/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
CF_FLAG_MAX
} switch_channel_flag_t;
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 ba4b6d310d..dba86e3103 100644
--- a/src/mod/applications/mod_commands/mod_commands.c
+++ b/src/mod/applications/mod_commands/mod_commands.c
@@ -2491,24 +2491,101 @@ 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 {
+ stream->write_function(stream, "-ERR Operation Failed\n");
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+#define JITTERBUFFER_SYNTAX " [0|[:]]"
+SWITCH_STANDARD_API(uuid_jitterbuffer_function)
+{
+ char *mydata = NULL, *argv[2] = { 0 };
+ int argc = 0;
+
+ switch_status_t status = SWITCH_STATUS_FALSE;
+
+ if (zstr(cmd)) {
+ goto error;
+ }
+
+ mydata = strdup(cmd);
+ switch_assert(mydata);
+
+ argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+
+ if (argc < 2) {
+ goto error;
+ }
+ if (argv[1]) {
+ switch_core_session_message_t msg = { 0 };
+ switch_core_session_t *lsession = NULL;
+
+ msg.message_id = SWITCH_MESSAGE_INDICATE_JITTER_BUFFER;
+ msg.string_arg = argv[1];
+ msg.from = __FILE__;
+
+ 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", JITTERBUFFER_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 +4045,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)
{
@@ -4214,21 +4332,33 @@ SWITCH_STANDARD_API(strftime_tz_api_function)
char *format = NULL;
const char *tz_name = NULL;
char date[80] = "";
+ char *mycmd = NULL, *p;
+ switch_time_t when = 0;
- if (!zstr(cmd)) {
- format = strchr(cmd, ' ');
- tz_name = cmd;
- if (format) {
+ if (cmd) mycmd = strdup(cmd);
+
+ if (!zstr(mycmd)) {
+ tz_name = mycmd;
+
+ if ((format = strchr(mycmd, ' '))) {
*format++ = '\0';
}
+
+ if ((p = strchr(format, '|'))) {
+ *p++ = '\0';
+ when = atol(format);
+ format = p;
+ }
}
- if (switch_strftime_tz(tz_name, format, date, sizeof(date), 0) == SWITCH_STATUS_SUCCESS) { /* The lookup of the zone may fail. */
+ if (switch_strftime_tz(tz_name, format, date, sizeof(date), when * 1000000) == SWITCH_STATUS_SUCCESS) { /* The lookup of the zone may fail. */
stream->write_function(stream, "%s", date);
} else {
stream->write_function(stream, "-ERR Invalid Timezone\n");
}
+ switch_safe_free(mycmd);
+
return SWITCH_STATUS_SUCCESS;
}
@@ -4651,7 +4781,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
SWITCH_ADD_API(commands_api_interface, "show", "Show", show_function, SHOW_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "sql_escape", "Escape a string to prevent sql injection", sql_escape, SQL_ESCAPE_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "status", "status", status_function, "");
- SWITCH_ADD_API(commands_api_interface, "strftime_tz", "strftime_tz", strftime_tz_api_function, " [format string]");
+ SWITCH_ADD_API(commands_api_interface, "strftime_tz", "strftime_tz", strftime_tz_api_function, " [|][format string]");
SWITCH_ADD_API(commands_api_interface, "stun", "stun", stun_function, "[:port]");
SWITCH_ADD_API(commands_api_interface, "system", "Execute a system command", system_function, SYSTEM_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "time_test", "time_test", time_test_function, " [count]");
@@ -4674,6 +4804,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);
@@ -4693,6 +4824,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
SWITCH_ADD_API(commands_api_interface, "uuid_transfer", "Transfer a session", transfer_function, TRANSFER_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_dual_transfer", "Transfer a session and its partner", dual_transfer_function, DUAL_TRANSFER_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_simplify", "Try to cut out of a call path / attended xfer", uuid_simplify_function, SIMPLIFY_SYNTAX);
+ SWITCH_ADD_API(commands_api_interface, "uuid_jitterbuffer", "Try to cut out of a call path / attended xfer",
+ uuid_jitterbuffer_function, JITTERBUFFER_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "xml_locate", "find some xml", xml_locate_function, "[root | ]");
SWITCH_ADD_API(commands_api_interface, "xml_wrap", "Wrap another api command in xml", xml_wrap_api_function, " ");
switch_console_set_complete("add alias add");
@@ -4785,9 +4918,11 @@ 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");
+ switch_console_set_complete("add uuid_jitterbuffer ::console::list_uuid");
switch_console_set_complete("add uuid_kill ::console::list_uuid");
switch_console_set_complete("add uuid_limit_release ::console::list_uuid");
switch_console_set_complete("add uuid_loglevel ::console::list_uuid console");
@@ -4810,6 +4945,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_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c
index 4cbb052994..53ce82b4cb 100644
--- a/src/mod/applications/mod_conference/mod_conference.c
+++ b/src/mod/applications/mod_conference/mod_conference.c
@@ -2456,7 +2456,7 @@ static void conference_loop_output(conference_member_t *member)
switch_event_destroy(&event);
}
- if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
/* test to see if outbound channel has answered */
if (switch_channel_test_flag(channel, CF_ANSWERED) && !switch_test_flag(member->conference, CFLAG_ANSWERED)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG,
@@ -2599,7 +2599,7 @@ static void conference_loop_output(conference_member_t *member)
switch_channel_cause2str(switch_channel_get_cause(channel)));
/* if it's an outbound channel, store the release cause in the conference struct, we might need it */
- if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
member->conference->bridge_hangup_cause = switch_channel_get_cause(channel);
}
@@ -4366,6 +4366,8 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc
}
}
+ switch_channel_set_variable(channel, "last_transfered_conference", argv[2]);
+
unlock_member(member);
stream->write_function(stream, "OK Member '%d' sent to conference %s.\n", member->id, argv[2]);
@@ -5374,6 +5376,14 @@ SWITCH_STANDARD_APP(conference_function)
}
#endif
+ if (switch_channel_test_flag(channel, CF_RECOVERED)) {
+ const char *check = switch_channel_get_variable(channel, "last_transfered_conference");
+
+ if (!zstr(check)) {
+ conf_name = (char *) check;
+ }
+ }
+
switch_event_create(¶ms, SWITCH_EVENT_COMMAND);
switch_assert(params);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "conf_name", conf_name);
@@ -5436,7 +5446,7 @@ SWITCH_STANDARD_APP(conference_function)
launch_conference_thread(conference);
} else {
- int enforce_security = !switch_channel_test_flag(channel, CF_OUTBOUND);
+ int enforce_security = switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND;
const char *pvar = switch_channel_get_variable(channel, "conference_enforce_security");
if (pvar) {
@@ -5645,7 +5655,7 @@ SWITCH_STANDARD_APP(conference_function)
} else {
/* if we're not using "bridge:" set the conference answered flag */
/* and this isn't an outbound channel, answer the call */
- if (!switch_channel_test_flag(channel, CF_OUTBOUND))
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND)
switch_set_flag(conference, CFLAG_ANSWERED);
}
diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c
index 4fd6a676ea..e508486380 100755
--- a/src/mod/applications/mod_dptools/mod_dptools.c
+++ b/src/mod/applications/mod_dptools/mod_dptools.c
@@ -269,7 +269,7 @@ SWITCH_STANDARD_APP(bind_digit_action_function)
}
-#define DETECT_SPEECH_SYNTAX " [] OR grammar [] OR pause OR resume"
+#define DETECT_SPEECH_SYNTAX " [] OR grammar [] OR nogrammar OR pause OR resume OR stop OR param "
SWITCH_STANDARD_APP(detect_speech_function)
{
char *argv[4];
@@ -957,6 +957,17 @@ SWITCH_STANDARD_APP(redirect_function)
switch_core_session_receive_message(session, &msg);
}
+SWITCH_STANDARD_APP(jitterbuffer_function)
+{
+ switch_core_session_message_t msg = { 0 };
+
+ /* Tell the channel to change the jitter buffer */
+ msg.from = __FILE__;
+ msg.string_arg = data;
+ msg.message_id = SWITCH_MESSAGE_INDICATE_JITTER_BUFFER;
+ switch_core_session_receive_message(session, &msg);
+}
+
SWITCH_STANDARD_APP(display_function)
{
switch_core_session_message_t msg = { 0 };
@@ -1303,13 +1314,22 @@ SWITCH_STANDARD_API(strftime_api_function)
char date[80] = "";
switch_time_t thetime;
char *p;
- if (!zstr(cmd) && (p = strchr(cmd, '|'))) {
- thetime = switch_time_make(atoi(cmd), 0);
+ char *mycmd = NULL;
+
+ if (!zstr(cmd)) {
+ mycmd = strdup(cmd);
+ }
+
+ if (!zstr(mycmd) && (p = strchr(cmd, '|'))) {
+ *p++ = '\0';
+
+ thetime = switch_time_make(atol(cmd), 0);
cmd = p + 1;
} else {
thetime = switch_micro_time_now();
}
switch_time_exp_lt(&tm, thetime);
+
if (zstr(cmd)) {
switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
} else {
@@ -3513,6 +3533,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SWITCH_ADD_APP(app_interface, "ivr", "Run an ivr menu", "Run an ivr menu.", ivr_application_function, "", SAF_NONE);
SWITCH_ADD_APP(app_interface, "redirect", "Send session redirect", "Send a redirect message to a session.", redirect_function, "",
SAF_SUPPORT_NOMEDIA);
+ SWITCH_ADD_APP(app_interface, "jitterbuffer", "Send session jitterbuffer", "Send a jitterbuffer message to a session.",
+ jitterbuffer_function, "", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "send_display", "Send session a new display", "Send session a new display.", display_function, "",
SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "respond", "Send session respond", "Send a respond message to a session.", respond_function, "",
diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c
index 3943ac6ea6..9d9896956e 100644
--- a/src/mod/applications/mod_fifo/mod_fifo.c
+++ b/src/mod/applications/mod_fifo/mod_fifo.c
@@ -291,6 +291,7 @@ static switch_status_t fifo_queue_popfly(fifo_queue_t *queue, const char *uuid)
struct fifo_node {
char *name;
switch_mutex_t *mutex;
+ switch_mutex_t *update_mutex;
fifo_queue_t *fifo_list[MAX_PRI];
switch_hash_t *consumer_hash;
int outbound_priority;
@@ -801,6 +802,7 @@ static fifo_node_t *create_node(const char *name, uint32_t importance, switch_mu
switch_core_hash_init(&node->consumer_hash, node->pool);
switch_thread_rwlock_create(&node->rwlock, node->pool);
switch_mutex_init(&node->mutex, SWITCH_MUTEX_NESTED, node->pool);
+ switch_mutex_init(&node->update_mutex, SWITCH_MUTEX_NESTED, node->pool);
cbt.buf = outbound_count;
cbt.len = sizeof(outbound_count);
sql = switch_mprintf("select count(*) from fifo_outbound where fifo_name = '%q'", name);
@@ -1193,10 +1195,10 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void
if (node) {
- switch_thread_rwlock_wrlock(node->rwlock);
+ switch_mutex_lock(node->update_mutex);
node->busy = 0;
node->ring_consumer_count = 1;
- switch_thread_rwlock_unlock(node->rwlock);
+ switch_mutex_unlock(node->update_mutex);
} else {
goto end;
}
@@ -1437,10 +1439,10 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void
cbh->ready = 1;
if (node) {
- switch_thread_rwlock_wrlock(node->rwlock);
+ switch_mutex_lock(node->update_mutex);
node->ring_consumer_count = 0;
node->busy = 0;
- switch_thread_rwlock_unlock(node->rwlock);
+ switch_mutex_unlock(node->update_mutex);
}
@@ -1501,10 +1503,10 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj)
switch_mutex_unlock(globals.mutex);
if (node) {
- switch_thread_rwlock_wrlock(node->rwlock);
+ switch_mutex_lock(node->update_mutex);
node->ring_consumer_count++;
node->busy = 0;
- switch_thread_rwlock_unlock(node->rwlock);
+ switch_mutex_unlock(node->update_mutex);
}
switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS);
@@ -1601,12 +1603,12 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj)
switch_event_destroy(&ovars);
if (node) {
- switch_thread_rwlock_wrlock(node->rwlock);
+ switch_mutex_lock(node->update_mutex);
if (node->ring_consumer_count-- < 0) {
node->ring_consumer_count = 0;
}
node->busy = 0;
- switch_thread_rwlock_unlock(node->rwlock);
+ switch_mutex_unlock(node->update_mutex);
}
switch_core_destroy_memory_pool(&h->pool);
@@ -1754,9 +1756,35 @@ static void *SWITCH_THREAD_FUNC node_thread_run(switch_thread_t *thread, void *o
if (globals.debug) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Trying priority: %d\n", cur_priority);
+ restart:
+
for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &var, NULL, &val);
if ((node = (fifo_node_t *) val)) {
+
+ if (node->ready == FIFO_DELAY_DESTROY) {
+ int doit = 0;
+
+ switch_mutex_lock(node->update_mutex);
+ doit = node->consumer_count == 0 && node_caller_count(node) == 0;
+ switch_mutex_unlock(node->update_mutex);
+
+ if (doit) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "%s removed.\n", node->name);
+ switch_core_hash_delete(globals.fifo_hash, node->name);
+
+ node->ready = 0;
+ switch_mutex_lock(node->mutex);
+ switch_core_hash_destroy(&node->consumer_hash);
+ switch_mutex_unlock(node->mutex);
+ switch_mutex_unlock(node->update_mutex);
+ switch_core_destroy_memory_pool(&node->pool);
+ goto restart;
+ }
+
+ }
+
+
if (node->outbound_priority == 0) node->outbound_priority = 5;
if (node->has_outbound && node->ready && !node->busy && node->outbound_priority == cur_priority) {
ppl_waiting = node_caller_count(node);
@@ -2219,6 +2247,7 @@ SWITCH_STANDARD_APP(fifo_function)
if (!(node = switch_core_hash_find(globals.fifo_hash, nlist[i]))) {
node = create_node(nlist[i], importance, globals.sql_mutex);
node->ready = 1;
+ switch_thread_rwlock_rdlock(node->rwlock);
}
node_list[node_count++] = node;
}
@@ -2306,7 +2335,7 @@ SWITCH_STANDARD_APP(fifo_function)
switch_channel_answer(channel);
- switch_thread_rwlock_wrlock(node->rwlock);
+ switch_mutex_lock(node->update_mutex);
if ((pri = switch_channel_get_variable(channel, "fifo_priority"))) {
p = atoi(pri);
@@ -2344,7 +2373,7 @@ SWITCH_STANDARD_APP(fifo_function)
switch_channel_set_variable(channel, "fifo_priority", tmp);
}
- switch_thread_rwlock_unlock(node->rwlock);
+ switch_mutex_unlock(node->update_mutex);
ts = switch_micro_time_now();
switch_time_exp_lt(&tm, ts);
@@ -2450,9 +2479,9 @@ SWITCH_STANDARD_APP(fifo_function)
}
switch_mutex_lock(globals.mutex);
- switch_thread_rwlock_wrlock(node->rwlock);
+ switch_mutex_lock(node->update_mutex);
node_remove_uuid(node, uuid);
- switch_thread_rwlock_unlock(node->rwlock);
+ switch_mutex_unlock(node->update_mutex);
send_presence(node);
check_cancel(node);
switch_mutex_unlock(globals.mutex);
@@ -2682,9 +2711,9 @@ SWITCH_STANDARD_APP(fifo_function)
}
if (pop && !node_caller_count(node)) {
- switch_thread_rwlock_wrlock(node->rwlock);
+ switch_mutex_lock(node->update_mutex);
node->start_waiting = 0;
- switch_thread_rwlock_unlock(node->rwlock);
+ switch_mutex_unlock(node->update_mutex);
}
}
@@ -3074,21 +3103,9 @@ SWITCH_STANDARD_APP(fifo_function)
done:
- switch_mutex_lock(globals.mutex);
- if (node && node->ready == FIFO_DELAY_DESTROY && node->consumer_count == 0 && node_caller_count(node) == 0) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "%s removed.\n", node->name);
- switch_core_hash_delete(globals.fifo_hash, node->name);
- switch_thread_rwlock_wrlock(node->rwlock);
- node->ready = 0;
- switch_mutex_lock(node->mutex);
- switch_core_hash_destroy(&node->consumer_hash);
- switch_mutex_unlock(node->mutex);
+ if (node) {
switch_thread_rwlock_unlock(node->rwlock);
- switch_core_destroy_memory_pool(&node->pool);
-
}
- switch_mutex_unlock(globals.mutex);
-
switch_channel_clear_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_BRIDGE_TAG);
@@ -3699,9 +3716,9 @@ SWITCH_STANDARD_API(fifo_api_function)
switch_hash_this(hi, &var, NULL, &val);
node = (fifo_node_t *) val;
len = node_caller_count(node);
- switch_thread_rwlock_wrlock(node->rwlock);
+ switch_mutex_lock(node->update_mutex);
stream->write_function(stream, "%s:%d:%d:%d\n", (char *) var, node->consumer_count, node_caller_count(node), len);
- switch_thread_rwlock_unlock(node->rwlock);
+ switch_mutex_unlock(node->update_mutex);
x++;
}
@@ -3710,9 +3727,9 @@ SWITCH_STANDARD_API(fifo_api_function)
}
} else if ((node = switch_core_hash_find(globals.fifo_hash, argv[1]))) {
len = node_caller_count(node);
- switch_thread_rwlock_wrlock(node->rwlock);
+ switch_mutex_lock(node->update_mutex);
stream->write_function(stream, "%s:%d:%d:%d\n", argv[1], node->consumer_count, node_caller_count(node), len);
- switch_thread_rwlock_unlock(node->rwlock);
+ switch_mutex_unlock(node->update_mutex);
} else {
stream->write_function(stream, "none\n");
}
@@ -3722,9 +3739,9 @@ SWITCH_STANDARD_API(fifo_api_function)
switch_hash_this(hi, &var, NULL, &val);
node = (fifo_node_t *) val;
len = node_caller_count(node);
- switch_thread_rwlock_wrlock(node->rwlock);
+ switch_mutex_lock(node->update_mutex);
stream->write_function(stream, "%s:%d\n", (char *) var, node->has_outbound);
- switch_thread_rwlock_unlock(node->rwlock);
+ switch_mutex_unlock(node->update_mutex);
x++;
}
@@ -3733,9 +3750,9 @@ SWITCH_STANDARD_API(fifo_api_function)
}
} else if ((node = switch_core_hash_find(globals.fifo_hash, argv[1]))) {
len = node_caller_count(node);
- switch_thread_rwlock_wrlock(node->rwlock);
+ switch_mutex_lock(node->update_mutex);
stream->write_function(stream, "%s:%d\n", argv[1], node->has_outbound);
- switch_thread_rwlock_unlock(node->rwlock);
+ switch_mutex_unlock(node->update_mutex);
} else {
stream->write_function(stream, "none\n");
}
@@ -4108,7 +4125,7 @@ static switch_status_t load_config(int reload, int del_all)
node->ready = FIFO_DELAY_DESTROY;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "%s removed.\n", node->name);
- switch_thread_rwlock_wrlock(node->rwlock);
+ switch_mutex_lock(node->update_mutex);
for (x = 0; x < MAX_PRI; x++) {
while (fifo_queue_pop(node->fifo_list[x], &pop, 2) == SWITCH_STATUS_SUCCESS) {
switch_event_destroy(&pop);
@@ -4117,7 +4134,7 @@ static switch_status_t load_config(int reload, int del_all)
switch_core_hash_delete(globals.fifo_hash, node->name);
switch_core_hash_destroy(&node->consumer_hash);
- switch_thread_rwlock_unlock(node->rwlock);
+ switch_mutex_unlock(node->update_mutex);
switch_core_destroy_memory_pool(&node->pool);
goto top;
}
@@ -4393,7 +4410,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown)
switch_hash_this(hi, NULL, NULL, &val);
node = (fifo_node_t *) val;
- switch_thread_rwlock_wrlock(node->rwlock);
+ switch_mutex_lock(node->update_mutex);
switch_mutex_lock(node->mutex);
for (x = 0; x < MAX_PRI; x++) {
while (fifo_queue_pop(node->fifo_list[x], &pop, 2) == SWITCH_STATUS_SUCCESS) {
@@ -4403,7 +4420,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown)
switch_mutex_unlock(node->mutex);
switch_core_hash_delete(globals.fifo_hash, node->name);
switch_core_hash_destroy(&node->consumer_hash);
- switch_thread_rwlock_unlock(node->rwlock);
+ switch_mutex_unlock(node->update_mutex);
switch_core_destroy_memory_pool(&node->pool);
}
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_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_spy/mod_spy.c b/src/mod/applications/mod_spy/mod_spy.c
index 5093ad8f22..cb8981d264 100644
--- a/src/mod/applications/mod_spy/mod_spy.c
+++ b/src/mod/applications/mod_spy/mod_spy.c
@@ -131,7 +131,6 @@ SWITCH_STANDARD_API(dump_hash)
static switch_status_t process_event(switch_event_t *event)
{
switch_core_session_t *session = NULL;
- switch_channel_t *channel;
char *username[3] = { 0 };
char *domain[3] = { 0 };
char key[512];
@@ -172,18 +171,19 @@ static switch_status_t process_event(switch_event_t *event)
return SWITCH_STATUS_FALSE;
}
- session = switch_core_session_locate(uuid);
- channel = switch_core_session_get_channel(session);
+ if ((session = switch_core_session_locate(uuid))) {
+ switch_channel_t *channel = switch_core_session_get_channel(session);
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "UserSpy retrieved uuid %s for key %s, activating eavesdrop \n", uuid, key);
- my_uuid = switch_event_get_header(event, "Unique-ID");
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "UserSpy retrieved uuid %s for key %s, activating eavesdrop \n", uuid, key);
+ my_uuid = switch_event_get_header(event, "Unique-ID");
- switch_channel_set_variable(channel, "spy_uuid", my_uuid);
+ switch_channel_set_variable(channel, "spy_uuid", my_uuid);
- switch_channel_set_state(channel, CS_EXCHANGE_MEDIA);
- switch_channel_set_flag(channel, CF_BREAK);
+ switch_channel_set_state(channel, CS_EXCHANGE_MEDIA);
+ switch_channel_set_flag(channel, CF_BREAK);
- switch_core_session_rwunlock(session);
+ switch_core_session_rwunlock(session);
+ }
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/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..13e433557d 100644
--- a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp
+++ b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp
@@ -1324,7 +1324,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
caller_profile = tech_pvt->caller_profile;
caller_profile->destination_number = rdest;
- switch_channel_set_flag(channel, CF_OUTBOUND);
switch_set_flag(tech_pvt, TFLAG_OUTBOUND);
switch_channel_set_state(channel, CS_INIT);
gsmopen_call(tech_pvt, rdest, 30);
@@ -1904,14 +1903,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..3d79917434 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){
}
@@ -725,7 +725,6 @@ FSH323Connection::FSH323Connection(FSH323EndPoint& endpoint, H323Transport* tran
name += outbound_profile->destination_number;
switch_channel_set_name(m_fsChannel, name);
- switch_channel_set_flag(m_fsChannel, CF_OUTBOUND);
switch_channel_set_state(m_fsChannel, CS_INIT);
}
@@ -742,6 +741,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 +1155,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)){
@@ -1500,7 +1507,7 @@ switch_status_t FSH323Connection::receive_message(switch_core_session_message_t
break;
}
case SWITCH_MESSAGE_INDICATE_ANSWER: {
- if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
return SWITCH_STATUS_FALSE;
}
AnsweringCall(H323Connection::AnswerCallNow);
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