Merge branch 'master' into smgmaster

This commit is contained in:
Moises Silva 2010-09-08 12:26:20 -04:00
commit 92e1a8186e
57 changed files with 2134 additions and 801 deletions

View File

@ -10,6 +10,8 @@
<param name="moh-sound" value="$${hold_music}"/> <param name="moh-sound" value="$${hold_music}"/>
<!--<param name="record-template" value="$${base_dir}/recordings/${strftime(%Y-%m-%d-%H-%M-%S)}.${destination_number}.${caller_id_number}.${uuid}.wav"/>--> <!--<param name="record-template" value="$${base_dir}/recordings/${strftime(%Y-%m-%d-%H-%M-%S)}.${destination_number}.${caller_id_number}.${uuid}.wav"/>-->
<param name="time-base-score" value="system"/> <param name="time-base-score" value="system"/>
<param name="max-wait-time" value="0"/>
<param name="max-wait-time-with-no-agent" value="0"/>
<param name="tier-rules-apply" value="false"/> <param name="tier-rules-apply" value="false"/>
<param name="tier-rule-wait-second" value="300"/> <param name="tier-rule-wait-second" value="300"/>
<param name="tier-rule-wait-multiply-level" value="true"/> <param name="tier-rule-wait-multiply-level" value="true"/>

View File

@ -715,15 +715,6 @@
--> -->
<X-PRE-PROCESS cmd="include" data="default/*.xml"/> <X-PRE-PROCESS cmd="include" data="default/*.xml"/>
<!--
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
Anything you put below this line will usually get ignored due to the file in
default/99999_enum.xml as it will transfer the call to the enum dialplan.
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
-->
<!-- <!--
<extension name="refer"> <extension name="refer">
<condition field="${sip_refer_to}"> <condition field="${sip_refer_to}">
@ -758,7 +749,12 @@
</extension> </extension>
--> -->
<!-- SEE WARNING ABOVE IF YOU ARE TRYING TO ADD EXTENSIONS HERE! --> <extension name="enum">
<condition field="${module_exists(mod_enum)}" expression="true"/>
<condition field="destination_number" expression="^(.*)$">
<action application="transfer" data="$1 enum"/>
</condition>
</extension>
</context> </context>
</include> </include>

View File

@ -1,8 +0,0 @@
<include>
<extension name="enum">
<condition field="${module_exists(mod_enum)}" expression="true"/>
<condition field="destination_number" expression="^(.*)$">
<action application="transfer" data="$1 enum"/>
</condition>
</extension>
</include>

View File

@ -3,6 +3,7 @@
<params> <params>
<!-- for devices requesting firmware via SCCP, like ATA186 <!-- for devices requesting firmware via SCCP, like ATA186
<param name="skinny-firmware-version" value="ATA030101SCCP04" <param name="skinny-firmware-version" value="ATA030101SCCP04"
<param name="skinny-soft-key-set-set" value="default"
--> -->
<param name="foo" value="bar"/> <param name="foo" value="bar"/>
</params> </params>

View File

@ -13,6 +13,17 @@
<param name="debug" value="4"/> <param name="debug" value="4"/>
<param name="auto-restart" value="true"/> <param name="auto-restart" value="true"/>
</settings> </settings>
<soft-key-set-sets>
<soft-key-set-set name="default">
<soft-key-set name="KeySetOnHook" value="SoftkeyNewcall,SoftkeyRedial"/>
<soft-key-set name="KeySetOffHook" value=",SoftkeyNewcall,SoftkeyEndcall"/>
<soft-key-set name="KeySetDigitsAfterDialingFirstDigit" value="SoftkeyBackspace,,SoftkeyEndcall"/>
<soft-key-set name="KeySetConnected" value="SoftkeyEndcall,SoftkeyHold,SoftkeyNewcall,SoftkeyTransfer"/>
<soft-key-set name="KeySetRingIn" value="SoftkeyAnswer,SoftkeyEndcall,SoftkeyNewcall"/>
<soft-key-set name="KeySetOnHold" value="SoftkeyNewcall,SoftkeyResume,SoftkeyEndcall"/>
<soft-key-set name="KeySetOffHookWithFeatures" value=",SoftkeyRedial,SoftkeyEndcall"/>
</soft-key-set-set>
</soft-key-set-sets>
<device-types> <device-types>
<device-type id="Cisco ATA 186"> <device-type id="Cisco ATA 186">
<param name="firmware-version" value="ATA030101SCCP04"/> <param name="firmware-version" value="ATA030101SCCP04"/>

View File

@ -15,6 +15,7 @@ freeswitch (1.0.7)
build: Fix build with --with-curl (r:e704f021/FSBUILD-285) build: Fix build with --with-curl (r:e704f021/FSBUILD-285)
build: VS 2010 - Change to V4 framework, add SWIG v2.0 files to fix release build exceptions(temp fix till we upgrade all SWIG files) (r:812f4309) build: VS 2010 - Change to V4 framework, add SWIG v2.0 files to fix release build exceptions(temp fix till we upgrade all SWIG files) (r:812f4309)
build: Windows VS2010 build - remove strange characters (r:ba1546e0/FSBUILD-297) build: Windows VS2010 build - remove strange characters (r:ba1546e0/FSBUILD-297)
build: Make bootstrap.sh Bourne shell compatible (r:8dbd62ff/FSBUILD-301)
config: move limit.conf to db.conf config: move limit.conf to db.conf
config: Update VM phrase macros to voice option then action on main, config menus config: Update VM phrase macros to voice option then action on main, config menus
config: Remove 99xx extension numbers to avoid dp conflicts (r:0c9bb174/DP-17) config: Remove 99xx extension numbers to avoid dp conflicts (r:0c9bb174/DP-17)
@ -30,7 +31,7 @@ freeswitch (1.0.7)
core: always export 'export_vars' core: always export 'export_vars'
core: add sanity check to launch threads that catch hangup and are not in a thread to make sure they clean up core: add sanity check to launch threads that catch hangup and are not in a thread to make sure they clean up
core: Tweak bridge_early_media to support passthrough codecs core: Tweak bridge_early_media to support passthrough codecs
core: cleanup C reserved identifer violation (JANITOR-3) core: cleanup C reserved identifier violation (JANITOR-3)
core: add sound_prefix support in uuid_displace (FSCORE-550) core: add sound_prefix support in uuid_displace (FSCORE-550)
core: add 'critical' param on modules.conf to abort on mod load failure from Moc core: add 'critical' param on modules.conf to abort on mod load failure from Moc
core: add 'direction' chan var core: add 'direction' chan var
@ -71,6 +72,12 @@ freeswitch (1.0.7)
core: Improve RTP timing on playback of files (r:d6d7773c/FSCORE-639) core: Improve RTP timing on playback of files (r:d6d7773c/FSCORE-639)
core: Allows bind_meta_app to use chars other than * (r:fd254766/FSCORE-630) core: Allows bind_meta_app to use chars other than * (r:fd254766/FSCORE-630)
core: Fixed core lib won't build for win32 (r:9327c994/FSCORE-646) core: Fixed core lib won't build for win32 (r:9327c994/FSCORE-646)
core: add last_bridge_to var to keep uuid of last bridged channel and fix race in show calls on hangup of bypass_media channels (r:77e2dccf)
core: Phrase "speak-text" application returns on first key press in phrase file on Windows (r:6d74d7ab/MODAPP-448)
core: pass originate flags into session_request so we can selectivly skip throttling (r:46c6650a)
core: Implemented 'Block Fork' and removed possibility for "-nc -nf" potential issue. (r:f26a6972/FSCORE-652)
core: Add console callback for listing loaded/available modules for load/unload/reload commands (r:d68a1218/FSCORE-662)
core: strip trailing and leading whitespace in api execute args and commands (r:ca481842)
lang: Improve French phrase files (FSCONFIG-23) lang: Improve French phrase files (FSCONFIG-23)
libdingaling: fix race on shutdown causing crash (FSMOD-47) libdingaling: fix race on shutdown causing crash (FSMOD-47)
libesl: Fix potential race condition (ESL-36) libesl: Fix potential race condition (ESL-36)
@ -88,8 +95,10 @@ freeswitch (1.0.7)
libfreetdm: implemented freetdm config nodes and ss7 initial configuration libfreetdm: implemented freetdm config nodes and ss7 initial configuration
libopenzap: Add CLI tracing libopenzap: Add CLI tracing
libs: Merged OpenZAP and FreeTDM into the FreeSWITCH tree. libs: Merged OpenZAP and FreeTDM into the FreeSWITCH tree.
libs: Add support for TLS on Windows using openssl (r:1abe3b93/MODSOFIA-92)
libsofiasip: Fix random crashes (r:c15ee980/SFSIP-219) libsofiasip: Fix random crashes (r:c15ee980/SFSIP-219)
libsofiasip: Fix T.38 bug in sofia_glue (r:2843f1ad/MODSOFIA-94) libsofiasip: Fix T.38 bug in sofia_glue (r:2843f1ad/MODSOFIA-94)
libsofiasip: VS2010 sofia posix problem (r:46dd24c2/SFSIP-220)
libspandsp: Fixed a typo in spandsp's msvc/inttypes.h Updated sig_tone processing in spandsp to the latest, to allow moy to proceed with his signaling work. libspandsp: Fixed a typo in spandsp's msvc/inttypes.h Updated sig_tone processing in spandsp to the latest, to allow moy to proceed with his signaling work.
libspandsp: removed a saturate16 from spandsp that was causing problems fixed a typo in the MSVC inttypes.h file for spandsp libspandsp: removed a saturate16 from spandsp that was causing problems fixed a typo in the MSVC inttypes.h file for spandsp
libspandsp: Changes to the signaling tone detector to detect concurrent 2400Hz + 2600Hz tones. This passes voice immunity and other key tests, but it bounces a bit when transitions like 2400 -> 2400+2600 -> 2600 occur. Transitions between tone off and tone on are clean. (r:bc13e944) libspandsp: Changes to the signaling tone detector to detect concurrent 2400Hz + 2600Hz tones. This passes voice immunity and other key tests, but it bounces a bit when transitions like 2400 -> 2400+2600 -> 2600 occur. Transitions between tone off and tone on are clean. (r:bc13e944)
@ -101,6 +110,13 @@ freeswitch (1.0.7)
mod_callcenter: Try to fix the ring-all, also add cli auto complete done in previous commit (r:1666783c) mod_callcenter: Try to fix the ring-all, also add cli auto complete done in previous commit (r:1666783c)
mod_callcenter: Add missing odbc db support (Not tested, please someone test this) (r:42436e27) mod_callcenter: Add missing odbc db support (Not tested, please someone test this) (r:42436e27)
mod_callcenter: More ODBC changes. It is not a global settings value. Cannot be changed in runtime. (r:6980305f) mod_callcenter: More ODBC changes. It is not a global settings value. Cannot be changed in runtime. (r:6980305f)
mod_callcenter: Added value busy_delay_time and reject_delay_time so we can wait if those 2 occur (Un registred phone are considered as busy). Add a ready_time epoch time when we can contact an again again, fix ring-all (good this time I hope). (r:8082aa98)
mod_callcenter: Add tiers rules before jumping to a different level. Also added support for dial-in agent. (r:86c9bed7)
mod_callcenter: Default the level to 0 since the new tier system will wait x second at level 1... just level 0 that will ring agent right away (if set to do so) (r:6558276a)
mod_callcenter: You can now allow caller that have hangup before agent answer to call back and resume their previous position. (r:ab2529d4)
mod_callcenter: correct multiple little things following the recent tiers and join back features (r:9b33bd1c)
mod_callcenter: Add more channel variable and event and fix a mem leak (r:2d3d8c8d)
od_callcenter: Make more sence to bridge the caller to the agent. Before, in the xml_cdr you saw it it like the agent initiated the call to the member (r:0be95658)
mod_cidlookup: null xml is bad (r:095815f8) mod_cidlookup: null xml is bad (r:095815f8)
mod_cid_lookup: honor skipcitystate when using whitepages (r:a66654de/FSMOD-53) mod_cid_lookup: honor skipcitystate when using whitepages (r:a66654de/FSMOD-53)
mod_commands: make break uuid_break and add cascade flag mod_commands: make break uuid_break and add cascade flag
@ -118,7 +134,11 @@ freeswitch (1.0.7)
mod_conference: add conference_member_id variable to all sessions with the member id used by their conference participation (For drk__) (r:49c9bfdb) mod_conference: add conference_member_id variable to all sessions with the member id used by their conference participation (For drk__) (r:49c9bfdb)
mod_conference: fix relate nohear (r:f029ce07/MODAPP-428) mod_conference: fix relate nohear (r:f029ce07/MODAPP-428)
mod_conference: Fix floor change events not always firing (r:8f1767d3/MODAPP-424) mod_conference: Fix floor change events not always firing (r:8f1767d3/MODAPP-424)
mod_curl: use method=post when post requested (r:c6a4ddd0/FSMOD-69)
mod_dialplan_xml: Add in the INFO log the caller id number when processing a request (Currenly only show the caller name) (r:e1df5e13) mod_dialplan_xml: Add in the INFO log the caller id number when processing a request (Currenly only show the caller name) (r:e1df5e13)
mod_dingaling: make mod_dingaling compat with google's new free phonecalls thing (r:ba0a2a32)
mod_dingaling: make dingaling work with google voice inbound too (r:4ee68141)
mod_dingaling: Fix crash when testing the new gv-dingaling with around 24 concurrent calls (r:73e1ec5e/FSCORE-667)
mod_db: fix stack corruption (MODAPP-407) mod_db: fix stack corruption (MODAPP-407)
mod_dptools: add eavesdrop_enable_dtmf chan var (r:596c0012) mod_dptools: add eavesdrop_enable_dtmf chan var (r:596c0012)
mod_dptools: Make park app not send 183 session progress (r:76932995/FSCORE-567) mod_dptools: Make park app not send 183 session progress (r:76932995/FSCORE-567)
@ -126,7 +146,9 @@ freeswitch (1.0.7)
mod_erlang_event: Make XML fetch reply ACKs distinguishable, update freeswitch.erl (r:9d44ed04) mod_erlang_event: Make XML fetch reply ACKs distinguishable, update freeswitch.erl (r:9d44ed04)
mod_erlang_event: Add 3 new commands; session_event, session_noevents, session_nixevent (r:698fa045) mod_erlang_event: Add 3 new commands; session_event, session_noevents, session_nixevent (r:698fa045)
mod_erlang_event: generate long node names the same as erlang does (r:9ad509c2) mod_erlang_event: generate long node names the same as erlang does (r:9ad509c2)
mod_erlang_event: Improve some logging to include UUIDs (r:c0d51b83)
mod_event_socket: fix up other users of switch_event_xmlize() to use SWITCH_EVENT_NONE (r:d6eb7562) mod_event_socket: fix up other users of switch_event_xmlize() to use SWITCH_EVENT_NONE (r:d6eb7562)
mod_event_socket: Fix small mem leaks (r:e4f90584/MODEVENT-68)
mod_fifo: allow multiple dtmf to exit fifo, set fifo_caller_exit_key to specify which (MODAPP-420) mod_fifo: allow multiple dtmf to exit fifo, set fifo_caller_exit_key to specify which (MODAPP-420)
mod_fifo: cancel outbound call if customer hangs up (r:cadb4d94) mod_fifo: cancel outbound call if customer hangs up (r:cadb4d94)
mod_fifo: add taking_calls param to fifo member add and config file (r:821488bf) mod_fifo: add taking_calls param to fifo member add and config file (r:821488bf)
@ -159,6 +181,8 @@ freeswitch (1.0.7)
mod_freetdm: fix fxs dialtone - should be stopped on first digit (r:f822180f) mod_freetdm: fix fxs dialtone - should be stopped on first digit (r:f822180f)
mod_freetdm: add bearer capability and layer1 pass-thru for boost (r:07b81760) mod_freetdm: add bearer capability and layer1 pass-thru for boost (r:07b81760)
mod_freetdm: OPENZAP-107 - Patched by Jeff Lenk (r:aa075136/OPENZAP-107) mod_freetdm: OPENZAP-107 - Patched by Jeff Lenk (r:aa075136/OPENZAP-107)
mod_freetdm: allocate channels in their own memory page when debugging (r:fcd8df0a)
mod_freetdm: lock the channel when placing call (r:705dd237)
mod_gsmopen: copy from branch mod_gsmopen: copy from branch
mod_hash: free all hashtables on shutdown (r:e76d7d92) mod_hash: free all hashtables on shutdown (r:e76d7d92)
mod_hash: remove unneeded initializer (r:10d468a6) mod_hash: remove unneeded initializer (r:10d468a6)
@ -179,6 +203,7 @@ freeswitch (1.0.7)
mod_h323: add missing conf prameter (r:0b353d7a) mod_h323: add missing conf prameter (r:0b353d7a)
mod_h323: Add mod_h323 to windows (r:015bcaf6/MODENDP-301) mod_h323: Add mod_h323 to windows (r:015bcaf6/MODENDP-301)
mod_h323: move PTrace level set to FSH323EndPoint::Initialise. partially apply patch from from Peter Olsson, Remove UnLock() when TryLock() failed and DEBUG_RTP_PACKETS directiv e. (r:7b5803f7) mod_h323: move PTrace level set to FSH323EndPoint::Initialise. partially apply patch from from Peter Olsson, Remove UnLock() when TryLock() failed and DEBUG_RTP_PACKETS directiv e. (r:7b5803f7)
mod_h323: set network_addr of caller profile to signaling ip address. (requested by Steven Ayre) (r:072bf5ad)
mod_java: fix eventConsumer issue and add flush() method (r:7fd3aff6) mod_java: fix eventConsumer issue and add flush() method (r:7fd3aff6)
mod_java: Allow user defined java methods to be called at startup and shutdown of JVM (r:1339e218/MODLANG-117) mod_java: Allow user defined java methods to be called at startup and shutdown of JVM (r:1339e218/MODLANG-117)
mod_json_cdr: Fix segfault in mod_json_cdr.c (r:f347698a/MODEVENT-66) mod_json_cdr: Fix segfault in mod_json_cdr.c (r:f347698a/MODEVENT-66)
@ -210,7 +235,9 @@ freeswitch (1.0.7)
mod_sangoma_codec: rename load/noload to register/noregister mod_sangoma_codec: rename load/noload to register/noregister
mod_sangoma_codec: silence suppression (r:73d9d56f) mod_sangoma_codec: silence suppression (r:73d9d56f)
mod_say_es: fix grammar when saying dates and time (r:6bed19b2/MODAPP-429) mod_say_es: fix grammar when saying dates and time (r:6bed19b2/MODAPP-429)
mod_say_ru: Fix saying time with +1 hour of current time (r:68d74c31/MODAPP-444)
mod_say_zh: Number reading should now be OK for the whole range of integers for Cantonese and Mandarin mod_say_zh: Number reading should now be OK for the whole range of integers for Cantonese and Mandarin
mod_silk: Fix mod_silk compliance and performance issues (r:2ddbc457/MODCODEC-20)
mod_skinny: Add the missing api files mod_skinny: Add the missing api files
mod_skinny: add example dialplan and directory config (r:1bfcc17e) mod_skinny: add example dialplan and directory config (r:1bfcc17e)
mod_skinny: rewrite of the skinny state machine (r:8cc89ab0) mod_skinny: rewrite of the skinny state machine (r:8cc89ab0)
@ -225,8 +252,16 @@ freeswitch (1.0.7)
mod_skinny: ib_calls stats (r:165140e0) mod_skinny: ib_calls stats (r:165140e0)
mod_skinny: blind transfer MODSKINNY-10 (r:53f75e9c/MODSKINNY-10) mod_skinny: blind transfer MODSKINNY-10 (r:53f75e9c/MODSKINNY-10)
mod_skinny: ring tone on dialing side (r:0a04ecb8) mod_skinny: ring tone on dialing side (r:0a04ecb8)
mod_skinny: stop media on early media hangup (ring-out) (r:ce352bcc)
mod_skinny: add windows x64 build support for mod_skinny (r:3e205683)
mod_skinny: avoid "-ERR no reply" when using API commands from CLI (r:690ae1b3)
mod_skinny: allow configuration of softkeys via xml (r:f5a6831f)
mod_skinny: allow skinny-default-soft-key-set-set per device (r:07c3c94d)
mod_skinny: Rename skinny-default-soft-key-set-set to skinny-soft-key-set-set (r:ba3a6ad6)
mod_skypopen: making XEvents to works when EARLYMEDIA, and correctly manage threads death mod_skypopen: making XEvents to works when EARLYMEDIA, and correctly manage threads death
mod_skypopen: now answer a call only when directed to do it (before was trying to answer any incoming call). Lot of changes to a messy part, so maybe some problem will come out... (r:45c6c4d3) mod_skypopen: now answer a call only when directed to do it (before was trying to answer any incoming call). Lot of changes to a messy part, so maybe some problem will come out... (r:45c6c4d3)
mod_skypopen: ignore early media sent by channels to be bridged before our channel is answered (r:ef14b78a)
mod_sndfile: Add support for .alaw and .ulaw to mod_sndfile (r:facf09b8/MODFORM-41)
mod_sofia: Send SIP MESSAGE to unregistered users by prefixing sip: to user@domain mod_sofia: Send SIP MESSAGE to unregistered users by prefixing sip: to user@domain
mod_sofia: fix callee being updated with callee information mod_sofia: fix callee being updated with callee information
mod_sofia: set appearance-index in update statement for SLA mod_sofia: set appearance-index in update statement for SLA
@ -258,6 +293,16 @@ freeswitch (1.0.7)
mod_sofia: Fix segfault (r:72be253d/MODSOFIA-83) mod_sofia: Fix segfault (r:72be253d/MODSOFIA-83)
mod_sofia: Add openssl build support to windows - no external build support needed (step 1 - not hooked up yet) vs2008 pro+ only (r:b0de3585/MODSOFIA-92) mod_sofia: Add openssl build support to windows - no external build support needed (step 1 - not hooked up yet) vs2008 pro+ only (r:b0de3585/MODSOFIA-92)
mod_sofia: REFER: to-tag and from-tag should be set other way around when other (bridged) channel is incoming. (r:92d324d3/MODSOFIA-91) mod_sofia: REFER: to-tag and from-tag should be set other way around when other (bridged) channel is incoming. (r:92d324d3/MODSOFIA-91)
mod_sofia: fix 302 to hangup in the two cases where switch_ivr_transfer is used and not in the case when it should carry on and follow the redirect (r:00b51403)
mod_sofia: Remove OPENSSL_USE_APPLINK - not needed (r:437c7805/MODSOFIA-92)
mod_sofia: Send Instant Messages To All Endpoints Registered to Targeted Extension (r:96b790fa/BOUNTY-20)
mod_sofia: increase sps during recovery (r:f1aead31)
mod_sofia: Forward unsolicited MWI nofity (r:5481d9a9/MODSOFIA-86)
mod_sofia: Add a quick fix for basic Polycom presence support. A more sane solution need to be implemented (r:a55b9d07)
mod_sofia: Unify gateway printing between 'sofia xmlstatus gateway' and 'sofia xmlstatus gateway <gatewayname>' (r:37c22467)
mod_sofia: Fix memleak and mwi event not generated on first register (r:04b9b3e2)
mod_sofia: when getting presence with no payload consider it an extension to the expires time in the dialog (r:70331e88)
mod_sofia: don't put blank 'version' attr in dialog-info packets (r:749dc864)
mod_spandsp: initial checkin of mod_fax/mod_voipcodecs merge into mod_spandsp (r:fa9a59a8) 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: 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) 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)
@ -276,6 +321,7 @@ freeswitch (1.0.7)
mod_voicemail: add 'vm-enabled' param (default true) mod_voicemail: add 'vm-enabled' param (default true)
mod_voicemail: fix vm msg being deleted when pressing key to forward to email (MODAPP-403) mod_voicemail: fix vm msg being deleted when pressing key to forward to email (MODAPP-403)
mod_voicemail: make voicemails use the uuid of the channel who recorded it when applicable (r:98a5a30a) mod_voicemail: make voicemails use the uuid of the channel who recorded it when applicable (r:98a5a30a)
mod_voicemail: user unable to play or delete voicemail via web API (r:b5205c0b/MODAPP-447)
mod_xml_cdr: add force_process_cdr var to process b leg cdr on a case by case basis when b leg cdr is disabled (XML-17) mod_xml_cdr: add force_process_cdr var to process b leg cdr on a case by case basis when b leg cdr is disabled (XML-17)
mod_xml_cdr: add leg param to query string (XML-24) mod_xml_cdr: add leg param to query string (XML-24)
mod_xml_cdr: fix locked sessions (XML-26) mod_xml_cdr: fix locked sessions (XML-26)

View File

@ -3896,7 +3896,7 @@ SWITCH_STANDARD_API(ft_function)
ftdm_channel_t *fchan = NULL; ftdm_channel_t *fchan = NULL;
ftdm_span_t *span = NULL; ftdm_span_t *span = NULL;
if (argc < 2) { if (argc < 2) {
stream->write_function(stream, "-ERR Usage: oz notrace <span_id> [<chan_id>]\n"); stream->write_function(stream, "-ERR Usage: ftdm notrace <span_id> [<chan_id>]\n");
goto end; goto end;
} }
ftdm_span_find_by_name(argv[1], &span); ftdm_span_find_by_name(argv[1], &span);

View File

@ -338,6 +338,10 @@
RelativePath="..\src\include\private\ftdm_buffer.h" RelativePath="..\src\include\private\ftdm_buffer.h"
> >
</File> </File>
<File
RelativePath="..\src\include\private\ftdm_call_utils.h"
>
</File>
<File <File
RelativePath="..\src\include\private\ftdm_config.h" RelativePath="..\src\include\private\ftdm_config.h"
> >
@ -416,6 +420,10 @@
RelativePath="..\src\ftdm_buffer.c" RelativePath="..\src\ftdm_buffer.c"
> >
</File> </File>
<File
RelativePath="..\src\ftdm_call_utils.c"
>
</File>
<File <File
RelativePath="..\src\ftdm_callerid.c" RelativePath="..\src\ftdm_callerid.c"
> >

View File

@ -1805,6 +1805,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open(uint32_t span_id, uint32_t chan_id,
status = FTDM_SUCCESS; status = FTDM_SUCCESS;
} }
ftdm_set_flag(check, FTDM_CHANNEL_INUSE); ftdm_set_flag(check, FTDM_CHANNEL_INUSE);
ftdm_set_flag(check, FTDM_CHANNEL_OUTBOUND);
*ftdmchan = check; *ftdmchan = check;
} }

View File

@ -189,7 +189,8 @@ ftdm_state_map_t sangoma_isdn_state_map = {
ZSD_OUTBOUND, ZSD_OUTBOUND,
ZSM_UNACCEPTABLE, ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_DIALING, FTDM_END}, {FTDM_CHANNEL_STATE_DIALING, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_DOWN, 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}
}, },
{ {
ZSD_OUTBOUND, ZSD_OUTBOUND,
@ -558,6 +559,9 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
/* We are hangup local call because there was a glare, we are waiting for a /* We are hangup local call because there was a glare, we are waiting for a
RELEASE on this call, before we can process the saved call */ RELEASE on this call, before we can process the saved call */
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Waiting for RELEASE on hungup glared call\n"); ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Waiting for RELEASE on hungup glared call\n");
} else if (sngisdn_test_flag(sngisdn_info, FLAG_SEND_DISC)) {
/* Remote side sent a PROGRESS message, but cause indicates disconnect or T310 expired*/
sngisdn_snd_disconnect(ftdmchan);
} else { } else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Hanging up call upon local request!\n"); ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Hanging up call upon local request!\n");
@ -568,16 +572,15 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
if (ftdmchan->last_state == FTDM_CHANNEL_STATE_RING || if (ftdmchan->last_state == FTDM_CHANNEL_STATE_RING ||
ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALING) { ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALING) {
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
sngisdn_snd_release(ftdmchan, 0);
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) { if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
sng_isdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN); sng_isdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
} }
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
sngisdn_snd_release(ftdmchan, 0);
} else { } else {
sngisdn_snd_disconnect(ftdmchan); sngisdn_snd_disconnect(ftdmchan);
} }
} }
/* now go to the HANGUP complete state */ /* now go to the HANGUP complete state */

View File

@ -68,6 +68,7 @@ typedef enum {
FLAG_GLARE = (1 << 6), FLAG_GLARE = (1 << 6),
FLAG_DELAYED_REL = (1 << 7), FLAG_DELAYED_REL = (1 << 7),
FLAG_SENT_PROCEED = (1 << 8), FLAG_SENT_PROCEED = (1 << 8),
FLAG_SEND_DISC = (1 << 9),
} sngisdn_flag_t; } sngisdn_flag_t;
@ -127,6 +128,13 @@ typedef enum {
SNGISDN_EVENT_RST_IND, SNGISDN_EVENT_RST_IND,
} ftdm_sngisdn_event_id_t; } ftdm_sngisdn_event_id_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 */
typedef enum {
SNGISDN_TIMER_FACILITY = 0,
} ftdm_sngisdn_timer_t;
typedef struct sngisdn_glare_data { typedef struct sngisdn_glare_data {
int16_t suId; int16_t suId;
uint32_t suInstId; uint32_t suInstId;
@ -148,6 +156,7 @@ typedef struct sngisdn_chan_data {
uint8_t globalFlg; uint8_t globalFlg;
sngisdn_glare_data_t glare; sngisdn_glare_data_t glare;
ftdm_timer_t *timers[SNGISDN_NUM_TIMERS];
} sngisdn_chan_data_t; } sngisdn_chan_data_t;
/* Span specific data */ /* Span specific data */
@ -165,6 +174,7 @@ typedef struct sngisdn_span_data {
uint8_t overlap_dial; uint8_t overlap_dial;
uint8_t setup_arb; uint8_t setup_arb;
uint8_t facility; uint8_t facility;
int8_t facility_timeout;
ftdm_sched_t *sched; ftdm_sched_t *sched;
ftdm_queue_t *event_queue; ftdm_queue_t *event_queue;
} sngisdn_span_data_t; } sngisdn_span_data_t;
@ -223,8 +233,8 @@ typedef struct sngisdn_cc {
ftdm_trunk_type_t trunktype; ftdm_trunk_type_t trunktype;
uint32_t last_suInstId; uint32_t last_suInstId;
ftdm_mutex_t *mutex; ftdm_mutex_t *mutex;
sngisdn_chan_data_t *active_spInstIds[MAX_INSTID]; sngisdn_chan_data_t *active_spInstIds[MAX_INSTID+1];
sngisdn_chan_data_t *active_suInstIds[MAX_INSTID]; sngisdn_chan_data_t *active_suInstIds[MAX_INSTID+1];
}sngisdn_cc_t; }sngisdn_cc_t;
/* Global sngisdn data */ /* Global sngisdn data */
@ -349,6 +359,7 @@ void sngisdn_set_span_sig_status(ftdm_span_t *ftdmspan, ftdm_signaling_status_t
void sngisdn_delayed_release(void* p_sngisdn_info); void sngisdn_delayed_release(void* p_sngisdn_info);
void sngisdn_delayed_connect(void* p_sngisdn_info); void sngisdn_delayed_connect(void* p_sngisdn_info);
void sngisdn_delayed_disconnect(void* p_sngisdn_info); void sngisdn_delayed_disconnect(void* p_sngisdn_info);
void sngisdn_facility_timeout(void* p_sngisdn_info);
/* Stack management functions */ /* Stack management functions */
ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span); ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span);

View File

@ -249,6 +249,11 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
ftdm_span_set_bearer_capability(val, &span->default_caller_data.bearer_capability); ftdm_span_set_bearer_capability(val, &span->default_caller_data.bearer_capability);
} else if (!strcasecmp(var, "outbound-bearer_layer1")) { } else if (!strcasecmp(var, "outbound-bearer_layer1")) {
ftdm_span_set_bearer_layer1(val, &span->default_caller_data.bearer_layer1); ftdm_span_set_bearer_layer1(val, &span->default_caller_data.bearer_layer1);
} else if (!strcasecmp(var, "facility-timeout")) {
signal_data->facility_timeout = atoi(val);
if (signal_data->facility_timeout < 0) {
signal_data->facility_timeout = 0;
}
} else { } else {
ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var); ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var);
} }

View File

@ -82,7 +82,6 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
/* If this is a glared call that was previously saved, we moved /* If this is a glared call that was previously saved, we moved
all the info to the current call, so clear the glared saved data */ all the info to the current call, so clear the glared saved data */
if (sngisdn_info->glare.spInstId == spInstId) { if (sngisdn_info->glare.spInstId == spInstId) {
clear_call_glare_data(sngisdn_info); clear_call_glare_data(sngisdn_info);
} }
@ -106,6 +105,7 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
break; break;
} }
/* Fill in call information */ /* Fill in call information */
cpy_calling_num_from_stack(&ftdmchan->caller_data, &conEvnt->cgPtyNmb); cpy_calling_num_from_stack(&ftdmchan->caller_data, &conEvnt->cgPtyNmb);
cpy_called_num_from_stack(&ftdmchan->caller_data, &conEvnt->cdPtyNmb); cpy_called_num_from_stack(&ftdmchan->caller_data, &conEvnt->cdPtyNmb);
@ -142,6 +142,10 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
if (ret_val == 1) { if (ret_val == 1) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n"); ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n");
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID); 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; break;
} else if (ret_val == 0) { } else if (ret_val == 0) {
strcpy(ftdmchan->caller_data.cid_name, retrieved_str); strcpy(ftdmchan->caller_data.cid_name, retrieved_str);
@ -289,6 +293,8 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; 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; CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt;
ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n"); ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
@ -302,19 +308,49 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
suId, suInstId, spInstId, ces); suId, suInstId, spInstId, ces);
switch(evntType) { switch(evntType) {
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_ALERTING:
case MI_CALLPROC: case MI_CALLPROC:
case MI_PROGRESS:
switch(ftdmchan->state) { switch(ftdmchan->state) {
case FTDM_CHANNEL_STATE_DIALING: case FTDM_CHANNEL_STATE_DIALING:
if (evntType == MI_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); ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
} else { } else {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
} }
break; break;
case FTDM_CHANNEL_STATE_PROGRESS: case FTDM_CHANNEL_STATE_PROGRESS:
if (evntType == MI_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); ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
} }
break; break;
@ -371,6 +407,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
break; break;
} }
sngisdn_process_cnst_ind_end:
ISDN_FUNC_TRACE_EXIT(__FUNCTION__); ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return; return;
} }
@ -638,12 +675,14 @@ void sngisdn_process_flc_ind (sngisdn_event_data_t *sngisdn_event)
void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event) void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event)
{ {
ISDN_FUNC_TRACE_ENTER(__FUNCTION__); ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
int16_t suId = sngisdn_event->suId; int16_t suId = sngisdn_event->suId;
uint32_t suInstId = sngisdn_event->suInstId; uint32_t suInstId = sngisdn_event->suInstId;
uint32_t spInstId = sngisdn_event->spInstId; uint32_t spInstId = sngisdn_event->spInstId;
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
FacEvnt *facEvnt = &sngisdn_event->event.facEvnt; FacEvnt *facEvnt = &sngisdn_event->event.facEvnt;
@ -659,10 +698,16 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event)
if (sng_isdn_retrieve_facility_caller_name(facility_str, facEvnt->facElmt.facStr.len, retrieved_str) != FTDM_SUCCESS) { if (sng_isdn_retrieve_facility_caller_name(facility_str, facEvnt->facElmt.facStr.len, retrieved_str) != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to retrieve Caller Name from Facility IE\n"); ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to retrieve Caller Name from Facility IE\n");
} }
/* Cancel facility timeout */
ftdm_sched_cancel_timer(signal_data->sched, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]);
} }
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
break; break;
case FTDM_CHANNEL_STATE_RING:
/* 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;
default: default:
/* We do not support other FACILITY types for now, so do nothing */ /* We do not support other FACILITY types for now, so do nothing */
break; break;
@ -794,6 +839,14 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
break; break;
case 3: case 3:
switch (ftdmchan->state) { switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_PROGRESS:
/* 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");
sngisdn_set_flag(sngisdn_info, FLAG_SEND_DISC);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
case FTDM_CHANNEL_STATE_UP: case FTDM_CHANNEL_STATE_UP:
/* Remote side is still waiting for our CONNECT message */ /* Remote side is still waiting for our CONNECT message */
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {

View File

@ -45,8 +45,8 @@ void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, Co
{ {
ISDN_FUNC_TRACE_ENTER(__FUNCTION__); ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
uint8_t bchan_no = 0; uint8_t bchan_no = 0;
sngisdn_chan_data_t *sngisdn_info; sngisdn_chan_data_t *sngisdn_info = NULL;
sngisdn_event_data_t *sngisdn_event; sngisdn_event_data_t *sngisdn_event = NULL;
ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Ind on unconfigured cc\n"); ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Ind on unconfigured cc\n");
ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Ind on unconfigured dchan\n"); ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Ind on unconfigured dchan\n");
@ -104,8 +104,8 @@ void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, Co
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_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, int16_t dChan, uint8_t ces)
{ {
ISDN_FUNC_TRACE_ENTER(__FUNCTION__); ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info; sngisdn_chan_data_t *sngisdn_info = NULL;
sngisdn_event_data_t *sngisdn_event; sngisdn_event_data_t *sngisdn_event = NULL;
ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Cfm on unconfigured cc\n"); ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Cfm on unconfigured cc\n");
ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Cfm on unconfigured dchan\n"); ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Cfm on unconfigured dchan\n");
@ -118,6 +118,7 @@ void sngisdn_rcv_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, Cn
if (!sngisdn_info->spInstId) { if (!sngisdn_info->spInstId) {
ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
sngisdn_info->spInstId = spInstId; sngisdn_info->spInstId = spInstId;
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info; g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);
@ -146,8 +147,8 @@ void sngisdn_rcv_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, Cn
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_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, int16_t dChan, uint8_t ces)
{ {
ISDN_FUNC_TRACE_ENTER(__FUNCTION__); ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info; sngisdn_chan_data_t *sngisdn_info = NULL;
sngisdn_event_data_t *sngisdn_event; sngisdn_event_data_t *sngisdn_event = NULL;
ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Cnst Ind on unconfigured cc\n"); ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Cnst Ind on unconfigured cc\n");
ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Cnst Ind on unconfigured dchan\n"); ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Cnst Ind on unconfigured dchan\n");
@ -160,6 +161,7 @@ void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, C
if (!sngisdn_info->spInstId) { if (!sngisdn_info->spInstId) {
ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
sngisdn_info->spInstId = spInstId; sngisdn_info->spInstId = spInstId;
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info; g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);
@ -195,8 +197,8 @@ void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, C
void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt) void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt)
{ {
ISDN_FUNC_TRACE_ENTER(__FUNCTION__); ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info; sngisdn_chan_data_t *sngisdn_info = NULL;
sngisdn_event_data_t *sngisdn_event; sngisdn_event_data_t *sngisdn_event = NULL;
ftdm_assert(spInstId != 0, "Received DISCONNECT with invalid id"); ftdm_assert(spInstId != 0, "Received DISCONNECT with invalid id");
@ -208,13 +210,6 @@ void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, D
return; return;
} }
if (!sngisdn_info->spInstId) {
ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
sngisdn_info->spInstId = spInstId;
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);
}
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received DISCONNECT (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received DISCONNECT (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
@ -237,8 +232,8 @@ void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, D
void sngisdn_rcv_rel_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt) void sngisdn_rcv_rel_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt)
{ {
ISDN_FUNC_TRACE_ENTER(__FUNCTION__); ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info; sngisdn_chan_data_t *sngisdn_info = NULL;
sngisdn_event_data_t *sngisdn_event; sngisdn_event_data_t *sngisdn_event = NULL;
if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
!(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
@ -251,7 +246,7 @@ void sngisdn_rcv_rel_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, Re
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received RELEASE/RELEASE COMPLETE (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received RELEASE/RELEASE COMPLETE (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event)); memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_REL_IND; sngisdn_event->event_id = SNGISDN_EVENT_REL_IND;
@ -270,7 +265,7 @@ void sngisdn_rcv_dat_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, In
{ {
ISDN_FUNC_TRACE_ENTER(__FUNCTION__); ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info; sngisdn_chan_data_t *sngisdn_info;
sngisdn_event_data_t *sngisdn_event; sngisdn_event_data_t *sngisdn_event = NULL;
if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
!(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
@ -283,7 +278,7 @@ void sngisdn_rcv_dat_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, In
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received DATA IND suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received DATA IND suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event)); memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_DAT_IND; sngisdn_event->event_id = SNGISDN_EVENT_DAT_IND;
@ -302,7 +297,7 @@ void sngisdn_rcv_sshl_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, S
{ {
ISDN_FUNC_TRACE_ENTER(__FUNCTION__); ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info; sngisdn_chan_data_t *sngisdn_info;
sngisdn_event_data_t *sngisdn_event; sngisdn_event_data_t *sngisdn_event = NULL;
if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
!(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
@ -315,7 +310,7 @@ void sngisdn_rcv_sshl_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, S
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received SSHL IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received SSHL IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event)); memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_SSHL_IND; sngisdn_event->event_id = SNGISDN_EVENT_SSHL_IND;
@ -335,7 +330,7 @@ void sngisdn_rcv_sshl_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, S
{ {
ISDN_FUNC_TRACE_ENTER(__FUNCTION__); ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info; sngisdn_chan_data_t *sngisdn_info;
sngisdn_event_data_t *sngisdn_event; sngisdn_event_data_t *sngisdn_event = NULL;
if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
!(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
@ -348,7 +343,7 @@ void sngisdn_rcv_sshl_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, S
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received SSHL CFM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received SSHL CFM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event)); memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_SSHL_CFM; sngisdn_event->event_id = SNGISDN_EVENT_SSHL_CFM;
@ -367,7 +362,7 @@ void sngisdn_rcv_rmrt_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, R
{ {
ISDN_FUNC_TRACE_ENTER(__FUNCTION__); ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info; sngisdn_chan_data_t *sngisdn_info;
sngisdn_event_data_t *sngisdn_event; sngisdn_event_data_t *sngisdn_event = NULL;
if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
!(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
@ -380,7 +375,7 @@ void sngisdn_rcv_rmrt_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, R
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received RMRT IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received RMRT IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event)); memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_RMRT_IND; sngisdn_event->event_id = SNGISDN_EVENT_RMRT_IND;
@ -400,7 +395,7 @@ void sngisdn_rcv_rmrt_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, R
{ {
ISDN_FUNC_TRACE_ENTER(__FUNCTION__); ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info; sngisdn_chan_data_t *sngisdn_info;
sngisdn_event_data_t *sngisdn_event; sngisdn_event_data_t *sngisdn_event = NULL;
if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
!(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
@ -413,7 +408,7 @@ void sngisdn_rcv_rmrt_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, R
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received RESUME/RETRIEVE CFM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received RESUME/RETRIEVE CFM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event)); memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_RMRT_CFM; sngisdn_event->event_id = SNGISDN_EVENT_RMRT_CFM;
@ -433,7 +428,7 @@ void sngisdn_rcv_flc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, St
{ {
ISDN_FUNC_TRACE_ENTER(__FUNCTION__); ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info; sngisdn_chan_data_t *sngisdn_info;
sngisdn_event_data_t *sngisdn_event; sngisdn_event_data_t *sngisdn_event = NULL;
if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
!(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
@ -446,7 +441,7 @@ void sngisdn_rcv_flc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, St
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received FLOW CONTROL IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received FLOW CONTROL IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event)); memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_FLC_IND; sngisdn_event->event_id = SNGISDN_EVENT_FLC_IND;
@ -466,7 +461,7 @@ void sngisdn_rcv_fac_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, Fa
{ {
ISDN_FUNC_TRACE_ENTER(__FUNCTION__); ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info; sngisdn_chan_data_t *sngisdn_info;
sngisdn_event_data_t *sngisdn_event; sngisdn_event_data_t *sngisdn_event = NULL;
if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
!(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
@ -478,7 +473,7 @@ void sngisdn_rcv_fac_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, Fa
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received FACILITY IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received FACILITY IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event)); memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_FAC_IND; sngisdn_event->event_id = SNGISDN_EVENT_FAC_IND;
@ -499,7 +494,7 @@ void sngisdn_rcv_sta_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, St
{ {
ISDN_FUNC_TRACE_ENTER(__FUNCTION__); ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info; sngisdn_chan_data_t *sngisdn_info;
sngisdn_event_data_t *sngisdn_event; sngisdn_event_data_t *sngisdn_event = NULL;
if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
!(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
@ -512,7 +507,7 @@ void sngisdn_rcv_sta_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, St
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received STATUS CONFIRM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received STATUS CONFIRM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event)); memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_STA_CFM; sngisdn_event->event_id = SNGISDN_EVENT_STA_CFM;
@ -532,7 +527,7 @@ void sngisdn_rcv_srv_ind (int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces
ISDN_FUNC_TRACE_ENTER(__FUNCTION__); ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
unsigned i; unsigned i;
sngisdn_span_data_t *signal_data; sngisdn_span_data_t *signal_data;
sngisdn_event_data_t *sngisdn_event; sngisdn_event_data_t *sngisdn_event = NULL;
ftdm_log(FTDM_LOG_INFO, "Received SERVICE IND (dChan:%d ces:%u)\n", dChan, ces); ftdm_log(FTDM_LOG_INFO, "Received SERVICE IND (dChan:%d ces:%u)\n", dChan, ces);
@ -540,7 +535,7 @@ void sngisdn_rcv_srv_ind (int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces
for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) { for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) {
signal_data = g_sngisdn_data.dchans[dChan].spans[i]; signal_data = g_sngisdn_data.dchans[dChan].spans[i];
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event)); memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_SRV_IND; sngisdn_event->event_id = SNGISDN_EVENT_SRV_IND;
@ -560,8 +555,8 @@ void sngisdn_rcv_srv_cfm (int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces
{ {
ISDN_FUNC_TRACE_ENTER(__FUNCTION__); ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
unsigned i; unsigned i;
sngisdn_span_data_t *signal_data; sngisdn_span_data_t *signal_data = NULL;
sngisdn_event_data_t *sngisdn_event; sngisdn_event_data_t *sngisdn_event = NULL;
ftdm_log(FTDM_LOG_INFO, "Received SERVICE CFM (dChan:%d ces:%u)\n", dChan, ces); ftdm_log(FTDM_LOG_INFO, "Received SERVICE CFM (dChan:%d ces:%u)\n", dChan, ces);
@ -569,7 +564,7 @@ void sngisdn_rcv_srv_cfm (int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces
for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) { for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) {
signal_data = g_sngisdn_data.dchans[dChan].spans[i]; signal_data = g_sngisdn_data.dchans[dChan].spans[i];
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event)); memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_SRV_CFM; sngisdn_event->event_id = SNGISDN_EVENT_SRV_CFM;
@ -588,8 +583,8 @@ void sngisdn_rcv_rst_ind (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces
{ {
ISDN_FUNC_TRACE_ENTER(__FUNCTION__); ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
unsigned i; unsigned i;
sngisdn_span_data_t *signal_data; sngisdn_span_data_t *signal_data = NULL;
sngisdn_event_data_t *sngisdn_event; sngisdn_event_data_t *sngisdn_event = NULL;
ftdm_log(FTDM_LOG_INFO, "Received RESTART IND (dChan:%d ces:%u type:%u)\n", dChan, ces, evntType); ftdm_log(FTDM_LOG_INFO, "Received RESTART IND (dChan:%d ces:%u type:%u)\n", dChan, ces, evntType);
@ -597,7 +592,7 @@ void sngisdn_rcv_rst_ind (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces
for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) { for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) {
signal_data = g_sngisdn_data.dchans[dChan].spans[i]; signal_data = g_sngisdn_data.dchans[dChan].spans[i];
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event)); memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_RST_IND; sngisdn_event->event_id = SNGISDN_EVENT_RST_IND;
@ -618,7 +613,7 @@ void sngisdn_rcv_rst_cfm (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces
ISDN_FUNC_TRACE_ENTER(__FUNCTION__); ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
unsigned i; unsigned i;
sngisdn_span_data_t *signal_data; sngisdn_span_data_t *signal_data;
sngisdn_event_data_t *sngisdn_event; sngisdn_event_data_t *sngisdn_event = NULL;
ftdm_log(FTDM_LOG_INFO, "Received RESTART CFM (dChan:%d ces:%u type:%u)\n", dChan, ces, evntType); ftdm_log(FTDM_LOG_INFO, "Received RESTART CFM (dChan:%d ces:%u type:%u)\n", dChan, ces, evntType);
@ -626,7 +621,7 @@ void sngisdn_rcv_rst_cfm (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces
for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) { for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) {
signal_data = g_sngisdn_data.dchans[dChan].spans[i]; signal_data = g_sngisdn_data.dchans[dChan].spans[i];
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event)); memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_RST_CFM; sngisdn_event->event_id = SNGISDN_EVENT_RST_CFM;

View File

@ -74,7 +74,9 @@ void __inline__ clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info)
sngisdn_info->suInstId, sngisdn_info->spInstId); sngisdn_info->suInstId, sngisdn_info->spInstId);
ftdm_mutex_lock(g_sngisdn_data.ccs[sngisdn_info->glare.suId].mutex); ftdm_mutex_lock(g_sngisdn_data.ccs[sngisdn_info->glare.suId].mutex);
if (sngisdn_info->glare.spInstId != sngisdn_info->spInstId) {
g_sngisdn_data.ccs[sngisdn_info->glare.suId].active_spInstIds[sngisdn_info->glare.spInstId]=NULL; g_sngisdn_data.ccs[sngisdn_info->glare.suId].active_spInstIds[sngisdn_info->glare.spInstId]=NULL;
}
g_sngisdn_data.ccs[sngisdn_info->glare.suId].active_suInstIds[sngisdn_info->glare.suInstId]=NULL; g_sngisdn_data.ccs[sngisdn_info->glare.suId].active_suInstIds[sngisdn_info->glare.suInstId]=NULL;
ftdm_mutex_unlock(g_sngisdn_data.ccs[sngisdn_info->glare.suId].mutex); ftdm_mutex_unlock(g_sngisdn_data.ccs[sngisdn_info->glare.suId].mutex);
@ -427,6 +429,24 @@ void sngisdn_delayed_disconnect(void* p_sngisdn_info)
return; return;
} }
void sngisdn_facility_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_mutex_lock(ftdmchan->mutex);
if (ftdmchan->state == FTDM_CHANNEL_STATE_GET_CALLERID) {
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Facility timeout reached proceeding with call (suId:%d suInstId:%u spInstId:%u)\n",
signal_data->cc_id, sngisdn_info->spInstId, sngisdn_info->suInstId);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
}
ftdm_mutex_unlock(ftdmchan->mutex);
return;
}
ftdm_status_t sngisdn_check_free_ids(void) ftdm_status_t sngisdn_check_free_ids(void)
{ {
unsigned i; unsigned i;

View File

@ -444,8 +444,8 @@ int ftmod_ss7_mtp3_gen_config(void)
cfg.t.cfg.s.snGen.tmr.t21.enb = TRUE; /* t21 - waiting to restart traffic routed through adjacent SP */ cfg.t.cfg.s.snGen.tmr.t21.enb = TRUE; /* t21 - waiting to restart traffic routed through adjacent SP */
cfg.t.cfg.s.snGen.tmr.t21.val = 650; cfg.t.cfg.s.snGen.tmr.t21.val = 650;
# if (SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || defined(TDS_ROLL_UPGRADE_SUPPORT)) # if (SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || defined(TDS_ROLL_UPGRADE_SUPPORT))
cfg.t.cfg.s.snGen.t26.enb = TRUE; /* t26 - waiting to repeat traffic restart waiting message for ANSI */ cfg.t.cfg.s.snGen.tmr.t26.enb = TRUE; /* t26 - waiting to repeat traffic restart waiting message for ANSI */
cfg.t.cfg.s.snGen.t26.val = 600; cfg.t.cfg.s.snGen.tmr.t26.val = 600;
# endif # endif
#endif #endif
@ -744,10 +744,6 @@ int ftmod_ss7_mtp3_dlsap_config(int id)
cfg.t.cfg.s.snDLSAP.msgPrior = 0; /* management message priority */ cfg.t.cfg.s.snDLSAP.msgPrior = 0; /* management message priority */
cfg.t.cfg.s.snDLSAP.lnkType = k->mtp3.linkType; /* link type ANSI, ITU, BICI or CHINA */ cfg.t.cfg.s.snDLSAP.lnkType = k->mtp3.linkType; /* link type ANSI, ITU, BICI or CHINA */
cfg.t.cfg.s.snDLSAP.upSwtch = k->mtp3.switchType; /* user part switch type */ cfg.t.cfg.s.snDLSAP.upSwtch = k->mtp3.switchType; /* user part switch type */
# if (SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || SS7_CHINA)
cfg.t.cfg.s.snDLSAP.l2Type = LSN_MTP2_56KBPS; /* layer 2 type - 56kbps MTP2 link, 1.536Mbps MTP2 link or QSAAL link */
cfg.t.cfg.s.snDLSAP.isCLink = FALSE; /* identifies if the link is a C type link.Required to check if sls has to be rotated.*/
# endif
cfg.t.cfg.s.snDLSAP.maxSLTtry = MAX_SLTM_RETRIES; /* maximun times to retry SLTM */ cfg.t.cfg.s.snDLSAP.maxSLTtry = MAX_SLTM_RETRIES; /* maximun times to retry SLTM */
cfg.t.cfg.s.snDLSAP.p0QLen = 32; /* size of the priority 0 Q */ cfg.t.cfg.s.snDLSAP.p0QLen = 32; /* size of the priority 0 Q */
cfg.t.cfg.s.snDLSAP.p1QLen = 32; /* size of the priority 1 Q */ cfg.t.cfg.s.snDLSAP.p1QLen = 32; /* size of the priority 1 Q */
@ -775,17 +771,46 @@ int ftmod_ss7_mtp3_dlsap_config(int id)
cfg.t.cfg.s.snDLSAP.selector = 0; /* lower layer selector */ cfg.t.cfg.s.snDLSAP.selector = 0; /* lower layer selector */
cfg.t.cfg.s.snDLSAP.mem.region = S_REG; /* memory region id */ cfg.t.cfg.s.snDLSAP.mem.region = S_REG; /* memory region id */
cfg.t.cfg.s.snDLSAP.mem.pool = S_POOL; /* memory pool id */ cfg.t.cfg.s.snDLSAP.mem.pool = S_POOL; /* memory pool id */
#if( SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || SS7_CHINA )
cfg.t.cfg.s.snDLSAP.dpcLen = DPC24; /* dpc length 24 bits */
#else
cfg.t.cfg.s.snDLSAP.dpcLen = DPC14; /* dpc length 14 bits */
#endif
cfg.t.cfg.s.snDLSAP.spId = k->mtp3.mtp2Id ;/* service provider id */ cfg.t.cfg.s.snDLSAP.spId = k->mtp3.mtp2Id ;/* service provider id */
#if (SS7_ITU88 || SS7_CHINA || SS7_TTC || SS7_NTT || SS7_BICI )
cfg.t.cfg.s.snDLSAP.flushContFlag = FALSE; /* flush continue handling */ switch (k->mtp3.linkType) {
#else /**************************************************************************/
case (LSN_SW_ANS):
case (LSN_SW_ANS96):
case (LSN_SW_CHINA):
cfg.t.cfg.s.snDLSAP.dpcLen = DPC24; /* dpc length 24 bits */
cfg.t.cfg.s.snDLSAP.l2Type = LSN_MTP2_56KBPS; /* layer 2 type - 56kbps MTP2 link, 1.536Mbps MTP2 link or QSAAL link */
cfg.t.cfg.s.snDLSAP.isCLink = FALSE; /* identifies if the link is a C type link.Required to check if sls has to be rotated.*/
break;
/**************************************************************************/
case (LSN_SW_ITU):
cfg.t.cfg.s.snDLSAP.dpcLen = DPC14; /* dpc length 14 bits */
break;
/**************************************************************************/
default:
cfg.t.cfg.s.snDLSAP.dpcLen = DPC14; /* dpc length 14 bits */
break;
/**************************************************************************/
} /* switch (k->mtp3.linkType) */
switch (k->mtp3.linkType) {
/**************************************************************************/
case (LSN_SW_ANS):
case (LSN_SW_ANS96):
cfg.t.cfg.s.snDLSAP.flushContFlag = TRUE; /* flush continue handling */ cfg.t.cfg.s.snDLSAP.flushContFlag = TRUE; /* flush continue handling */
#endif break;
/**************************************************************************/
case (LSN_SW_ITU):
case (LSN_SW_CHINA):
cfg.t.cfg.s.snDLSAP.flushContFlag = FALSE; /* flush continue handling */
break;
/**************************************************************************/
default:
cfg.t.cfg.s.snDLSAP.flushContFlag = FALSE; /* flush continue handling */
break;
/**************************************************************************/
} /* switch (k->mtp3.linkType) */
cfg.t.cfg.s.snDLSAP.tmr.t1.enb = TRUE; /* t1 - delay to avoid missequencing on changeover */ cfg.t.cfg.s.snDLSAP.tmr.t1.enb = TRUE; /* t1 - delay to avoid missequencing on changeover */
cfg.t.cfg.s.snDLSAP.tmr.t1.val = k->mtp3.t1; cfg.t.cfg.s.snDLSAP.tmr.t1.val = k->mtp3.t1;
cfg.t.cfg.s.snDLSAP.tmr.t2.enb = TRUE; /* t2 - waiting for changeover ack */ cfg.t.cfg.s.snDLSAP.tmr.t2.enb = TRUE; /* t2 - waiting for changeover ack */
@ -1209,12 +1234,12 @@ int ftmod_ss7_isup_ckt_config(int id)
cfg.t.cfg.s.siCir.typeCntrl = k->typeCntrl; /* type of control */ cfg.t.cfg.s.siCir.typeCntrl = k->typeCntrl; /* type of control */
cfg.t.cfg.s.siCir.contReq = FALSE; /* continuity check required */ cfg.t.cfg.s.siCir.contReq = FALSE; /* continuity check required */
#if (SI_218_COMP || SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL) #if (SI_218_COMP || SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL)
cfg.t.cfg.s.siCir.firstCic =; /* First cic in the circuit group */ cfg.t.cfg.s.siCir.firstCic = 1; /* First cic in the circuit group */
cfg.t.cfg.s.siCir.numCir =; /* Number of circuits in the circuit group */ cfg.t.cfg.s.siCir.numCir = 24; /* Number of circuits in the circuit group */
cfg.t.cfg.s.siCir.nonSS7Con = TRUE; /* connecting to non SS7 network */ cfg.t.cfg.s.siCir.nonSS7Con = TRUE; /* connecting to non SS7 network */
cfg.t.cfg.s.siCir.outTrkGrpN =; /* outgoing trunk group number (For EXM) */ cfg.t.cfg.s.siCir.outTrkGrpN.length = 0; /* outgoing trunk group number (For EXM) */
cfg.t.cfg.s.siCir.cvrTrkClli =; /* Trunk Group number (For CVR validation) */ cfg.t.cfg.s.siCir.cvrTrkClli.length = 0; /* Trunk Group number (For CVR validation) */
cfg.t.cfg.s.siCir.clli =; /* common language location identifier */ cfg.t.cfg.s.siCir.clli.length = 0; /* common language location identifier */
#endif #endif
cfg.t.cfg.s.siCir.cirTmr.t3.enb = TRUE; /* t3 timer - overload received */ cfg.t.cfg.s.siCir.cirTmr.t3.enb = TRUE; /* t3 timer - overload received */
cfg.t.cfg.s.siCir.cirTmr.t3.val = k->t3; cfg.t.cfg.s.siCir.cirTmr.t3.val = k->t3;

View File

@ -71,6 +71,8 @@ ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ
ftdm_status_t handle_local_blk(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); ftdm_status_t handle_local_blk(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
ftdm_status_t handle_local_ubl(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); ftdm_status_t handle_local_ubl(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
ftdm_status_t handle_cgb_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
/******************************************************************************/ /******************************************************************************/
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
@ -898,12 +900,12 @@ ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/**************************************************************************/ /**************************************************************************/
case SIT_STA_CGBREQ: /* CGB request */ case SIT_STA_CGBREQ: /* CGB request */
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGB\n"); SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGB\n");
SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); handle_cgb_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
break; break;
/**************************************************************************/ /**************************************************************************/
case SIT_STA_CGUREQ: /* CGU request */ case SIT_STA_CGUREQ: /* CGU request */
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGU\n"); SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGU\n");
SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); handle_cgu_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
break; break;
/**************************************************************************/ /**************************************************************************/
case SIT_STA_CGQRYREQ: /* circuit group query request */ case SIT_STA_CGQRYREQ: /* circuit group query request */
@ -913,7 +915,7 @@ ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/**************************************************************************/ /**************************************************************************/
case SIT_STA_CGBRSP: /* mntc. oriented CGB response */ case SIT_STA_CGBRSP: /* mntc. oriented CGB response */
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx mntc CGB\n"); SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx mntc CGB\n");
SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); handle_cgb_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
break; break;
/**************************************************************************/ /**************************************************************************/
case SIT_STA_CGURSP: /* mntc. oriented CGU response */ case SIT_STA_CGURSP: /* mntc. oriented CGU response */
@ -1012,8 +1014,8 @@ ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
break; break;
/**************************************************************************/ /**************************************************************************/
case SIT_STA_CGBINFOIND: /* circuit grp blking ind , no resp req */ case SIT_STA_CGBINFOIND: /* circuit grp blking ind , no resp req */
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGB no resp req\n"); /*SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGB no resp req\n");*/
SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); /* handle_cgb_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);*/
break; break;
/**************************************************************************/ /**************************************************************************/
case SIT_STA_LMCQMINFOREQ: /* when LM requests ckt grp query */ case SIT_STA_LMCQMINFOREQ: /* when LM requests ckt grp query */
@ -1989,6 +1991,265 @@ ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit
return FTDM_SUCCESS; return FTDM_SUCCESS;
} }
/******************************************************************************/
ftdm_status_t handle_cgb_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
sngss7_chan_data_t *sngss7_info = NULL;
sngss7_span_data_t *sngss7_span = NULL;
ftdm_channel_t *ftdmchan = NULL;
int range;
uint8_t status[255];
int blockType = 0;
int byte = 0;
int bit = 0;
int x;
memset(&status[0], '\0', sizeof(status));
/* get the ftdmchan and ss7_chan_data from the circuit */
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return FTDM_FAIL;
}
/* grab the span info */
sngss7_span = ftdmchan->span->mod_data;
/* figure out what type of block needs to be applied */
if ((siStaEvnt->cgsmti.eh.pres == PRSNT_NODEF) && (siStaEvnt->cgsmti.typeInd.pres == PRSNT_NODEF)) {
blockType = siStaEvnt->cgsmti.typeInd.val;
} else {
SS7_ERROR("Received CGB with no circuit group supervision value on CIC = %d\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return FTDM_FAIL;
}
/* pull out the range value */
if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.range.pres == PRSNT_NODEF)) {
range = siStaEvnt->rangStat.range.val;
} else {
SS7_ERROR("Received CGB with no range value on CIC = %d\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return FTDM_FAIL;
}
/* pull out the status field */
if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.status.pres == PRSNT_NODEF)) {
for (x = 0; x < siStaEvnt->rangStat.status.len; x++) {
status[x] = siStaEvnt->rangStat.status.val[x];
}
} else {
SS7_ERROR("Received CGB with no status value on CIC = %d\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return FTDM_FAIL;
}
/* save the circuit, range and status */
sngss7_span->rx_cgb.circuit = circuit;
sngss7_span->rx_cgb.range = range;
sngss7_span->rx_cgb.type = blockType;
for (x = 0; x < siStaEvnt->rangStat.status.len; x++) {
sngss7_span->rx_cgb.status[x] = status[x];
}
/* loop over the cics starting from circuit until range+1 */
for (x = circuit; x < (circuit + range + 1); x++) {
/* grab the circuit in question */
if (extract_chan_data(x, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", x);
break;
}
/* now that we have the right channel...put a lock on it so no-one else can use it */
ftdm_mutex_lock(ftdmchan->mutex);
/* check if there is a pending state change, give it a bit to clear */
if (check_for_state_change(ftdmchan)) {
SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
ftdm_mutex_unlock(ftdmchan->mutex);
SS7_ASSERT;
};
#if 1
SS7_ERROR("KONRAD -> circuit=%d, byte=%d, bit=%d, status[byte]=%d, math=%d\n",
x,
byte,
bit,
status[byte],
(status[byte] & (1 << bit)));
#endif
if (status[byte] & (1 << bit)) {
switch (blockType) {
/**********************************************************************/
case 0: /* maintenance oriented */
sngss7_set_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX);
break;
/**********************************************************************/
case 1: /* hardware failure oriented */
sngss7_set_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX);
break;
/**********************************************************************/
case 2: /* reserved for national use */
break;
/**********************************************************************/
default:
break;
/**********************************************************************/
} /* switch (blockType) */
}
/* unlock the channel again before we exit */
ftdm_mutex_unlock(ftdmchan->mutex);
/* update the bit and byte counter*/
bit ++;
if (bit == 8) {
byte++;
bit = 0;
}
} /* for (x = circuit; x < (circuit + range + 1); x++) */
/* get the ftdmchan and ss7_chan_data from the circuit */
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return FTDM_FAIL;
}
ft_to_sngss7_cgba(ftdmchan);
return FTDM_SUCCESS;
}
/******************************************************************************/
ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
sngss7_chan_data_t *sngss7_info = NULL;
sngss7_span_data_t *sngss7_span = NULL;
ftdm_channel_t *ftdmchan = NULL;
int range;
uint8_t status[255];
int blockType = 0;
int byte = 0;
int bit = 0;
int x;
memset(&status[0], '\0', sizeof(status));
/* get the ftdmchan and ss7_chan_data from the circuit */
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return FTDM_FAIL;
}
/* grab the span info */
sngss7_span = ftdmchan->span->mod_data;
/* figure out what type of block needs to be applied */
if ((siStaEvnt->cgsmti.eh.pres == PRSNT_NODEF) && (siStaEvnt->cgsmti.typeInd.pres == PRSNT_NODEF)) {
blockType = siStaEvnt->cgsmti.typeInd.val;
} else {
SS7_ERROR("Received CGB with no circuit group supervision value on CIC = %d\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return FTDM_FAIL;
}
/* pull out the range value */
if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.range.pres == PRSNT_NODEF)) {
range = siStaEvnt->rangStat.range.val;
} else {
SS7_ERROR("Received CGB with no range value on CIC = %d\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return FTDM_FAIL;
}
/* pull out the status field */
if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.status.pres == PRSNT_NODEF)) {
for (x = 0; x < siStaEvnt->rangStat.status.len; x++) {
status[x] = siStaEvnt->rangStat.status.val[x];
}
} else {
SS7_ERROR("Received CGB with no status value on CIC = %d\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return FTDM_FAIL;
}
/* save the circuit, range and status */
sngss7_span->rx_cgu.circuit = circuit;
sngss7_span->rx_cgu.range = range;
sngss7_span->rx_cgu.type = blockType;
for (x = 0; x < siStaEvnt->rangStat.status.len; x++) {
sngss7_span->rx_cgu.status[x] = status[x];
}
/* loop over the cics starting from circuit until range+1 */
for (x = circuit; x < (circuit + range + 1); x++) {
/* grab the circuit in question */
if (extract_chan_data(x, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", x);
break;
}
/* now that we have the right channel...put a lock on it so no-one else can use it */
ftdm_mutex_lock(ftdmchan->mutex);
/* check if there is a pending state change, give it a bit to clear */
if (check_for_state_change(ftdmchan)) {
SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
ftdm_mutex_unlock(ftdmchan->mutex);
SS7_ASSERT;
};
if (status[byte] & (1 << bit)) {
switch (blockType) {
/**********************************************************************/
case 0: /* maintenance oriented */
sngss7_clear_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX);
break;
/**********************************************************************/
case 1: /* hardware failure oriented */
sngss7_clear_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX);
break;
/**********************************************************************/
case 2: /* reserved for national use */
break;
/**********************************************************************/
default:
break;
/**********************************************************************/
} /* switch (blockType) */
} /* */
/* unlock the channel again before we exit */
ftdm_mutex_unlock(ftdmchan->mutex);
/* update the bit and byte counter*/
bit ++;
if (bit == 8) {
byte++;
bit = 0;
}
} /* for (x = circuit; x < (circuit + range + 1); x++) */
/* get the ftdmchan and ss7_chan_data from the circuit */
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return FTDM_FAIL;
}
ft_to_sngss7_cgua(ftdmchan);
return FTDM_SUCCESS;
}
/******************************************************************************/ /******************************************************************************/
/* For Emacs: /* For Emacs:

View File

@ -272,10 +272,8 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
ftdm_interrupt_t *ftdm_sangoma_ss7_int[2]; ftdm_interrupt_t *ftdm_sangoma_ss7_int[2];
ftdm_span_t *ftdmspan = (ftdm_span_t *) obj; ftdm_span_t *ftdmspan = (ftdm_span_t *) obj;
ftdm_channel_t *ftdmchan = NULL; ftdm_channel_t *ftdmchan = NULL;
sngss7_chan_data_t *sngss7_info = NULL;
sngss7_event_data_t *sngss7_event = 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->mod_data;
int i;
ftdm_log (FTDM_LOG_INFO, "ftmod_sangoma_ss7 monitor thread for span=%u started.\n", ftdmspan->span_id); ftdm_log (FTDM_LOG_INFO, "ftmod_sangoma_ss7 monitor thread for span=%u started.\n", ftdmspan->span_id);
@ -344,73 +342,11 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
/**********************************************************************/ /**********************************************************************/
} /* switch ((ftdm_interrupt_wait(ftdm_sangoma_ss7_int, 100))) */ } /* switch ((ftdm_interrupt_wait(ftdm_sangoma_ss7_int, 100))) */
/* extract the span data structure */
sngss7_span = (sngss7_span_data_t *)ftdmspan->mod_data;
/* check if there is a GRS being processed on the span */ /* check if there is a GRS being processed on the span */
if (sngss7_span->rx_grs.range > 0) { if (sngss7_span->rx_grs.range > 0) {
ftdm_log(FTDM_LOG_DEBUG, "Found Rx GRS on span %d...checking circuits\n", ftdmspan->span_id); /* check if the rx_grs has cleared */
/*SS7_DEBUG("Found Rx GRS on span %d...checking circuits\n", ftdmspan->span_id);*/ check_if_rx_grs_processed(ftdmspan);
} /* if (sngss7_span->rx_grs.range > 0) */
/* check all the circuits in the range to see if they are done resetting */
for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
/* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
SS7_ASSERT;
}
/* lock the channel */
ftdm_mutex_lock(ftdmchan->mutex);
/* check if there is a state change pending on the channel */
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
/* check the state to the GRP_RESET_RX_DN flag */
if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) {
/* this channel is still resetting...do nothing */
goto GRS_UNLOCK_ALL;
} /* if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) */
} else {
/* state change pending */
goto GRS_UNLOCK_ALL;
}
} /* for ( i = circuit; i < (circuit + range + 1); i++) */
SS7_DEBUG("All circuits out of reset for GRS: circuit=%d, range=%d\n",
sngss7_span->rx_grs.circuit,
sngss7_span->rx_grs.range);
/* check all the circuits in the range to see if they are done resetting */
for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
/* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n",i);
SS7_ASSERT;
}
/* throw the GRP reset flag complete flag */
sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT);
/* move the channel to the down state */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
} /* for ( i = circuit; i < (circuit + range + 1); i++) */
GRS_UNLOCK_ALL:
for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
/* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
SS7_ASSERT;
}
/* unlock the channel */
ftdm_mutex_unlock(ftdmchan->mutex);
}
} /* if (ftdmspan->grs.range > 0) */
} /* master while loop */ } /* master while loop */
/* clear the IN_THREAD flag so that we know the thread is done */ /* clear the IN_THREAD flag so that we know the thread is done */

View File

@ -139,7 +139,6 @@ typedef struct sng_mtp_link {
uint32_t t23; uint32_t t23;
uint32_t t24; uint32_t t24;
uint32_t t25; uint32_t t25;
uint32_t t26;
uint32_t t27; uint32_t t27;
uint32_t t28; uint32_t t28;
uint32_t t29; uint32_t t29;
@ -188,6 +187,7 @@ typedef struct sng_route {
uint32_t t19; uint32_t t19;
uint32_t t21; uint32_t t21;
uint32_t t25; uint32_t t25;
uint32_t t26;
} sng_route_t; } sng_route_t;
typedef struct sng_isup_intf { typedef struct sng_isup_intf {
@ -329,6 +329,8 @@ typedef struct sngss7_glare_data {
typedef struct sngss7_group_data { typedef struct sngss7_group_data {
uint32_t circuit; uint32_t circuit;
uint32_t range; uint32_t range;
uint8_t status[255];
uint8_t type;
}sngss7_group_data_t; }sngss7_group_data_t;
typedef struct sngss7_chan_data { typedef struct sngss7_chan_data {
@ -348,6 +350,10 @@ typedef struct sngss7_span_data {
ftdm_sched_t *sched; ftdm_sched_t *sched;
sngss7_group_data_t rx_grs; sngss7_group_data_t rx_grs;
sngss7_group_data_t tx_grs; sngss7_group_data_t tx_grs;
sngss7_group_data_t rx_cgb;
sngss7_group_data_t tx_cgb;
sngss7_group_data_t rx_cgu;
sngss7_group_data_t tx_cgu;
ftdm_queue_t *event_queue; ftdm_queue_t *event_queue;
}sngss7_span_data_t; }sngss7_span_data_t;
@ -397,17 +403,15 @@ typedef enum {
FLAG_CKT_LC_BLOCK_RX = (1 << 18), FLAG_CKT_LC_BLOCK_RX = (1 << 18),
FLAG_CKT_LC_UNBLK_RX = (1 << 19), FLAG_CKT_LC_UNBLK_RX = (1 << 19),
FLAG_CKT_MN_BLOCK_RX = (1 << 20), FLAG_CKT_MN_BLOCK_RX = (1 << 20),
FLAG_CKT_MN_BLOCK_TX = (1 << 21), FLAG_CKT_MN_UNBLK_RX = (1 << 21),
FLAG_CKT_MN_UNBLK_RX = (1 << 22), FLAG_CKT_MN_BLOCK_TX = (1 << 22),
FLAG_CKT_MN_UNBLK_TX = (1 << 23), FLAG_CKT_MN_UNBLK_TX = (1 << 23),
FLAG_GRP_HW_BLOCK_RX = (1 << 24), FLAG_GRP_HW_BLOCK_RX = (1 << 24),
FLAG_GRP_HW_BLOCK_TX = (1 << 25), FLAG_GRP_HW_BLOCK_TX = (1 << 25),
FLAG_GRP_MN_BLOCK_RX = (1 << 26), FLAG_GRP_MN_BLOCK_RX = (1 << 26),
FLAG_GRP_MN_BLOCK_TX = (1 << 27), FLAG_GRP_MN_BLOCK_TX = (1 << 27),
FLAG_GRP_HW_UNBLK_RX = (1 << 28), FLAG_GRP_HW_UNBLK_TX = (1 << 28),
FLAG_GRP_HW_UNBLK_TX = (1 << 29), FLAG_GRP_MN_UNBLK_TX = (1 << 29)
FLAG_GRP_MN_UNBLK_RX = (1 << 30),
FLAG_GRP_MN_UNBLK_TX = (1 << 31)
} flag_t; } flag_t;
/******************************************************************************/ /******************************************************************************/
@ -465,6 +469,8 @@ void ft_to_sngss7_uba(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_lpa(ftdm_channel_t *ftdmchan); void ft_to_sngss7_lpa(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_gra(ftdm_channel_t *ftdmchan); void ft_to_sngss7_gra(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_grs(ftdm_channel_t *ftdmchan); void ft_to_sngss7_grs(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_cgba(ftdm_channel_t * ftdmchan);
void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan);
void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
void sngss7_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt); void sngss7_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt);
@ -524,6 +530,8 @@ int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *spa
void handle_isup_t35(void *userdata); void handle_isup_t35(void *userdata);
ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const char *data); ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const char *data);
ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan);
/******************************************************************************/ /******************************************************************************/
/* MACROS *********************************************************************/ /* MACROS *********************************************************************/

View File

@ -60,6 +60,9 @@ void ft_to_sngss7_lpa (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_gra(ftdm_channel_t * ftdmchan); void ft_to_sngss7_gra(ftdm_channel_t * ftdmchan);
void ft_to_sngss7_grs(ftdm_channel_t * ftdmchan); void ft_to_sngss7_grs(ftdm_channel_t * ftdmchan);
void ft_to_sngss7_cgba(ftdm_channel_t * ftdmchan);
void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan);
/******************************************************************************/ /******************************************************************************/
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
@ -114,6 +117,56 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
iam.txMedReq.trMedReq.pres = PRSNT_NODEF; iam.txMedReq.trMedReq.pres = PRSNT_NODEF;
iam.txMedReq.trMedReq.val = ftdmchan->caller_data.bearer_capability; iam.txMedReq.trMedReq.val = ftdmchan->caller_data.bearer_capability;
if ((g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].switchType == LSI_SW_ANS88) ||
(g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].switchType == LSI_SW_ANS92) ||
(g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].switchType == LSI_SW_ANS95)) {
iam.usrServInfoA.eh.pres = PRSNT_NODEF;
iam.usrServInfoA.infoTranCap.pres = PRSNT_NODEF;
switch (ftdmchan->caller_data.bearer_capability) {
/**********************************************************************/
case (FTDM_BEARER_CAP_SPEECH):
iam.usrServInfoA.infoTranCap.val = 0x0; /* speech as per ATIS-1000113.3.2005 */
break;
/**********************************************************************/
case (FTDM_BEARER_CAP_64K_UNRESTRICTED):
iam.usrServInfoA.infoTranCap.val = 0x8; /* unrestricted digital as per ATIS-1000113.3.2005 */
break;
/**********************************************************************/
case (FTDM_BEARER_CAP_3_1KHZ_AUDIO):
iam.usrServInfoA.infoTranCap.val = 0x10; /* 3.1kHz audio as per ATIS-1000113.3.2005 */
break;
/**********************************************************************/
default:
SS7_ERROR_CHAN(ftdmchan, "Unknown Bearer capability falling back to speech%s\n", " ");
iam.usrServInfoA.infoTranCap.val = 0x0; /* speech as per ATIS-1000113.3.2005 */
break;
/**********************************************************************/
} /* switch (ftdmchan->caller_data.bearer_capability) */
iam.usrServInfoA.cdeStand.pres = PRSNT_NODEF;
iam.usrServInfoA.cdeStand.val = 0x0; /* ITU-T standardized coding */
iam.usrServInfoA.tranMode.pres = PRSNT_NODEF;
iam.usrServInfoA.tranMode.val = 0x0; /* circuit mode */
iam.usrServInfoA.infoTranRate0.pres = PRSNT_NODEF;
iam.usrServInfoA.infoTranRate0.val = 0x10; /* 64kbps origination to destination */
iam.usrServInfoA.infoTranRate1.pres = PRSNT_NODEF;
iam.usrServInfoA.infoTranRate1.val = 0x10; /* 64kbps destination to origination */
iam.usrServInfoA.chanStruct.pres = PRSNT_NODEF;
iam.usrServInfoA.chanStruct.val = 0x1; /* 8kHz integrity */
iam.usrServInfoA.config.pres = PRSNT_NODEF;
iam.usrServInfoA.config.val = 0x0; /* point to point configuration */
iam.usrServInfoA.establish.pres = PRSNT_NODEF;
iam.usrServInfoA.establish.val = 0x0; /* on demand */
iam.usrServInfoA.symmetry.pres = PRSNT_NODEF;
iam.usrServInfoA.symmetry.val = 0x0; /* bi-directional symmetric */
iam.usrServInfoA.usrInfLyr1Prot.pres = PRSNT_NODEF;
iam.usrServInfoA.usrInfLyr1Prot.val = 0x2; /* G.711 ulaw */
iam.usrServInfoA.rateMultiplier.pres = PRSNT_NODEF;
iam.usrServInfoA.rateMultiplier.val = 0x1; /* 1x rate multipler */
} /* if ANSI */
/* copy down the called number information */ /* copy down the called number information */
copy_cdPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cdPtyNum); copy_cdPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cdPtyNum);
@ -485,6 +538,101 @@ void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan)
return; return;
} }
/******************************************************************************/
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_chan_data_t *sngss7_info = ftdmchan->call_data;
int x = 0;
SiStaEvnt cgba;
memset (&cgba, 0x0, sizeof(cgba));
/* fill in the circuit group supervisory message */
cgba.cgsmti.eh.pres = PRSNT_NODEF;
cgba.cgsmti.typeInd.pres = PRSNT_NODEF;
cgba.cgsmti.typeInd.val = sngss7_span->rx_cgb.type;
cgba.rangStat.eh.pres = PRSNT_NODEF;
/* fill in the range */
cgba.rangStat.range.pres = PRSNT_NODEF;
cgba.rangStat.range.val = sngss7_span->rx_cgb.range;
/* fill in the status */
cgba.rangStat.status.pres = PRSNT_NODEF;
cgba.rangStat.status.len = ((sngss7_span->rx_cgb.range + 1) >> 3) + (((sngss7_span->rx_cgb.range + 1) & 0x07) ? 1 : 0);
for(x = 0; x < cgba.rangStat.status.len; x++){
cgba.rangStat.status.val[x] = sngss7_span->rx_cgb.status[x];
}
sng_cc_sta_request (1,
0,
0,
sngss7_span->rx_cgb.circuit,
0,
SIT_STA_CGBRSP,
&cgba);
SS7_INFO_CHAN(ftdmchan, "Tx CGBA (%d:%d)\n",
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->rx_cgb.range));
/* clean out the saved data */
memset(&sngss7_span->rx_cgb, 0x0, sizeof(sngss7_group_data_t));
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/******************************************************************************/
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_chan_data_t *sngss7_info = ftdmchan->call_data;
int x = 0;
SiStaEvnt cgua;
memset (&cgua, 0x0, sizeof(cgua));
/* fill in the circuit group supervisory message */
cgua.cgsmti.eh.pres = PRSNT_NODEF;
cgua.cgsmti.typeInd.pres = PRSNT_NODEF;
cgua.cgsmti.typeInd.val = sngss7_span->rx_cgu.type;
cgua.rangStat.eh.pres = PRSNT_NODEF;
/* fill in the range */
cgua.rangStat.range.pres = PRSNT_NODEF;
cgua.rangStat.range.val = sngss7_span->rx_cgu.range;
/* fill in the status */
cgua.rangStat.status.pres = PRSNT_NODEF;
cgua.rangStat.status.len = ((sngss7_span->rx_cgu.range + 1) >> 3) + (((sngss7_span->rx_cgu.range + 1) & 0x07) ? 1 : 0);
for(x = 0; x < cgua.rangStat.status.len; x++){
cgua.rangStat.status.val[x] = sngss7_span->rx_cgu.status[x];
}
sng_cc_sta_request (1,
0,
0,
sngss7_span->rx_cgu.circuit,
0,
SIT_STA_CGURSP,
&cgua);
SS7_INFO_CHAN(ftdmchan, "Tx CGUA (%d:%d)\n",
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->rx_cgu.range));
/* clean out the saved data */
memset(&sngss7_span->rx_cgu, 0x0, sizeof(sngss7_group_data_t));
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/******************************************************************************/ /******************************************************************************/
/* For Emacs: /* For Emacs:
* Local Variables: * Local Variables:

View File

@ -57,6 +57,7 @@ unsigned long get_unique_id(void);
ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan); ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan);
ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan);
/******************************************************************************/ /******************************************************************************/
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
@ -451,6 +452,78 @@ unsigned long get_unique_id(void)
} }
/******************************************************************************/ /******************************************************************************/
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;
int i;
ftdm_log(FTDM_LOG_DEBUG, "Found Rx GRS on span %d...checking circuits\n", ftdmspan->span_id);
/* check all the circuits in the range to see if they are done resetting */
for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
/* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
SS7_ASSERT;
}
/* lock the channel */
ftdm_mutex_lock(ftdmchan->mutex);
/* check if there is a state change pending on the channel */
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
/* check the state to the GRP_RESET_RX_DN flag */
if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) {
/* this channel is still resetting...do nothing */
goto GRS_UNLOCK_ALL;
} /* if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) */
} else {
/* state change pending */
goto GRS_UNLOCK_ALL;
}
} /* for ( i = circuit; i < (circuit + range + 1); i++) */
SS7_DEBUG("All circuits out of reset for GRS: circuit=%d, range=%d\n",
sngss7_span->rx_grs.circuit,
sngss7_span->rx_grs.range);
/* check all the circuits in the range to see if they are done resetting */
for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
/* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n",i);
SS7_ASSERT;
}
/* throw the GRP reset flag complete flag */
sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT);
/* move the channel to the down state */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
} /* for ( i = circuit; i < (circuit + range + 1); i++) */
GRS_UNLOCK_ALL:
for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
/* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
SS7_ASSERT;
}
/* unlock the channel */
ftdm_mutex_unlock(ftdmchan->mutex);
}
return FTDM_SUCCESS;
}
/******************************************************************************/
/******************************************************************************/ /******************************************************************************/
/* For Emacs: /* For Emacs:

View File

@ -551,6 +551,15 @@ static int ftmod_ss7_parse_mtp_link(ftdm_conf_node_t *mtp_link, sng_mtp_link_t *
} else if (!strcasecmp(parm->val, "INDIA")) { } else if (!strcasecmp(parm->val, "INDIA")) {
mtpLink->mtp3.switchType = LSI_SW_INDIA; mtpLink->mtp3.switchType = LSI_SW_INDIA;
SS7_DEBUG("\tFoundmtpLink->switchType = \"INDIA\"\n"); SS7_DEBUG("\tFoundmtpLink->switchType = \"INDIA\"\n");
} else if (!strcasecmp(parm->val, "ansi88")) {
mtpLink->mtp3.switchType = LSI_SW_ANS88;
SS7_DEBUG("\tFoundmtpLink->switchType = \"ANSI88\"\n");
} else if (!strcasecmp(parm->val, "ansi92")) {
mtpLink->mtp3.switchType = LSI_SW_ANS92;
SS7_DEBUG("\tFoundmtpLink->switchType = \"ANSI92\"\n");
} else if (!strcasecmp(parm->val, "ansi95")) {
mtpLink->mtp3.switchType = LSI_SW_ANS95;
SS7_DEBUG("\tFoundmtpLink->switchType = \"ANSI95\"\n");
} else { } else {
SS7_ERROR("\tFound an invalid linktype of \"%s\"!\n", parm->val); SS7_ERROR("\tFound an invalid linktype of \"%s\"!\n", parm->val);
return FTDM_FAIL; return FTDM_FAIL;
@ -1159,6 +1168,11 @@ static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route)
} else { } else {
g_ftdm_sngss7_data.cfg.mtpRoute[i].t25 = 100; g_ftdm_sngss7_data.cfg.mtpRoute[i].t25 = 100;
} }
if (mtp3_route->t26 != 0) {
g_ftdm_sngss7_data.cfg.mtpRoute[i].t26 = mtp3_route->t26;
} else {
g_ftdm_sngss7_data.cfg.mtpRoute[i].t26 = 100;
}
return 0; return 0;
} }

View File

@ -259,7 +259,10 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
chan->physical_chan_id = x; chan->physical_chan_id = x;
chan->rate = 8000; chan->rate = 8000;
if (type == FTDM_CHAN_TYPE_FXS || type == FTDM_CHAN_TYPE_FXO || type == FTDM_CHAN_TYPE_B) { if (type == FTDM_CHAN_TYPE_FXS
|| type == FTDM_CHAN_TYPE_FXO
|| type == FTDM_CHAN_TYPE_CAS
|| type == FTDM_CHAN_TYPE_B) {
int err; int err;
dtmf = "software"; dtmf = "software";

View File

@ -1974,10 +1974,19 @@ unsigned int ldl_session_terminate(ldl_session_t *session)
{ {
iks *iq, *sess; iks *iq, *sess;
unsigned int id; unsigned int id;
apr_hash_t *hash = session->handle->sessions;
new_session_iq(session, &iq, &sess, &id, "terminate"); new_session_iq(session, &iq, &sess, &id, "terminate");
schedule_packet(session->handle, id, iq, LDL_RETRY); schedule_packet(session->handle, id, iq, LDL_RETRY);
if (session->id) {
apr_hash_set(hash, session->id, APR_HASH_KEY_STRING, NULL);
}
if (session->them) {
apr_hash_set(hash, session->them, APR_HASH_KEY_STRING, NULL);
}
return id; return id;
} }
@ -2471,6 +2480,11 @@ int ldl_handle_running(ldl_handle_t *handle)
} }
void ldl_session_set_gateway(ldl_session_t *session)
{
ldl_set_flag(session, LDL_FLAG_GATEWAY);
}
int ldl_session_gateway(ldl_session_t *session) int ldl_session_gateway(ldl_session_t *session)
{ {
return ldl_test_flag(session, LDL_FLAG_GATEWAY) ? 1 : 0; return ldl_test_flag(session, LDL_FLAG_GATEWAY) ? 1 : 0;

View File

@ -593,6 +593,7 @@ ldl_status ldl_handle_init(ldl_handle_t **handle,
void ldl_handle_run(ldl_handle_t *handle); void ldl_handle_run(ldl_handle_t *handle);
int ldl_session_gateway(ldl_session_t *handle); int ldl_session_gateway(ldl_session_t *handle);
void ldl_session_set_gateway(ldl_session_t *session);
/*! /*!
\brief Stop a libDingaLing handle \brief Stop a libDingaLing handle

View File

@ -207,6 +207,13 @@ struct t30_state_s
/*! \brief This is only used in full duplex (e.g. ISDN) modes. */ /*! \brief This is only used in full duplex (e.g. ISDN) modes. */
int timer_t8; int timer_t8;
/* These fields are guessed based on compiler error forensics, I added them to fix the build -anthm */
int remote_interrupts_allowed;
int rtp_events;
int rtn_events;
int retransmit_capable;
/* end guessed fields */
/*! \brief TRUE once the far end FAX entity has been detected. */ /*! \brief TRUE once the far end FAX entity has been detected. */
int far_end_detected; int far_end_detected;

View File

@ -682,6 +682,8 @@ SPAN_DECLARE(void) t30_get_transfer_statistics(t30_state_t *s, t30_stats_t *t);
\param state TRUE to enable interrupt request, else FALSE. */ \param state TRUE to enable interrupt request, else FALSE. */
SPAN_DECLARE(void) t30_local_interrupt_request(t30_state_t *s, int state); SPAN_DECLARE(void) t30_local_interrupt_request(t30_state_t *s, int state);
SPAN_DECLARE(void) t30_remote_interrupts_allowed(t30_state_t *s, int state);
#if defined(__cplusplus) #if defined(__cplusplus)
} }
#endif #endif

View File

@ -2377,6 +2377,8 @@ static int send_response_to_pps(t30_state_t *s)
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
#define VET_ALL_FCD_FRAMES
static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len) static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len)
{ {
int page; int page;
@ -2387,6 +2389,10 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len)
int frame_no; int frame_no;
int first_bad_frame; int first_bad_frame;
int image_ended; int image_ended;
#if defined(VET_ALL_FCD_FRAMES)
int first;
int expected_len;
#endif
if (len < 7) if (len < 7)
{ {
@ -2469,12 +2475,35 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len)
/* Build a bit map of which frames we now have stored OK */ /* Build a bit map of which frames we now have stored OK */
first_bad_frame = 256; first_bad_frame = 256;
#if defined(VET_ALL_FCD_FRAMES)
first = TRUE;
expected_len = 256;
#endif
for (i = 0; i < 32; i++) for (i = 0; i < 32; i++)
{ {
s->ecm_frame_map[i + 3] = 0; s->ecm_frame_map[i + 3] = 0;
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
{ {
frame_no = (i << 3) + j; frame_no = (i << 3) + j;
#if defined(VET_ALL_FCD_FRAMES)
if (s->ecm_len[frame_no] >= 0)
{
if (frame_no < s->ecm_frames - 1)
{
if (first)
{
if (s->ecm_len[frame_no] == 64)
expected_len = 64;
first = FALSE;
}
if (s->ecm_len[frame_no] != expected_len)
{
span_log(&s->logging, SPAN_LOG_FLOW, "Bad length ECM frame - %d\n", s->ecm_len[frame_no]);
s->ecm_len[frame_no] = -1;
}
}
}
#endif
if (s->ecm_len[frame_no] < 0) if (s->ecm_len[frame_no] < 0)
{ {
s->ecm_frame_map[i + 3] |= (1 << j); s->ecm_frame_map[i + 3] |= (1 << j);
@ -2524,14 +2553,18 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len)
switch (s->last_pps_fcf2) switch (s->last_pps_fcf2)
{ {
case T30_NULL:
case T30_EOP:
case T30_PRI_EOP:
case T30_EOM:
case T30_PRI_EOM:
case T30_EOS:
case T30_MPS:
case T30_PRI_MPS: case T30_PRI_MPS:
case T30_PRI_EOM:
case T30_PRI_EOP:
if (s->remote_interrupts_allowed)
{
}
/* Fall through */
case T30_NULL:
case T30_MPS:
case T30_EOM:
case T30_EOS:
case T30_EOP:
if (s->receiver_not_ready_count > 0) if (s->receiver_not_ready_count > 0)
{ {
s->receiver_not_ready_count--; s->receiver_not_ready_count--;
@ -2635,7 +2668,13 @@ static void process_rx_fcd(t30_state_t *s, const uint8_t *msg, int len)
switch (s->state) switch (s->state)
{ {
case T30_STATE_F_DOC_ECM: case T30_STATE_F_DOC_ECM:
if (len <= 4 + 256) if (len > 4 + 256)
{
/* For other frame types we kill the call on an unexpected frame length. For FCD frames it is better to just ignore
the frame, and let retries sort things out. */
span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s frame length - %d\n", t30_frametype(msg[0]), len);
}
else
{ {
frame_no = msg[3]; frame_no = msg[3];
/* Just store the actual image data, and record its length */ /* Just store the actual image data, and record its length */
@ -2645,10 +2684,6 @@ static void process_rx_fcd(t30_state_t *s, const uint8_t *msg, int len)
/* In case we are just after a CTC/CTR exchange, which kicked us back to long training */ /* In case we are just after a CTC/CTR exchange, which kicked us back to long training */
s->short_train = TRUE; s->short_train = TRUE;
} }
else
{
unexpected_frame_length(s, msg, len);
}
/* We have received something, so any missing carrier status is out of date */ /* We have received something, so any missing carrier status is out of date */
if (s->current_status == T30_ERR_RX_NOCARRIER) if (s->current_status == T30_ERR_RX_NOCARRIER)
s->current_status = T30_ERR_OK; s->current_status = T30_ERR_OK;
@ -2677,6 +2712,7 @@ static void process_rx_rcp(t30_state_t *s, const uint8_t *msg, int len)
case T30_STATE_F_POST_DOC_ECM: case T30_STATE_F_POST_DOC_ECM:
/* Just ignore this. It must be an extra RCP. Several are usually sent, to maximise the chance /* Just ignore this. It must be an extra RCP. Several are usually sent, to maximise the chance
of receiving a correct one. */ of receiving a correct one. */
timer_t2_start(s);
break; break;
default: default:
unexpected_non_final_frame(s, msg, len); unexpected_non_final_frame(s, msg, len);
@ -3063,6 +3099,11 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
case T30_DCS: case T30_DCS:
process_rx_dcs(s, msg, len); process_rx_dcs(s, msg, len);
break; break;
case T30_PRI_MPS:
if (s->remote_interrupts_allowed)
{
}
/* Fall through */
case T30_MPS: case T30_MPS:
/* Treat this as a bad quality page. */ /* Treat this as a bad quality page. */
if (s->phase_d_handler) if (s->phase_d_handler)
@ -3072,16 +3113,11 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
set_state(s, T30_STATE_III_Q_RTN); set_state(s, T30_STATE_III_Q_RTN);
send_simple_frame(s, T30_RTN); send_simple_frame(s, T30_RTN);
break; break;
case T30_PRI_MPS: case T30_PRI_EOM:
/* Treat this as a bad quality page. */ if (s->remote_interrupts_allowed)
if (s->phase_d_handler)
{ {
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
} }
s->next_rx_step = msg[2] & 0xFE; /* Fall through */
set_state(s, T30_STATE_III_Q_RTN);
break;
case T30_EOM: case T30_EOM:
case T30_EOS: case T30_EOS:
/* Treat this as a bad quality page. */ /* Treat this as a bad quality page. */
@ -3093,16 +3129,11 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
set_state(s, T30_STATE_III_Q_RTN); set_state(s, T30_STATE_III_Q_RTN);
send_simple_frame(s, T30_RTN); send_simple_frame(s, T30_RTN);
break; break;
case T30_PRI_EOM: case T30_PRI_EOP:
/* Treat this as a bad quality page. */ if (s->remote_interrupts_allowed)
if (s->phase_d_handler)
{ {
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
} }
s->next_rx_step = T30_PRI_EOM; /* Fall through */
set_state(s, T30_STATE_III_Q_RTN);
break;
case T30_EOP: case T30_EOP:
/* Treat this as a bad quality page. */ /* Treat this as a bad quality page. */
if (s->phase_d_handler) if (s->phase_d_handler)
@ -3112,16 +3143,6 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
set_state(s, T30_STATE_III_Q_RTN); set_state(s, T30_STATE_III_Q_RTN);
send_simple_frame(s, T30_RTN); send_simple_frame(s, T30_RTN);
break; break;
case T30_PRI_EOP:
/* Treat this as a bad quality page. */
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
s->next_rx_step = msg[2] & 0xFE;
set_state(s, T30_STATE_III_Q_RTN);
break;
case T30_DCN: case T30_DCN:
s->current_status = T30_ERR_RX_DCNDATA; s->current_status = T30_ERR_RX_DCNDATA;
disconnect(s); disconnect(s);
@ -3148,6 +3169,11 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg,
fcf = msg[2] & 0xFE; fcf = msg[2] & 0xFE;
switch (fcf) switch (fcf)
{ {
case T30_PRI_MPS:
if (s->remote_interrupts_allowed)
{
}
/* Fall through */
case T30_MPS: case T30_MPS:
s->next_rx_step = fcf; s->next_rx_step = fcf;
queue_phase(s, T30_PHASE_D_TX); queue_phase(s, T30_PHASE_D_TX);
@ -3179,41 +3205,11 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg,
break; break;
} }
break; break;
case T30_PRI_MPS: case T30_PRI_EOM:
s->next_rx_step = fcf; if (s->remote_interrupts_allowed)
switch (copy_quality(s))
{ {
case T30_COPY_QUALITY_PERFECT:
case T30_COPY_QUALITY_GOOD:
rx_end_page(s);
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
} }
terminate_operation_in_progress(s); /* Fall through */
set_state(s, T30_STATE_III_Q_MCF);
break;
case T30_COPY_QUALITY_POOR:
rx_end_page(s);
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
terminate_operation_in_progress(s);
set_state(s, T30_STATE_III_Q_RTP);
break;
case T30_COPY_QUALITY_BAD:
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
set_state(s, T30_STATE_III_Q_RTN);
break;
}
break;
case T30_EOM: case T30_EOM:
case T30_EOS: case T30_EOS:
s->next_rx_step = fcf; s->next_rx_step = fcf;
@ -3247,41 +3243,11 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg,
break; break;
} }
break; break;
case T30_PRI_EOM: case T30_PRI_EOP:
s->next_rx_step = fcf; if (s->remote_interrupts_allowed)
switch (copy_quality(s))
{ {
case T30_COPY_QUALITY_PERFECT:
case T30_COPY_QUALITY_GOOD:
rx_end_page(s);
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
} }
terminate_operation_in_progress(s); /* Fall through */
set_state(s, T30_STATE_III_Q_MCF);
break;
case T30_COPY_QUALITY_POOR:
rx_end_page(s);
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
terminate_operation_in_progress(s);
set_state(s, T30_STATE_III_Q_RTP);
break;
case T30_COPY_QUALITY_BAD:
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
set_state(s, T30_STATE_III_Q_RTN);
break;
}
break;
case T30_EOP: case T30_EOP:
s->next_rx_step = fcf; s->next_rx_step = fcf;
queue_phase(s, T30_PHASE_D_TX); queue_phase(s, T30_PHASE_D_TX);
@ -3312,41 +3278,6 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg,
break; break;
} }
break; break;
case T30_PRI_EOP:
s->next_rx_step = fcf;
switch (copy_quality(s))
{
case T30_COPY_QUALITY_PERFECT:
case T30_COPY_QUALITY_GOOD:
rx_end_page(s);
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
terminate_operation_in_progress(s);
set_state(s, T30_STATE_III_Q_MCF);
break;
case T30_COPY_QUALITY_POOR:
rx_end_page(s);
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
terminate_operation_in_progress(s);
set_state(s, T30_STATE_III_Q_RTP);
break;
case T30_COPY_QUALITY_BAD:
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
set_state(s, T30_STATE_III_Q_RTN);
break;
}
break;
case T30_DCN: case T30_DCN:
s->current_status = T30_ERR_RX_DCNFAX; s->current_status = T30_ERR_RX_DCNFAX;
disconnect(s); disconnect(s);
@ -3384,21 +3315,7 @@ static void process_state_f_doc_and_post_doc_ecm(t30_state_t *s, const uint8_t *
case T4_RCP: case T4_RCP:
/* Return to control for partial page. These might come through with or without the final frame tag. /* Return to control for partial page. These might come through with or without the final frame tag.
Here we deal with the "final frame tag" case. */ Here we deal with the "final frame tag" case. */
if (s->state == T30_STATE_F_DOC_ECM) process_rx_rcp(s, msg, len);
{
/* Return to control for partial page */
set_state(s, T30_STATE_F_POST_DOC_ECM);
queue_phase(s, T30_PHASE_D_RX);
timer_t2_start(s);
/* We have received something, so any missing carrier status is out of date */
if (s->current_status == T30_ERR_RX_NOCARRIER)
s->current_status = T30_ERR_OK;
}
else
{
/* Just ignore this. It must be an extra RCP. Several are usually sent, to maximise the chance
of receiving a correct one. */
}
break; break;
case T30_EOR: case T30_EOR:
if (len != 4) if (len != 4)
@ -3413,7 +3330,10 @@ static void process_state_f_doc_and_post_doc_ecm(t30_state_t *s, const uint8_t *
case T30_PRI_EOP: case T30_PRI_EOP:
case T30_PRI_EOM: case T30_PRI_EOM:
case T30_PRI_MPS: case T30_PRI_MPS:
if (s->remote_interrupts_allowed)
{
/* TODO: Alert operator */ /* TODO: Alert operator */
}
/* Fall through */ /* Fall through */
case T30_NULL: case T30_NULL:
case T30_EOP: case T30_EOP:
@ -3651,11 +3571,22 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
fcf = msg[2] & 0xFE; fcf = msg[2] & 0xFE;
switch (fcf) switch (fcf)
{ {
case T30_PIP:
if (s->remote_interrupts_allowed)
{
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
}
/* Fall through */
case T30_MCF: case T30_MCF:
switch (s->next_tx_step) switch (s->next_tx_step)
{ {
case T30_MPS:
case T30_PRI_MPS: case T30_PRI_MPS:
case T30_MPS:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf); s->phase_d_handler(s, s->phase_d_user_data, fcf);
@ -3668,8 +3599,8 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
set_state(s, T30_STATE_I); set_state(s, T30_STATE_I);
queue_phase(s, T30_PHASE_C_NON_ECM_TX); queue_phase(s, T30_PHASE_C_NON_ECM_TX);
break; break;
case T30_EOM:
case T30_PRI_EOM: case T30_PRI_EOM:
case T30_EOM:
case T30_EOS: case T30_EOS:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) if (s->phase_d_handler)
@ -3678,8 +3609,8 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
report_tx_result(s, TRUE); report_tx_result(s, TRUE);
return_to_phase_b(s, FALSE); return_to_phase_b(s, FALSE);
break; break;
case T30_EOP:
case T30_PRI_EOP: case T30_PRI_EOP:
case T30_EOP:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf); s->phase_d_handler(s, s->phase_d_user_data, fcf);
@ -3690,13 +3621,11 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
} }
break; break;
case T30_RTP: case T30_RTP:
#if 0
s->rtp_events++; s->rtp_events++;
#endif
switch (s->next_tx_step) switch (s->next_tx_step)
{ {
case T30_MPS:
case T30_PRI_MPS: case T30_PRI_MPS:
case T30_MPS:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf); s->phase_d_handler(s, s->phase_d_user_data, fcf);
@ -3717,8 +3646,8 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
queue_phase(s, T30_PHASE_B_TX); queue_phase(s, T30_PHASE_B_TX);
restart_sending_document(s); restart_sending_document(s);
break; break;
case T30_EOM:
case T30_PRI_EOM: case T30_PRI_EOM:
case T30_EOM:
case T30_EOS: case T30_EOS:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) if (s->phase_d_handler)
@ -3727,8 +3656,8 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
/* TODO: should go back to T, and resend */ /* TODO: should go back to T, and resend */
return_to_phase_b(s, TRUE); return_to_phase_b(s, TRUE);
break; break;
case T30_EOP:
case T30_PRI_EOP: case T30_PRI_EOP:
case T30_EOP:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf); s->phase_d_handler(s, s->phase_d_user_data, fcf);
@ -3737,20 +3666,27 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
break; break;
} }
break; break;
case T30_PIN:
if (s->remote_interrupts_allowed)
{
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
}
/* Fall through */
case T30_RTN: case T30_RTN:
#if 0
s->rtn_events++; s->rtn_events++;
#endif
switch (s->next_tx_step) switch (s->next_tx_step)
{ {
case T30_MPS:
case T30_PRI_MPS: case T30_PRI_MPS:
case T30_MPS:
s->retries = 0; s->retries = 0;
if (s->phase_d_handler) if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf); s->phase_d_handler(s, s->phase_d_user_data, fcf);
#if 0
if (!s->retransmit_capable) if (!s->retransmit_capable)
#endif
{ {
/* Send the next page, regardless of the problem with the current one. */ /* Send the next page, regardless of the problem with the current one. */
if (tx_start_page(s)) if (tx_start_page(s))
@ -3771,29 +3707,26 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
queue_phase(s, T30_PHASE_B_TX); queue_phase(s, T30_PHASE_B_TX);
restart_sending_document(s); restart_sending_document(s);
break; break;
case T30_EOM:
case T30_PRI_EOM: case T30_PRI_EOM:
case T30_EOM:
case T30_EOS: case T30_EOS:
s->retries = 0; s->retries = 0;
if (s->phase_d_handler) if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf); s->phase_d_handler(s, s->phase_d_user_data, fcf);
#if 0
if (s->retransmit_capable) if (s->retransmit_capable)
{ {
/* Wait for DIS */ /* Wait for DIS */
} }
else else
#endif
{ {
return_to_phase_b(s, TRUE); return_to_phase_b(s, TRUE);
} }
break; break;
case T30_EOP:
case T30_PRI_EOP: case T30_PRI_EOP:
case T30_EOP:
s->retries = 0; s->retries = 0;
if (s->phase_d_handler) if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf); s->phase_d_handler(s, s->phase_d_user_data, fcf);
#if 0
if (s->retransmit_capable) if (s->retransmit_capable)
{ {
/* Send fresh training, and then repeat the last page */ /* Send fresh training, and then repeat the last page */
@ -3809,36 +3742,19 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
restart_sending_document(s); restart_sending_document(s);
} }
else else
#endif
{ {
send_dcn(s); send_dcn(s);
} }
break; break;
} }
break; break;
case T30_PIP:
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
case T30_PIN:
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
case T30_DCN: case T30_DCN:
switch (s->next_tx_step) switch (s->next_tx_step)
{ {
case T30_MPS:
case T30_PRI_MPS: case T30_PRI_MPS:
case T30_EOM:
case T30_PRI_EOM: case T30_PRI_EOM:
case T30_MPS:
case T30_EOM:
case T30_EOS: case T30_EOS:
/* Unexpected DCN after EOM, EOS or MPS sequence */ /* Unexpected DCN after EOM, EOS or MPS sequence */
s->current_status = T30_ERR_RX_DCNPHD; s->current_status = T30_ERR_RX_DCNPHD;
@ -4019,8 +3935,8 @@ static void process_state_iv_pps_null(t30_state_t *s, const uint8_t *msg, int le
span_log(&s->logging, SPAN_LOG_FLOW, "Moving on to the next page\n"); span_log(&s->logging, SPAN_LOG_FLOW, "Moving on to the next page\n");
switch (s->next_tx_step) switch (s->next_tx_step)
{ {
case T30_MPS:
case T30_PRI_MPS: case T30_PRI_MPS:
case T30_MPS:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf); s->phase_d_handler(s, s->phase_d_user_data, fcf);
@ -4036,8 +3952,8 @@ static void process_state_iv_pps_null(t30_state_t *s, const uint8_t *msg, int le
send_first_ecm_frame(s); send_first_ecm_frame(s);
} }
break; break;
case T30_EOM:
case T30_PRI_EOM: case T30_PRI_EOM:
case T30_EOM:
case T30_EOS: case T30_EOS:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) if (s->phase_d_handler)
@ -4046,8 +3962,8 @@ static void process_state_iv_pps_null(t30_state_t *s, const uint8_t *msg, int le
report_tx_result(s, TRUE); report_tx_result(s, TRUE);
return_to_phase_b(s, FALSE); return_to_phase_b(s, FALSE);
break; break;
case T30_EOP:
case T30_PRI_EOP: case T30_PRI_EOP:
case T30_EOP:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf); s->phase_d_handler(s, s->phase_d_user_data, fcf);
@ -4094,6 +4010,17 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
fcf = msg[2] & 0xFE; fcf = msg[2] & 0xFE;
switch (fcf) switch (fcf)
{ {
case T30_PIP:
if (s->remote_interrupts_allowed)
{
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
}
/* Fall through */
case T30_MCF: case T30_MCF:
s->retries = 0; s->retries = 0;
s->timer_t5 = 0; s->timer_t5 = 0;
@ -4112,8 +4039,8 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
span_log(&s->logging, SPAN_LOG_FLOW, "Moving on to the next page\n"); span_log(&s->logging, SPAN_LOG_FLOW, "Moving on to the next page\n");
switch (s->next_tx_step) switch (s->next_tx_step)
{ {
case T30_MPS:
case T30_PRI_MPS: case T30_PRI_MPS:
case T30_MPS:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf); s->phase_d_handler(s, s->phase_d_user_data, fcf);
@ -4129,8 +4056,8 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
send_first_ecm_frame(s); send_first_ecm_frame(s);
} }
break; break;
case T30_EOM:
case T30_PRI_EOM: case T30_PRI_EOM:
case T30_EOM:
case T30_EOS: case T30_EOS:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) if (s->phase_d_handler)
@ -4139,8 +4066,8 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
report_tx_result(s, TRUE); report_tx_result(s, TRUE);
return_to_phase_b(s, FALSE); return_to_phase_b(s, FALSE);
break; break;
case T30_EOP:
case T30_PRI_EOP: case T30_PRI_EOP:
case T30_EOP:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf); s->phase_d_handler(s, s->phase_d_user_data, fcf);
@ -4158,22 +4085,6 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
set_state(s, T30_STATE_IV_PPS_RNR); set_state(s, T30_STATE_IV_PPS_RNR);
send_rr(s); send_rr(s);
break; break;
case T30_PIP:
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
case T30_PIN:
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
case T30_PPR: case T30_PPR:
process_rx_ppr(s, msg, len); process_rx_ppr(s, msg, len);
break; break;
@ -4187,6 +4098,17 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
case T30_FNV: case T30_FNV:
process_rx_fnv(s, msg, len); process_rx_fnv(s, msg, len);
break; break;
case T30_PIN:
if (s->remote_interrupts_allowed)
{
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
}
/* Fall through */
default: default:
/* We don't know what to do with this. */ /* We don't know what to do with this. */
unexpected_final_frame(s, msg, len); unexpected_final_frame(s, msg, len);
@ -4203,6 +4125,17 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len
fcf = msg[2] & 0xFE; fcf = msg[2] & 0xFE;
switch (fcf) switch (fcf)
{ {
case T30_PIP:
if (s->remote_interrupts_allowed)
{
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
}
/* Fall through */
case T30_MCF: case T30_MCF:
s->retries = 0; s->retries = 0;
s->timer_t5 = 0; s->timer_t5 = 0;
@ -4221,8 +4154,8 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len
span_log(&s->logging, SPAN_LOG_FLOW, "Moving on to the next page\n"); span_log(&s->logging, SPAN_LOG_FLOW, "Moving on to the next page\n");
switch (s->next_tx_step) switch (s->next_tx_step)
{ {
case T30_MPS:
case T30_PRI_MPS: case T30_PRI_MPS:
case T30_MPS:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf); s->phase_d_handler(s, s->phase_d_user_data, fcf);
@ -4238,8 +4171,8 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len
send_first_ecm_frame(s); send_first_ecm_frame(s);
} }
break; break;
case T30_EOM:
case T30_PRI_EOM: case T30_PRI_EOM:
case T30_EOM:
case T30_EOS: case T30_EOS:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) if (s->phase_d_handler)
@ -4248,8 +4181,8 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len
report_tx_result(s, TRUE); report_tx_result(s, TRUE);
return_to_phase_b(s, FALSE); return_to_phase_b(s, FALSE);
break; break;
case T30_EOP:
case T30_PRI_EOP: case T30_PRI_EOP:
case T30_EOP:
tx_end_page(s); tx_end_page(s);
if (s->phase_d_handler) if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf); s->phase_d_handler(s, s->phase_d_user_data, fcf);
@ -4267,22 +4200,6 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len
set_state(s, T30_STATE_IV_PPS_RNR); set_state(s, T30_STATE_IV_PPS_RNR);
send_rr(s); send_rr(s);
break; break;
case T30_PIP:
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
case T30_PIN:
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
case T30_DCN: case T30_DCN:
s->current_status = T30_ERR_RX_DCNRRD; s->current_status = T30_ERR_RX_DCNRRD;
disconnect(s); disconnect(s);
@ -4293,6 +4210,17 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len
case T30_FNV: case T30_FNV:
process_rx_fnv(s, msg, len); process_rx_fnv(s, msg, len);
break; break;
case T30_PIN:
if (s->remote_interrupts_allowed)
{
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
}
/* Fall through */
default: default:
/* We don't know what to do with this. */ /* We don't know what to do with this. */
unexpected_final_frame(s, msg, len); unexpected_final_frame(s, msg, len);
@ -4345,14 +4273,6 @@ static void process_state_iv_eor(t30_state_t *s, const uint8_t *msg, int len)
set_state(s, T30_STATE_IV_EOR_RNR); set_state(s, T30_STATE_IV_EOR_RNR);
send_rr(s); send_rr(s);
break; break;
case T30_PIN:
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
case T30_ERR: case T30_ERR:
/* TODO: Continue with the next message if MPS or EOM? */ /* TODO: Continue with the next message if MPS or EOM? */
s->timer_t5 = 0; s->timer_t5 = 0;
@ -4364,6 +4284,17 @@ static void process_state_iv_eor(t30_state_t *s, const uint8_t *msg, int len)
case T30_FNV: case T30_FNV:
process_rx_fnv(s, msg, len); process_rx_fnv(s, msg, len);
break; break;
case T30_PIN:
if (s->remote_interrupts_allowed)
{
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
}
/* Fall through */
default: default:
/* We don't know what to do with this. */ /* We don't know what to do with this. */
unexpected_final_frame(s, msg, len); unexpected_final_frame(s, msg, len);
@ -4386,14 +4317,6 @@ static void process_state_iv_eor_rnr(t30_state_t *s, const uint8_t *msg, int len
set_state(s, T30_STATE_IV_EOR_RNR); set_state(s, T30_STATE_IV_EOR_RNR);
send_rr(s); send_rr(s);
break; break;
case T30_PIN:
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
case T30_ERR: case T30_ERR:
/* TODO: Continue with the next message if MPS or EOM? */ /* TODO: Continue with the next message if MPS or EOM? */
s->timer_t5 = 0; s->timer_t5 = 0;
@ -4409,6 +4332,17 @@ static void process_state_iv_eor_rnr(t30_state_t *s, const uint8_t *msg, int len
case T30_FNV: case T30_FNV:
process_rx_fnv(s, msg, len); process_rx_fnv(s, msg, len);
break; break;
case T30_PIN:
if (s->remote_interrupts_allowed)
{
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
}
/* Fall through */
default: default:
/* We don't know what to do with this. */ /* We don't know what to do with this. */
unexpected_final_frame(s, msg, len); unexpected_final_frame(s, msg, len);
@ -4596,7 +4530,7 @@ static void process_rx_control_msg(t30_state_t *s, const uint8_t *msg, int len)
/* The following handles context sensitive message types, which should /* The following handles context sensitive message types, which should
occur at the end of message sequences. They should, therefore have occur at the end of message sequences. They should, therefore have
the final frame flag set. */ the final frame flag set. */
span_log(&s->logging, SPAN_LOG_FLOW, "In state %d\n", s->state); span_log(&s->logging, SPAN_LOG_FLOW, "Rx final frame in state %d\n", s->state);
switch (s->state) switch (s->state)
{ {
@ -5082,11 +5016,11 @@ static void timer_t2_expired(t30_state_t *s)
case T30_STATE_F_POST_RCP_MCF: case T30_STATE_F_POST_RCP_MCF:
switch (s->next_rx_step) switch (s->next_rx_step)
{ {
case T30_EOM:
case T30_PRI_EOM: case T30_PRI_EOM:
case T30_EOM:
case T30_EOS: case T30_EOS:
/* We didn't receive a response to our T30_MCF after T30_EOM, so we must be OK /* We didn't receive a response to our T30_MCF after T30_EOM, so we must be OK
to proceed to phase B, and pretty act like its the beginning of a call. */ to proceed to phase B, and pretty much act like its the beginning of a call. */
span_log(&s->logging, SPAN_LOG_FLOW, "Returning to phase B after %s\n", t30_frametype(s->next_rx_step)); span_log(&s->logging, SPAN_LOG_FLOW, "Returning to phase B after %s\n", t30_frametype(s->next_rx_step));
set_phase(s, T30_PHASE_B_TX); set_phase(s, T30_PHASE_B_TX);
timer_t2_start(s); timer_t2_start(s);
@ -5109,6 +5043,8 @@ static void timer_t2_expired(t30_state_t *s)
case T30_STATE_F_POST_DOC_ECM: case T30_STATE_F_POST_DOC_ECM:
case T30_STATE_F_POST_DOC_NON_ECM: case T30_STATE_F_POST_DOC_NON_ECM:
/* While waiting for next FAX page */ /* While waiting for next FAX page */
/* Figure 5-2b/T.30 and note 7 says we should allow 1 to 3 tries at this point.
The way we work now is effectively hard coding a 1 try limit */
s->current_status = T30_ERR_RX_T2EXPMPS; s->current_status = T30_ERR_RX_T2EXPMPS;
break; break;
#if 0 #if 0
@ -5873,8 +5809,8 @@ SPAN_DECLARE(void) t30_front_end_status(void *user_data, int status)
{ {
switch (s->next_rx_step) switch (s->next_rx_step)
{ {
case T30_MPS:
case T30_PRI_MPS: case T30_PRI_MPS:
case T30_MPS:
/* We should now start to get another page */ /* We should now start to get another page */
if (s->error_correcting_mode) if (s->error_correcting_mode)
{ {
@ -5888,15 +5824,15 @@ SPAN_DECLARE(void) t30_front_end_status(void *user_data, int status)
} }
timer_t2_start(s); timer_t2_start(s);
break; break;
case T30_EOM:
case T30_PRI_EOM: case T30_PRI_EOM:
case T30_EOM:
case T30_EOS: case T30_EOS:
/* See if we get something back, before moving to phase B. */ /* See if we get something back, before moving to phase B. */
timer_t2_start(s); timer_t2_start(s);
set_phase(s, T30_PHASE_D_RX); set_phase(s, T30_PHASE_D_RX);
break; break;
case T30_EOP:
case T30_PRI_EOP: case T30_PRI_EOP:
case T30_EOP:
/* Wait for a DCN. */ /* Wait for a DCN. */
set_phase(s, T30_PHASE_D_RX); set_phase(s, T30_PHASE_D_RX);
timer_t4_start(s); timer_t4_start(s);
@ -6256,6 +6192,12 @@ SPAN_DECLARE(void) t30_local_interrupt_request(t30_state_t *s, int state)
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) t30_remote_interrupts_allowed(t30_state_t *s, int state)
{
s->remote_interrupts_allowed = state;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) t30_restart(t30_state_t *s) SPAN_DECLARE(int) t30_restart(t30_state_t *s)
{ {
s->phase = T30_PHASE_IDLE; s->phase = T30_PHASE_IDLE;
@ -6276,10 +6218,9 @@ SPAN_DECLARE(int) t30_restart(t30_state_t *s)
/* The page number is only reset at call establishment */ /* The page number is only reset at call establishment */
s->rx_page_number = 0; s->rx_page_number = 0;
s->tx_page_number = 0; s->tx_page_number = 0;
#if 0
s->rtn_events = 0; s->rtn_events = 0;
s->rtp_events = 0; s->rtp_events = 0;
#endif s->local_interrupt_pending = FALSE;
s->far_end_detected = FALSE; s->far_end_detected = FALSE;
s->timer_t0_t1 = ms_to_samples(DEFAULT_TIMER_T0); s->timer_t0_t1 = ms_to_samples(DEFAULT_TIMER_T0);
if (s->calling_party) if (s->calling_party)

View File

@ -2602,7 +2602,9 @@ SPAN_DECLARE(t31_state_t *) t31_init(t31_state_t *s,
t38_tx_packet_handler_t *tx_t38_packet_handler, t38_tx_packet_handler_t *tx_t38_packet_handler,
void *tx_t38_packet_user_data) void *tx_t38_packet_user_data)
{ {
#if 0
v8_parms_t v8_parms; v8_parms_t v8_parms;
#endif
int alloced; int alloced;
if (at_tx_handler == NULL || modem_control_handler == NULL) if (at_tx_handler == NULL || modem_control_handler == NULL)

View File

@ -426,7 +426,6 @@ static int set_next_tx_type(t38_gateway_state_t *s)
t38_gateway_hdlc_state_t *u; t38_gateway_hdlc_state_t *u;
t = &s->audio.modems; t = &s->audio.modems;
u = &s->core.hdlc_to_modem;
t38_non_ecm_buffer_report_output_status(&s->core.non_ecm_to_modem, &s->logging); t38_non_ecm_buffer_report_output_status(&s->core.non_ecm_to_modem, &s->logging);
if (t->next_tx_handler) if (t->next_tx_handler)
{ {
@ -447,6 +446,7 @@ static int set_next_tx_type(t38_gateway_state_t *s)
return TRUE; return TRUE;
} }
/*endif*/ /*endif*/
u = &s->core.hdlc_to_modem;
if (u->in == u->out) if (u->in == u->out)
return FALSE; return FALSE;
/*endif*/ /*endif*/
@ -1057,6 +1057,8 @@ static int process_rx_missing(t38_core_state_t *t, void *user_data, int rx_seq_n
static int process_rx_indicator(t38_core_state_t *t, void *user_data, int indicator) static int process_rx_indicator(t38_core_state_t *t, void *user_data, int indicator)
{ {
t38_gateway_state_t *s; t38_gateway_state_t *s;
t38_gateway_hdlc_state_t *u;
int immediate;
s = (t38_gateway_state_t *) user_data; s = (t38_gateway_state_t *) user_data;
@ -1067,25 +1069,50 @@ static int process_rx_indicator(t38_core_state_t *t, void *user_data, int indica
return 0; return 0;
} }
/*endif*/ /*endif*/
if (s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in].contents)
u = &s->core.hdlc_to_modem;
immediate = (u->in == u->out);
if (u->buf[u->in].contents)
{ {
if (++s->core.hdlc_to_modem.in >= T38_TX_HDLC_BUFS) if (++u->in >= T38_TX_HDLC_BUFS)
s->core.hdlc_to_modem.in = 0; u->in = 0;
/*endif*/ /*endif*/
} }
/*endif*/ /*endif*/
s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in].contents = (indicator | FLAG_INDICATOR); u->buf[u->in].contents = (indicator | FLAG_INDICATOR);
if (++s->core.hdlc_to_modem.in >= T38_TX_HDLC_BUFS) if (++u->in >= T38_TX_HDLC_BUFS)
s->core.hdlc_to_modem.in = 0; u->in = 0;
/*endif*/ /*endif*/
t38_non_ecm_buffer_set_mode(&s->core.non_ecm_to_modem, s->core.image_data_mode, s->core.min_row_bits);
if (immediate)
{
span_log(&s->logging,
SPAN_LOG_FLOW,
"Changing - (%d) %s -> %s\n",
silence_gen_remainder(&(s->audio.modems.silence_gen)),
t38_indicator_to_str(t->current_rx_indicator),
t38_indicator_to_str(indicator));
switch (s->t38x.current_rx_field_class)
{
case T38_FIELD_CLASS_NONE:
break;
case T38_FIELD_CLASS_HDLC:
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC shutdown\n");
hdlc_tx_frame(&s->audio.modems.hdlc_tx, NULL, 0);
break;
case T38_FIELD_CLASS_NON_ECM:
break;
}
}
else
{
span_log(&s->logging, span_log(&s->logging,
SPAN_LOG_FLOW, SPAN_LOG_FLOW,
"Queued change - (%d) %s -> %s\n", "Queued change - (%d) %s -> %s\n",
silence_gen_remainder(&(s->audio.modems.silence_gen)), silence_gen_remainder(&(s->audio.modems.silence_gen)),
t38_indicator_to_str(t->current_rx_indicator), t38_indicator_to_str(t->current_rx_indicator),
t38_indicator_to_str(indicator)); t38_indicator_to_str(indicator));
}
s->t38x.current_rx_field_class = T38_FIELD_CLASS_NONE; s->t38x.current_rx_field_class = T38_FIELD_CLASS_NONE;
/* We need to set this here, since we might have been called as a fake /* We need to set this here, since we might have been called as a fake
indication when the real one was missing */ indication when the real one was missing */
@ -1440,6 +1467,8 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
xx->corrupt_current_frame[0] = FALSE; xx->corrupt_current_frame[0] = FALSE;
break; break;
case T38_FIELD_T4_NON_ECM_DATA: case T38_FIELD_T4_NON_ECM_DATA:
if (xx->current_rx_field_class == T38_FIELD_CLASS_NONE)
t38_non_ecm_buffer_set_mode(&s->core.non_ecm_to_modem, s->core.image_data_mode, s->core.min_row_bits);
xx->current_rx_field_class = T38_FIELD_CLASS_NON_ECM; xx->current_rx_field_class = T38_FIELD_CLASS_NON_ECM;
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in]; hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
if (hdlc_buf->contents != (data_type | FLAG_DATA)) if (hdlc_buf->contents != (data_type | FLAG_DATA))
@ -1454,6 +1483,8 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
xx->corrupt_current_frame[0] = FALSE; xx->corrupt_current_frame[0] = FALSE;
break; break;
case T38_FIELD_T4_NON_ECM_SIG_END: case T38_FIELD_T4_NON_ECM_SIG_END:
if (xx->current_rx_field_class == T38_FIELD_CLASS_NONE)
t38_non_ecm_buffer_set_mode(&s->core.non_ecm_to_modem, s->core.image_data_mode, s->core.min_row_bits);
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in]; hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
/* Some T.38 implementations send multiple T38_FIELD_T4_NON_ECM_SIG_END messages, in IFP packets with /* Some T.38 implementations send multiple T38_FIELD_T4_NON_ECM_SIG_END messages, in IFP packets with
incrementing sequence numbers, which are actually repeats. They get through to this point because incrementing sequence numbers, which are actually repeats. They get through to this point because
@ -2432,8 +2463,8 @@ SPAN_DECLARE(t38_gateway_state_t *) t38_gateway_init(t38_gateway_state_t *s,
s->core.to_t38.octets_per_data_packet = 1; s->core.to_t38.octets_per_data_packet = 1;
s->core.ecm_allowed = TRUE; s->core.ecm_allowed = TRUE;
t38_non_ecm_buffer_init(&s->core.non_ecm_to_modem, FALSE, 0);
//s->core.ms_per_tx_chunk = DEFAULT_MS_PER_TX_CHUNK; //s->core.ms_per_tx_chunk = DEFAULT_MS_PER_TX_CHUNK;
t38_non_ecm_buffer_init(&s->core.non_ecm_to_modem, FALSE, 0);
restart_rx_modem(s); restart_rx_modem(s);
s->core.timed_mode = TIMED_MODE_STARTUP; s->core.timed_mode = TIMED_MODE_STARTUP;
s->core.samples_to_timeout = 1; s->core.samples_to_timeout = 1;

View File

@ -103,6 +103,7 @@ SWITCH_BEGIN_EXTERN_C
switch_caller_profile_flag_t flags; switch_caller_profile_flag_t flags;
struct switch_caller_profile *originator_caller_profile; struct switch_caller_profile *originator_caller_profile;
struct switch_caller_profile *originatee_caller_profile; struct switch_caller_profile *originatee_caller_profile;
struct switch_caller_profile *origination_caller_profile;
struct switch_caller_profile *hunt_caller_profile; struct switch_caller_profile *hunt_caller_profile;
struct switch_channel_timetable *times; struct switch_channel_timetable *times;
struct switch_caller_extension *caller_extension; struct switch_caller_extension *caller_extension;

View File

@ -215,6 +215,20 @@ SWITCH_DECLARE(void) switch_channel_set_originatee_caller_profile(switch_channel
*/ */
SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_originatee_caller_profile(switch_channel_t *channel); SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_originatee_caller_profile(switch_channel_t *channel);
/*!
\brief Set the given channel's origination caller profile
\param channel channel to assign the profile to
\param caller_profile the profile to assign
*/
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
\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 \brief Retrive the given channel's unique id

View File

@ -37,6 +37,7 @@
#define CC_AGENT_TYPE_UUID_STANDBY "uuid-standby" #define CC_AGENT_TYPE_UUID_STANDBY "uuid-standby"
#define CC_SQLITE_DB_NAME "callcenter" #define CC_SQLITE_DB_NAME "callcenter"
#define CC_MAX_TIME_DIFF_CHECK 5
/* TODO /* TODO
drop caller if no agent login drop caller if no agent login
dont allow new caller dont allow new caller
@ -53,6 +54,16 @@ SWITCH_MODULE_DEFINITION(mod_callcenter, mod_callcenter_load, mod_callcenter_shu
static const char *global_cf = "callcenter.conf"; static const char *global_cf = "callcenter.conf";
struct cc_status_table {
const char *name;
int status;
};
struct cc_state_table {
const char *name;
int state;
};
typedef enum { typedef enum {
CC_STATUS_SUCCESS, CC_STATUS_SUCCESS,
CC_STATUS_FALSE, CC_STATUS_FALSE,
@ -77,12 +88,7 @@ typedef enum {
CC_TIER_STATE_STANDBY = 5 CC_TIER_STATE_STANDBY = 5
} cc_tier_state_t; } cc_tier_state_t;
struct cc_tier_state_table { static struct cc_state_table STATE_CHART[] = {
const char *name;
cc_tier_state_t state;
};
static struct cc_tier_state_table STATE_CHART[] = {
{"Unknown", CC_TIER_STATE_UNKNOWN}, {"Unknown", CC_TIER_STATE_UNKNOWN},
{"No Answer", CC_TIER_STATE_NO_ANSWER}, {"No Answer", CC_TIER_STATE_NO_ANSWER},
{"Ready", CC_TIER_STATE_READY}, {"Ready", CC_TIER_STATE_READY},
@ -101,12 +107,7 @@ typedef enum {
CC_AGENT_STATUS_ON_BREAK = 4 CC_AGENT_STATUS_ON_BREAK = 4
} cc_agent_status_t; } cc_agent_status_t;
struct cc_agent_status_table { static struct cc_status_table AGENT_STATUS_CHART[] = {
const char *name;
cc_agent_status_t status;
};
static struct cc_agent_status_table AGENT_STATUS_CHART[] = {
{"Unknown", CC_AGENT_STATUS_UNKNOWN}, {"Unknown", CC_AGENT_STATUS_UNKNOWN},
{"Logged Out", CC_AGENT_STATUS_LOGGED_OUT}, {"Logged Out", CC_AGENT_STATUS_LOGGED_OUT},
{"Available", CC_AGENT_STATUS_AVAILABLE}, {"Available", CC_AGENT_STATUS_AVAILABLE},
@ -124,12 +125,7 @@ typedef enum {
CC_AGENT_STATE_IDLE = 4 CC_AGENT_STATE_IDLE = 4
} cc_agent_state_t; } cc_agent_state_t;
struct cc_agent_state_table { static struct cc_state_table AGENT_STATE_CHART[] = {
const char *name;
cc_agent_state_t state;
};
static struct cc_agent_state_table AGENT_STATE_CHART[] = {
{"Unknown", CC_AGENT_STATE_UNKNOWN}, {"Unknown", CC_AGENT_STATE_UNKNOWN},
{"Waiting", CC_AGENT_STATE_WAITING}, {"Waiting", CC_AGENT_STATE_WAITING},
{"Receiving", CC_AGENT_STATE_RECEIVING}, {"Receiving", CC_AGENT_STATE_RECEIVING},
@ -147,12 +143,7 @@ typedef enum {
CC_MEMBER_STATE_ABANDONED = 4 CC_MEMBER_STATE_ABANDONED = 4
} cc_member_state_t; } cc_member_state_t;
struct cc_member_state_table { static struct cc_state_table MEMBER_STATE_CHART[] = {
const char *name;
cc_member_state_t state;
};
static struct cc_member_state_table MEMBER_STATE_CHART[] = {
{"Unknown", CC_MEMBER_STATE_UNKNOWN}, {"Unknown", CC_MEMBER_STATE_UNKNOWN},
{"Waiting", CC_MEMBER_STATE_WAITING}, {"Waiting", CC_MEMBER_STATE_WAITING},
{"Trying", CC_MEMBER_STATE_TRYING}, {"Trying", CC_MEMBER_STATE_TRYING},
@ -162,10 +153,24 @@ static struct cc_member_state_table MEMBER_STATE_CHART[] = {
}; };
/*static char queues_sql[] = struct cc_member_cancel_reason_table {
"CREATE TABLE queues (\n" const char *name;
" name VARCHAR(255)\n" ");\n"; int reason;
*/ };
typedef enum {
CC_MEMBER_CANCEL_REASON_NONE,
CC_MEMBER_CANCEL_REASON_TIMEOUT,
CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT
} cc_member_cancel_reason_t;
static struct cc_member_cancel_reason_table MEMBER_CANCEL_REASON_CHART[] = {
{"NONE", CC_MEMBER_CANCEL_REASON_NONE},
{"TIMEOUT", CC_MEMBER_CANCEL_REASON_TIMEOUT},
{"NO_AGENT_TIMEOUT", CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT},
{NULL, 0}
};
static char members_sql[] = static char members_sql[] =
"CREATE TABLE members (\n" "CREATE TABLE members (\n"
" queue VARCHAR(255),\n" " queue VARCHAR(255),\n"
@ -222,7 +227,6 @@ static char agents_sql[] =
" ready_time INTEGER NOT NULL DEFAULT 0\n" " ready_time INTEGER NOT NULL DEFAULT 0\n"
");\n"; ");\n";
static char tiers_sql[] = static char tiers_sql[] =
"CREATE TABLE tiers (\n" "CREATE TABLE tiers (\n"
" queue VARCHAR(255),\n" " queue VARCHAR(255),\n"
@ -247,7 +251,7 @@ const char * cc_tier_state2str(cc_tier_state_t state)
uint8_t x; uint8_t x;
const char *str = "Unknown"; const char *str = "Unknown";
for (x = 0; x < (sizeof(STATE_CHART) / sizeof(struct cc_tier_state_table)) - 1; x++) { for (x = 0; x < (sizeof(STATE_CHART) / sizeof(struct cc_state_table)) - 1; x++) {
if (STATE_CHART[x].state == state) { if (STATE_CHART[x].state == state) {
str = STATE_CHART[x].name; str = STATE_CHART[x].name;
break; break;
@ -262,7 +266,7 @@ cc_tier_state_t cc_tier_str2state(const char *str)
uint8_t x; uint8_t x;
cc_tier_state_t state = CC_TIER_STATE_UNKNOWN; cc_tier_state_t state = CC_TIER_STATE_UNKNOWN;
for (x = 0; x < (sizeof(STATE_CHART) / sizeof(struct cc_tier_state_table)) - 1 && STATE_CHART[x].name; x++) { for (x = 0; x < (sizeof(STATE_CHART) / sizeof(struct cc_state_table)) - 1 && STATE_CHART[x].name; x++) {
if (!strcasecmp(STATE_CHART[x].name, str)) { if (!strcasecmp(STATE_CHART[x].name, str)) {
state = STATE_CHART[x].state; state = STATE_CHART[x].state;
break; break;
@ -271,12 +275,41 @@ cc_tier_state_t cc_tier_str2state(const char *str)
return state; return state;
} }
const char * cc_member_cancel_reason2str(cc_member_cancel_reason_t reason)
{
uint8_t x;
const char *str = "NONE";
for (x = 0; x < (sizeof(MEMBER_CANCEL_REASON_CHART) / sizeof(struct cc_member_cancel_reason_table)) - 1; x++) {
if (MEMBER_CANCEL_REASON_CHART[x].reason == reason) {
str = MEMBER_CANCEL_REASON_CHART[x].name;
break;
}
}
return str;
}
cc_member_cancel_reason_t cc_member_cancel_str2reason(const char *str)
{
uint8_t x;
cc_member_cancel_reason_t reason = CC_MEMBER_CANCEL_REASON_NONE;
for (x = 0; x < (sizeof(MEMBER_CANCEL_REASON_CHART) / sizeof(struct cc_member_cancel_reason_table)) - 1 && MEMBER_CANCEL_REASON_CHART[x].name; x++) {
if (!strcasecmp(MEMBER_CANCEL_REASON_CHART[x].name, str)) {
reason = MEMBER_CANCEL_REASON_CHART[x].reason;
break;
}
}
return reason;
}
const char * cc_agent_status2str(cc_agent_status_t status) const char * cc_agent_status2str(cc_agent_status_t status)
{ {
uint8_t x; uint8_t x;
const char *str = "Unknown"; const char *str = "Unknown";
for (x = 0; x < (sizeof(AGENT_STATUS_CHART) / sizeof(struct cc_agent_status_table)) - 1; x++) { for (x = 0; x < (sizeof(AGENT_STATUS_CHART) / sizeof(struct cc_status_table)) - 1; x++) {
if (AGENT_STATUS_CHART[x].status == status) { if (AGENT_STATUS_CHART[x].status == status) {
str = AGENT_STATUS_CHART[x].name; str = AGENT_STATUS_CHART[x].name;
break; break;
@ -291,7 +324,7 @@ cc_agent_status_t cc_agent_str2status(const char *str)
uint8_t x; uint8_t x;
cc_agent_status_t status = CC_AGENT_STATUS_UNKNOWN; cc_agent_status_t status = CC_AGENT_STATUS_UNKNOWN;
for (x = 0; x < (sizeof(AGENT_STATUS_CHART) / sizeof(struct cc_agent_status_table)) - 1 && AGENT_STATUS_CHART[x].name; x++) { for (x = 0; x < (sizeof(AGENT_STATUS_CHART) / sizeof(struct cc_status_table)) - 1 && AGENT_STATUS_CHART[x].name; x++) {
if (!strcasecmp(AGENT_STATUS_CHART[x].name, str)) { if (!strcasecmp(AGENT_STATUS_CHART[x].name, str)) {
status = AGENT_STATUS_CHART[x].status; status = AGENT_STATUS_CHART[x].status;
break; break;
@ -305,7 +338,7 @@ const char * cc_agent_state2str(cc_agent_state_t state)
uint8_t x; uint8_t x;
const char *str = "Unknown"; const char *str = "Unknown";
for (x = 0; x < (sizeof(AGENT_STATE_CHART) / sizeof(struct cc_agent_state_table)) - 1; x++) { for (x = 0; x < (sizeof(AGENT_STATE_CHART) / sizeof(struct cc_state_table)) - 1; x++) {
if (AGENT_STATE_CHART[x].state == state) { if (AGENT_STATE_CHART[x].state == state) {
str = AGENT_STATE_CHART[x].name; str = AGENT_STATE_CHART[x].name;
break; break;
@ -320,7 +353,7 @@ cc_agent_state_t cc_agent_str2state(const char *str)
uint8_t x; uint8_t x;
cc_agent_state_t state = CC_AGENT_STATE_UNKNOWN; cc_agent_state_t state = CC_AGENT_STATE_UNKNOWN;
for (x = 0; x < (sizeof(AGENT_STATE_CHART) / sizeof(struct cc_agent_state_table)) - 1 && AGENT_STATE_CHART[x].name; x++) { for (x = 0; x < (sizeof(AGENT_STATE_CHART) / sizeof(struct cc_state_table)) - 1 && AGENT_STATE_CHART[x].name; x++) {
if (!strcasecmp(AGENT_STATE_CHART[x].name, str)) { if (!strcasecmp(AGENT_STATE_CHART[x].name, str)) {
state = AGENT_STATE_CHART[x].state; state = AGENT_STATE_CHART[x].state;
break; break;
@ -334,7 +367,7 @@ const char * cc_member_state2str(cc_member_state_t state)
uint8_t x; uint8_t x;
const char *str = "Unknown"; const char *str = "Unknown";
for (x = 0; x < (sizeof(MEMBER_STATE_CHART) / sizeof(struct cc_member_state_table)) - 1; x++) { for (x = 0; x < (sizeof(MEMBER_STATE_CHART) / sizeof(struct cc_state_table)) - 1; x++) {
if (MEMBER_STATE_CHART[x].state == state) { if (MEMBER_STATE_CHART[x].state == state) {
str = MEMBER_STATE_CHART[x].name; str = MEMBER_STATE_CHART[x].name;
break; break;
@ -349,7 +382,7 @@ cc_member_state_t cc_member_str2state(const char *str)
uint8_t x; uint8_t x;
cc_member_state_t state = CC_MEMBER_STATE_UNKNOWN; cc_member_state_t state = CC_MEMBER_STATE_UNKNOWN;
for (x = 0; x < (sizeof(MEMBER_STATE_CHART) / sizeof(struct cc_member_state_table)) - 1 && MEMBER_STATE_CHART[x].name; x++) { for (x = 0; x < (sizeof(MEMBER_STATE_CHART) / sizeof(struct cc_state_table)) - 1 && MEMBER_STATE_CHART[x].name; x++) {
if (!strcasecmp(MEMBER_STATE_CHART[x].name, str)) { if (!strcasecmp(MEMBER_STATE_CHART[x].name, str)) {
state = MEMBER_STATE_CHART[x].state; state = MEMBER_STATE_CHART[x].state;
break; break;
@ -384,19 +417,27 @@ struct cc_queue {
char *moh; char *moh;
char *record_template; char *record_template;
char *time_base_score; char *time_base_score;
switch_bool_t tier_rules_apply; switch_bool_t tier_rules_apply;
uint32_t tier_rule_wait_second; uint32_t tier_rule_wait_second;
switch_bool_t tier_rule_wait_multiply_level; switch_bool_t tier_rule_wait_multiply_level;
switch_bool_t tier_rule_no_agent_no_wait; switch_bool_t tier_rule_no_agent_no_wait;
uint32_t discard_abandoned_after; uint32_t discard_abandoned_after;
switch_bool_t abandoned_resume_allowed; switch_bool_t abandoned_resume_allowed;
uint32_t max_wait_time;
uint32_t max_wait_time_with_no_agent;
switch_mutex_t *mutex; switch_mutex_t *mutex;
switch_thread_rwlock_t *rwlock; switch_thread_rwlock_t *rwlock;
switch_memory_pool_t *pool; switch_memory_pool_t *pool;
uint32_t flags; uint32_t flags;
switch_time_t last_agent_exist;
switch_time_t last_agent_exist_check;
switch_xml_config_item_t config[CC_QUEUE_CONFIGITEM_COUNT]; switch_xml_config_item_t config[CC_QUEUE_CONFIGITEM_COUNT];
switch_xml_config_string_options_t config_str_pool; switch_xml_config_string_options_t config_str_pool;
@ -488,6 +529,7 @@ cc_queue_t *queue_set_config(cc_queue_t *queue)
SWITCH_CONFIG_SET_ITEM(queue->config[i++], "moh-sound", SWITCH_CONFIG_STRING, 0, &queue->moh, NULL, &queue->config_str_pool, NULL, NULL); SWITCH_CONFIG_SET_ITEM(queue->config[i++], "moh-sound", SWITCH_CONFIG_STRING, 0, &queue->moh, NULL, &queue->config_str_pool, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(queue->config[i++], "record-template", SWITCH_CONFIG_STRING, 0, &queue->record_template, NULL, &queue->config_str_pool, NULL, NULL); SWITCH_CONFIG_SET_ITEM(queue->config[i++], "record-template", SWITCH_CONFIG_STRING, 0, &queue->record_template, NULL, &queue->config_str_pool, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(queue->config[i++], "time-base-score", SWITCH_CONFIG_STRING, 0, &queue->time_base_score, "queue", &queue->config_str_pool, NULL, NULL); SWITCH_CONFIG_SET_ITEM(queue->config[i++], "time-base-score", SWITCH_CONFIG_STRING, 0, &queue->time_base_score, "queue", &queue->config_str_pool, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(queue->config[i++], "tier-rules-apply", SWITCH_CONFIG_BOOL, 0, &queue->tier_rules_apply, SWITCH_FALSE, NULL, NULL, NULL); SWITCH_CONFIG_SET_ITEM(queue->config[i++], "tier-rules-apply", SWITCH_CONFIG_BOOL, 0, &queue->tier_rules_apply, SWITCH_FALSE, NULL, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(queue->config[i++], "tier-rule-wait-second", SWITCH_CONFIG_INT, 0, &queue->tier_rule_wait_second, 0, &config_int_0_86400, NULL, NULL); SWITCH_CONFIG_SET_ITEM(queue->config[i++], "tier-rule-wait-second", SWITCH_CONFIG_INT, 0, &queue->tier_rule_wait_second, 0, &config_int_0_86400, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(queue->config[i++], "tier-rule-wait-multiply-level", SWITCH_CONFIG_BOOL, 0, &queue->tier_rule_wait_multiply_level, SWITCH_FALSE, NULL, NULL, NULL); SWITCH_CONFIG_SET_ITEM(queue->config[i++], "tier-rule-wait-multiply-level", SWITCH_CONFIG_BOOL, 0, &queue->tier_rule_wait_multiply_level, SWITCH_FALSE, NULL, NULL, NULL);
@ -495,6 +537,9 @@ cc_queue_t *queue_set_config(cc_queue_t *queue)
SWITCH_CONFIG_SET_ITEM(queue->config[i++], "discard-abandoned-after", SWITCH_CONFIG_INT, 0, &queue->discard_abandoned_after, 60, &config_int_0_86400, NULL, NULL); SWITCH_CONFIG_SET_ITEM(queue->config[i++], "discard-abandoned-after", SWITCH_CONFIG_INT, 0, &queue->discard_abandoned_after, 60, &config_int_0_86400, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(queue->config[i++], "abandoned-resume-allowed", SWITCH_CONFIG_BOOL, 0, &queue->abandoned_resume_allowed, SWITCH_FALSE, NULL, NULL, NULL); SWITCH_CONFIG_SET_ITEM(queue->config[i++], "abandoned-resume-allowed", SWITCH_CONFIG_BOOL, 0, &queue->abandoned_resume_allowed, SWITCH_FALSE, NULL, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(queue->config[i++], "max-wait-time", SWITCH_CONFIG_INT, 0, &queue->max_wait_time, 0, &config_int_0_86400, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(queue->config[i++], "max-wait-time-with-no-agent", SWITCH_CONFIG_INT, 0, &queue->max_wait_time_with_no_agent, 0, &config_int_0_86400, NULL, NULL);
switch_assert(i < CC_QUEUE_CONFIGITEM_COUNT); switch_assert(i < CC_QUEUE_CONFIGITEM_COUNT);
return queue; return queue;
@ -646,6 +691,9 @@ static cc_queue_t *load_queue(const char *queue_name)
switch_thread_rwlock_create(&queue->rwlock, pool); switch_thread_rwlock_create(&queue->rwlock, pool);
queue->name = switch_core_strdup(pool, queue_name); queue->name = switch_core_strdup(pool, queue_name);
queue->last_agent_exist = 0;
queue->last_agent_exist_check = 0;
if (!(dbh = cc_get_db_handle())) { if (!(dbh = cc_get_db_handle())) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot open DB!\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot open DB!\n");
goto end; goto end;
@ -702,7 +750,7 @@ static cc_queue_t *get_queue(const char *queue_name)
struct call_helper { struct call_helper {
const char *member_uuid; const char *member_uuid;
const char *queue; const char *queue_name;
const char *queue_strategy; const char *queue_strategy;
const char *member_joined_epoch; const char *member_joined_epoch;
const char *member_caller_name; const char *member_caller_name;
@ -744,7 +792,7 @@ int cc_queue_count(const char *queue)
count = atoi(res); count = atoi(res);
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) { if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", queue); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", queue);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "members-count"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "members-count");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Count", res); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Count", res);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Selection", event_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Selection", event_name);
@ -827,7 +875,7 @@ cc_agent_status_t cc_agent_get(const char *key, const char *agent, char *ret_res
result = CC_STATUS_SUCCESS; result = CC_STATUS_SUCCESS;
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) { if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", agent); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", agent);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "agent-status-get"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "agent-status-get");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-Status", res); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-Status", res);
switch_event_fire(&event); switch_event_fire(&event);
@ -894,7 +942,7 @@ cc_status_t cc_agent_update(const char *key, const char *value, const char *agen
result = CC_STATUS_SUCCESS; result = CC_STATUS_SUCCESS;
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) { if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", agent); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", agent);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "agent-status-change"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "agent-status-change");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-Status", value); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-Status", value);
switch_event_fire(&event); switch_event_fire(&event);
@ -918,7 +966,7 @@ cc_status_t cc_agent_update(const char *key, const char *value, const char *agen
result = CC_STATUS_SUCCESS; result = CC_STATUS_SUCCESS;
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) { if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", agent); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", agent);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "agent-state-change"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "agent-state-change");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-State", value); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-State", value);
switch_event_fire(&event); switch_event_fire(&event);
@ -1118,13 +1166,13 @@ done:
return result; return result;
} }
cc_status_t cc_tier_del(const char *queue, const char *agent) cc_status_t cc_tier_del(const char *queue_name, const char *agent)
{ {
cc_status_t result = CC_STATUS_SUCCESS; cc_status_t result = CC_STATUS_SUCCESS;
char *sql; char *sql;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Deleted tier Agent %s in Queue %s\n", agent, queue); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Deleted tier Agent %s in Queue %s\n", agent, queue_name);
sql = switch_mprintf("DELETE FROM tiers WHERE queue = '%q' AND agent = '%q';", queue, agent); sql = switch_mprintf("DELETE FROM tiers WHERE queue = '%q' AND agent = '%q';", queue_name, agent);
cc_execute_sql(NULL, sql, NULL); cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql); switch_safe_free(sql);
@ -1307,8 +1355,11 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
} }
if (!strcasecmp(h->agent_type, CC_AGENT_TYPE_CALLBACK)) { if (!strcasecmp(h->agent_type, CC_AGENT_TYPE_CALLBACK)) {
switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS); switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_queue", "%s", h->queue_name);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_member_uuid", "%s", h->member_uuid); switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_member_uuid", "%s", h->member_uuid);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_member_pre_answer_uuid", "%s", h->member_uuid); switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_member_pre_answer_uuid", "%s", h->member_uuid);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_agent", "%s", h->agent_name);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_agent_type", "%s", h->agent_type);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "ignore_early_media", "true"); switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "ignore_early_media", "true");
t_agent_called = switch_epoch_time_now(NULL); t_agent_called = switch_epoch_time_now(NULL);
@ -1323,6 +1374,12 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_channel_t *agent_channel = switch_core_session_get_channel(agent_session); switch_channel_t *agent_channel = switch_core_session_get_channel(agent_session);
switch_event_t *event; switch_event_t *event;
const char *cc_warning_tone = switch_channel_get_variable(agent_channel, "cc_warning_tone"); const char *cc_warning_tone = switch_channel_get_variable(agent_channel, "cc_warning_tone");
switch_channel_set_variable(agent_channel, "cc_queue", h->queue_name);
switch_channel_set_variable(agent_channel, "cc_agent", h->agent_name);
switch_channel_set_variable(agent_channel, "cc_agent_type", h->agent_type);
switch_channel_set_variable(agent_channel, "cc_member_uuid", h->member_uuid);
/* Playback this to the agent */ /* Playback this to the agent */
if (cc_warning_tone && switch_event_create(&event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { if (cc_warning_tone && switch_event_create(&event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute");
@ -1375,7 +1432,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) { if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(agent_channel, event); switch_channel_event_set_data(agent_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", h->queue); 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", "bridge-agent-start"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "bridge-agent-start");
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", h->agent_name);
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-Agent-System", h->agent_system);
@ -1398,11 +1455,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_safe_free(sql); switch_safe_free(sql);
/* Change the agents Status in the tiers */ /* Change the agents Status in the tiers */
sql = switch_mprintf("UPDATE tiers SET state = '%q' WHERE agent = '%q' AND queue = '%q'", cc_tier_update("state", cc_tier_state2str(CC_TIER_STATE_ACTIVE_INBOUND), h->queue_name, h->agent_name);
cc_tier_state2str(CC_TIER_STATE_ACTIVE_INBOUND), h->agent_name, h->queue);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
cc_agent_update("state", cc_agent_state2str(CC_AGENT_STATE_IN_A_QUEUE_CALL), h->agent_name); cc_agent_update("state", cc_agent_state2str(CC_AGENT_STATE_IN_A_QUEUE_CALL), h->agent_name);
/* Record session if record-template is provided */ /* Record session if record-template is provided */
@ -1415,9 +1468,12 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
} }
} }
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Agent %s answered \"%s\" (%s) from queue %s%s\n", switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Agent %s answered \"%s\" <%s> from queue %s%s\n",
h->agent_name, h->member_caller_name, h->member_caller_number, h->queue, (h->record_template?" (Recorded)":"")); h->agent_name, h->member_caller_name, h->member_caller_number, h->queue_name, (h->record_template?" (Recorded)":""));
switch_ivr_uuid_bridge(switch_core_session_get_uuid(agent_session), h->member_uuid); switch_ivr_uuid_bridge(h->member_uuid, switch_core_session_get_uuid(agent_session));
/* This is used for the waiting caller to quit waiting for a agent */
switch_channel_set_variable(member_channel, "cc_agent_uuid", agent_uuid);
/* Wait until the member hangup or the agent hangup. This will quit also if the agent transfer the call */ /* Wait until the member hangup or the agent hangup. This will quit also if the agent transfer the call */
while(switch_channel_up(member_channel) && switch_channel_up(agent_channel) && globals.running) { while(switch_channel_up(member_channel) && switch_channel_up(agent_channel) && globals.running) {
@ -1427,7 +1483,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) { if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(agent_channel, event); switch_channel_event_set_data(agent_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", h->queue); 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", "bridge-agent-end"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "bridge-agent-end");
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", h->agent_name);
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-Agent-System", h->agent_system);
@ -1443,7 +1499,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
/* Update Agents Items */ /* Update Agents Items */
/* Do not remove uuid of the agent if we are a standby agent */ /* Do not remove uuid of the agent if we are a standby agent */
sql = switch_mprintf("UPDATE agents SET %q last_bridge_end = %ld, talk_time = talk_time + (%ld-last_bridge_start) WHERE name = '%q' AND system = '%q';" sql = switch_mprintf("UPDATE agents SET %q last_bridge_end = %ld, talk_time = talk_time + (%ld-last_bridge_start) WHERE name = '%q' AND system = '%q';"
, (strcasecmp(h->agent_type, "uuid-standby")?"uuid = '',":""), (long) switch_epoch_time_now(NULL), (long) switch_epoch_time_now(NULL), h->agent_name, h->agent_system); , (strcasecmp(h->agent_type, CC_AGENT_TYPE_UUID_STANDBY)?"uuid = '',":""), (long) switch_epoch_time_now(NULL), (long) switch_epoch_time_now(NULL), h->agent_name, h->agent_system);
cc_execute_sql(NULL, sql, NULL); cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql); switch_safe_free(sql);
@ -1455,7 +1511,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
/* Caller off event */ /* Caller off event */
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) { if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(member_channel, event); switch_channel_event_set_data(member_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", h->queue); 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", "member-queue-end"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "member-queue-end");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cause", "Terminated"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cause", "Terminated");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answer-Time", "%ld", (long) (t_agent_answered - t_agent_called)); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answer-Time", "%ld", (long) (t_agent_answered - t_agent_called));
@ -1463,8 +1519,10 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Talk-Time", "%ld", (long) (switch_epoch_time_now(NULL) - t_agent_answered)); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Talk-Time", "%ld", (long) (switch_epoch_time_now(NULL) - t_agent_answered));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Total-Time", "%ld", (long) (switch_epoch_time_now(NULL) - t_member_called)); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Total-Time", "%ld", (long) (switch_epoch_time_now(NULL) - t_member_called));
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-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name"))); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name",
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number"))); switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number",
switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
switch_event_fire(&event); switch_event_fire(&event);
} }
@ -1529,8 +1587,8 @@ done:
sql = switch_mprintf( sql = switch_mprintf(
"UPDATE tiers SET state = '%q' WHERE agent = '%q' AND queue = '%q' AND (state = '%q' OR state = '%q' OR state = '%q');" "UPDATE tiers SET state = '%q' WHERE agent = '%q' AND queue = '%q' AND (state = '%q' OR state = '%q' OR state = '%q');"
"UPDATE tiers SET state = '%q' WHERE agent = '%q' AND NOT queue = '%q' AND state = '%q'" "UPDATE tiers SET state = '%q' WHERE agent = '%q' AND NOT queue = '%q' AND state = '%q'"
, cc_tier_state2str(tiers_state), h->agent_name, h->queue, cc_tier_state2str(CC_TIER_STATE_ACTIVE_INBOUND), cc_tier_state2str(CC_TIER_STATE_STANDBY), cc_tier_state2str(CC_TIER_STATE_OFFERING), , cc_tier_state2str(tiers_state), h->agent_name, h->queue_name, cc_tier_state2str(CC_TIER_STATE_ACTIVE_INBOUND), cc_tier_state2str(CC_TIER_STATE_STANDBY), cc_tier_state2str(CC_TIER_STATE_OFFERING),
cc_tier_state2str(CC_TIER_STATE_READY), h->agent_name, h->queue, cc_tier_state2str(CC_TIER_STATE_STANDBY)); cc_tier_state2str(CC_TIER_STATE_READY), h->agent_name, h->queue_name, cc_tier_state2str(CC_TIER_STATE_STANDBY));
cc_execute_sql(NULL, sql, NULL); cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql); switch_safe_free(sql);
@ -1558,7 +1616,7 @@ done:
} }
struct agent_callback { struct agent_callback {
const char *queue; const char *queue_name;
const char *system; const char *system;
const char *uuid; const char *uuid;
const char *caller_number; const char *caller_number;
@ -1570,6 +1628,7 @@ struct agent_callback {
uint32_t tier_rule_wait_second; uint32_t tier_rule_wait_second;
switch_bool_t tier_rule_wait_multiply_level; switch_bool_t tier_rule_wait_multiply_level;
switch_bool_t tier_rule_no_agent_no_wait; switch_bool_t tier_rule_no_agent_no_wait;
switch_bool_t agent_found;
int tier; int tier;
int tier_agent_available; int tier_agent_available;
@ -1593,6 +1652,8 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
switch_bool_t contact_agent = SWITCH_TRUE; switch_bool_t contact_agent = SWITCH_TRUE;
cbt->agent_found = SWITCH_TRUE;
/* Check if we switch to a different tier, if so, check if we should continue further for that member */ /* Check if we switch to a different tier, if so, check if we should continue further for that member */
if (cbt->tier_rules_apply == SWITCH_TRUE && atoi(agent_tier_level) > cbt->tier) { if (cbt->tier_rules_apply == SWITCH_TRUE && atoi(agent_tier_level) > cbt->tier) {
@ -1691,7 +1752,7 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
h->member_joined_epoch = switch_core_strdup(h->pool, cbt->joined_epoch); h->member_joined_epoch = switch_core_strdup(h->pool, cbt->joined_epoch);
h->member_caller_name = switch_core_strdup(h->pool, cbt->caller_name); h->member_caller_name = switch_core_strdup(h->pool, cbt->caller_name);
h->member_caller_number = switch_core_strdup(h->pool, cbt->caller_number); h->member_caller_number = switch_core_strdup(h->pool, cbt->caller_number);
h->queue = switch_core_strdup(h->pool, cbt->queue); h->queue_name = switch_core_strdup(h->pool, cbt->queue_name);
h->record_template = switch_core_strdup(h->pool, cbt->record_template); h->record_template = switch_core_strdup(h->pool, cbt->record_template);
h->no_answer_count = atoi(argv[4]); h->no_answer_count = atoi(argv[4]);
h->max_no_answer = atoi(argv[5]); h->max_no_answer = atoi(argv[5]);
@ -1704,8 +1765,8 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
sql = switch_mprintf( sql = switch_mprintf(
"UPDATE tiers SET state = '%q' WHERE agent = '%q' AND queue = '%q';" "UPDATE tiers SET state = '%q' WHERE agent = '%q' AND queue = '%q';"
"UPDATE tiers SET state = '%q' WHERE agent = '%q' AND NOT queue = '%q' AND state = '%q';", "UPDATE tiers SET state = '%q' WHERE agent = '%q' AND NOT queue = '%q' AND state = '%q';",
cc_tier_state2str(CC_TIER_STATE_OFFERING), h->agent_name, h->queue, cc_tier_state2str(CC_TIER_STATE_OFFERING), h->agent_name, h->queue_name,
cc_tier_state2str(CC_TIER_STATE_STANDBY), h->agent_name, h->queue, cc_tier_state2str(CC_TIER_STATE_READY)); cc_tier_state2str(CC_TIER_STATE_STANDBY), h->agent_name, h->queue_name, cc_tier_state2str(CC_TIER_STATE_READY));
cc_execute_sql(NULL, sql, NULL); cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql); switch_safe_free(sql);
@ -1772,7 +1833,7 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
switch_safe_free(sql); switch_safe_free(sql);
} }
/* Skip this member */ /* Skip this member */
return 0; goto end;
} }
memset(&cbt, 0, sizeof(cbt)); memset(&cbt, 0, sizeof(cbt));
cbt.tier = 0; cbt.tier = 0;
@ -1787,9 +1848,10 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
cbt.caller_number = argv[2]; cbt.caller_number = argv[2];
cbt.caller_name = argv[3]; cbt.caller_name = argv[3];
cbt.joined_epoch = argv[4]; cbt.joined_epoch = argv[4];
cbt.queue = argv[0]; cbt.queue_name = argv[0];
cbt.strategy = queue_strategy; cbt.strategy = queue_strategy;
cbt.record_template = queue_record_template; cbt.record_template = queue_record_template;
cbt.agent_found = SWITCH_FALSE;
if (!strcasecmp(queue->strategy, "longest-idle-agent")) { if (!strcasecmp(queue->strategy, "longest-idle-agent")) {
sql_order_by = switch_mprintf("level, agents.last_offered_call, position"); sql_order_by = switch_mprintf("level, agents.last_offered_call, position");
@ -1823,6 +1885,18 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
switch_safe_free(sql); switch_safe_free(sql);
switch_safe_free(sql_order_by); switch_safe_free(sql_order_by);
/* We update a field in the queue struct so we can kick caller out if waiting for too long with no agent */
if (!argv[0] || !(queue = get_queue(argv[0]))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Queue %s not found locally, skip this member\n", argv[0]);
goto end;
} else {
queue->last_agent_exist_check = switch_epoch_time_now(NULL);
if (cbt.agent_found) {
queue->last_agent_exist = queue->last_agent_exist_check;
}
queue_rwunlock(queue);
}
end: end:
switch_safe_free(queue_name); switch_safe_free(queue_name);
switch_safe_free(queue_strategy); switch_safe_free(queue_strategy);
@ -1902,30 +1976,53 @@ void cc_agent_dispatch_thread_start(void)
switch_thread_create(&thread, thd_attr, cc_agent_dispatch_thread_run, NULL, globals.pool); switch_thread_create(&thread, thd_attr, cc_agent_dispatch_thread_run, NULL, globals.pool);
} }
struct member_helper { struct member_thread_helper {
const char *uuid; const char *member_uuid;
const char *queue_name;
switch_time_t t_member_called;
cc_member_cancel_reason_t member_cancel_reason;
int running; int running;
switch_memory_pool_t *pool; switch_memory_pool_t *pool;
}; };
void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj) void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj)
{ {
struct member_helper *m = (struct member_helper *) obj; struct member_thread_helper *m = (struct member_thread_helper *) obj;
switch_core_session_t *member_session = switch_core_session_locate(m->uuid); switch_core_session_t *member_session = switch_core_session_locate(m->member_uuid);
switch_channel_t *channel = NULL; switch_channel_t *member_channel = NULL;
switch_mutex_lock(globals.mutex); switch_mutex_lock(globals.mutex);
globals.threads++; globals.threads++;
switch_mutex_unlock(globals.mutex); switch_mutex_unlock(globals.mutex);
if (member_session) { if (member_session) {
channel = switch_core_session_get_channel(member_session); member_channel = switch_core_session_get_channel(member_session);
} else { } else {
switch_core_destroy_memory_pool(&m->pool); switch_core_destroy_memory_pool(&m->pool);
return NULL; return NULL;
} }
while(switch_channel_ready(channel) && m->running && globals.running) { while(switch_channel_ready(member_channel) && m->running && globals.running) {
cc_queue_t *queue = NULL;
if (!m->queue_name || !(queue = get_queue(m->queue_name))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Queue %s not found\n", m->queue_name);
break;
}
/* Make the Caller Leave if he went over his max wait time */
if (queue->max_wait_time > 0 && queue->max_wait_time <= switch_epoch_time_now(NULL) - m->t_member_called) {
m->member_cancel_reason = CC_MEMBER_CANCEL_REASON_TIMEOUT;
switch_channel_set_flag_value(member_channel, CF_BREAK, 2);
}
/* Will drop the caller if no agent was found for more than X secondes */
if (queue->max_wait_time_with_no_agent > 0 && m->t_member_called < queue->last_agent_exist_check - CC_MAX_TIME_DIFF_CHECK &&
queue->last_agent_exist_check - queue->last_agent_exist >= queue->max_wait_time_with_no_agent) {
m->member_cancel_reason = CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT;
switch_channel_set_flag_value(member_channel, CF_BREAK, 2);
}
/* TODO Go thought the list of phrases */ /* TODO Go thought the list of phrases */
/* SAMPLE CODE to playback something over the MOH /* SAMPLE CODE to playback something over the MOH
@ -1940,8 +2037,12 @@ void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj
/* If Agent Logoff, we might need to recalculare score based on skill */ /* If Agent Logoff, we might need to recalculare score based on skill */
/* Play Announcement in order */ /* Play Announcement in order */
switch_yield(100000);
queue_rwunlock(queue);
switch_yield(500000);
} }
switch_core_session_rwunlock(member_session); switch_core_session_rwunlock(member_session);
switch_core_destroy_memory_pool(&m->pool); switch_core_destroy_memory_pool(&m->pool);
@ -1962,26 +2063,27 @@ SWITCH_STANDARD_APP(callcenter_function)
char *mydata = NULL; char *mydata = NULL;
cc_queue_t *queue = NULL; cc_queue_t *queue = NULL;
const char *queue_name = NULL; const char *queue_name = NULL;
switch_channel_t *member_channel = switch_core_session_get_channel(session); switch_core_session_t *member_session = session;
switch_channel_t *member_channel = switch_core_session_get_channel(member_session);
char *sql = NULL; char *sql = NULL;
char *uuid = switch_core_session_get_uuid(session); char *member_uuid = switch_core_session_get_uuid(member_session);
switch_input_args_t args = { 0 }; struct member_thread_helper *h = NULL;
struct member_helper *h = NULL;
switch_thread_t *thread; switch_thread_t *thread;
switch_threadattr_t *thd_attr = NULL; switch_threadattr_t *thd_attr = NULL;
switch_memory_pool_t *pool; switch_memory_pool_t *pool;
int cc_base_score_int = 0;
switch_channel_timetable_t *times = NULL; switch_channel_timetable_t *times = NULL;
const char *cc_base_score = switch_channel_get_variable(member_channel, "cc_base_score");
const char *cc_moh_override = switch_channel_get_variable(member_channel, "cc_moh_override"); const char *cc_moh_override = switch_channel_get_variable(member_channel, "cc_moh_override");
const char *cc_base_score = switch_channel_get_variable(member_channel, "cc_base_score");
int cc_base_score_int = 0;
const char *cur_moh = NULL; const char *cur_moh = NULL;
char start_epoch[64]; char start_epoch[64];
switch_event_t *event; switch_event_t *event;
switch_time_t t_member_called = switch_epoch_time_now(NULL); switch_time_t t_member_called = switch_epoch_time_now(NULL);
long abandoned_epoch = 0; long abandoned_epoch = 0;
const char *agent_uuid = NULL;
if (!zstr(data)) { if (!zstr(data)) {
mydata = switch_core_session_strdup(session, data); mydata = switch_core_session_strdup(member_session, data);
argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
} else { } else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No Queue name provided\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No Queue name provided\n");
@ -2004,7 +2106,7 @@ SWITCH_STANDARD_APP(callcenter_function)
times = switch_channel_get_timetable(member_channel); times = switch_channel_get_timetable(member_channel);
switch_snprintf(start_epoch, sizeof(start_epoch), "%" SWITCH_TIME_T_FMT, times->answered / 1000000); switch_snprintf(start_epoch, sizeof(start_epoch), "%" SWITCH_TIME_T_FMT, times->answered / 1000000);
/* Check of we have a queued abandoned member we can resume from */ /* Check if we support and have a queued abandoned member we can resume from */
if (queue->abandoned_resume_allowed == SWITCH_TRUE) { if (queue->abandoned_resume_allowed == SWITCH_TRUE) {
char res[256]; char res[256];
@ -2028,9 +2130,9 @@ SWITCH_STANDARD_APP(callcenter_function)
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) { if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(member_channel, event); switch_channel_event_set_data(member_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", queue_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", queue_name);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Action", "member-queue-%s", (abandoned_epoch==0?"start":"resume")); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Action", "member-queue-%s", (abandoned_epoch==0?"start":"resume"));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", uuid); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name"))); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number"))); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
switch_event_fire(&event); switch_event_fire(&event);
@ -2045,7 +2147,7 @@ SWITCH_STANDARD_APP(callcenter_function)
" (queue,system,uuid,system_epoch,joined_epoch,base_score,skill_score,caller_number,caller_name,serving_agent,serving_system,state)" " (queue,system,uuid,system_epoch,joined_epoch,base_score,skill_score,caller_number,caller_name,serving_agent,serving_system,state)"
" VALUES('%q','single_box','%q','%q','%ld','%d','%d','%q','%q','%q','','%q')", " VALUES('%q','single_box','%q','%q','%ld','%d','%d','%q','%q','%q','','%q')",
queue_name, queue_name,
uuid, member_uuid,
start_epoch, start_epoch,
(long) switch_epoch_time_now(NULL), (long) switch_epoch_time_now(NULL),
cc_base_score_int, cc_base_score_int,
@ -2060,12 +2162,12 @@ SWITCH_STANDARD_APP(callcenter_function)
char res[256]; char res[256];
/* Update abandoned member */ /* Update abandoned member */
sql = switch_mprintf("UPDATE members SET uuid = '%q', state = '%q', rejoined_epoch = '%ld' WHERE caller_number = '%q' AND abandoned_epoch = '%ld' AND state = '%q' AND queue = '%q'", sql = switch_mprintf("UPDATE members SET uuid = '%q', state = '%q', rejoined_epoch = '%ld' WHERE caller_number = '%q' AND abandoned_epoch = '%ld' AND state = '%q' AND queue = '%q'",
uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), (long) switch_epoch_time_now(NULL), switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")), abandoned_epoch, cc_member_state2str(CC_MEMBER_STATE_ABANDONED), queue_name); member_uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), (long) switch_epoch_time_now(NULL), switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")), abandoned_epoch, cc_member_state2str(CC_MEMBER_STATE_ABANDONED), queue_name);
cc_execute_sql(queue, sql, NULL); cc_execute_sql(queue, sql, NULL);
switch_safe_free(sql); switch_safe_free(sql);
/* Confirm we took that member in */ /* Confirm we took that member in */
sql = switch_mprintf("SELECT abandoned_epoch FROM members WHERE uuid = '%q' AND state = '%q' AND queue = '%q'", uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), queue_name); sql = switch_mprintf("SELECT abandoned_epoch FROM members WHERE uuid = '%q' AND state = '%q' AND queue = '%q'", member_uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), queue_name);
cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res)); cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
switch_safe_free(sql); switch_safe_free(sql);
@ -2083,9 +2185,14 @@ SWITCH_STANDARD_APP(callcenter_function)
/* Start Thread that will playback different prompt to the channel */ /* Start Thread that will playback different prompt to the channel */
switch_core_new_memory_pool(&pool); switch_core_new_memory_pool(&pool);
h = switch_core_alloc(pool, sizeof(*h)); h = switch_core_alloc(pool, sizeof(*h));
h->pool = pool; h->pool = pool;
h->uuid = switch_core_strdup(h->pool, uuid); h->member_uuid = switch_core_strdup(h->pool, member_uuid);
h->queue_name = switch_core_strdup(h->pool, queue_name);
h->t_member_called = t_member_called;
h->member_cancel_reason = CC_MEMBER_CANCEL_REASON_NONE;
h->running = 1; h->running = 1;
switch_threadattr_create(&thd_attr, h->pool); switch_threadattr_create(&thd_attr, h->pool);
switch_threadattr_detach_set(thd_attr, 1); switch_threadattr_detach_set(thd_attr, 1);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
@ -2095,18 +2202,39 @@ SWITCH_STANDARD_APP(callcenter_function)
/* TODO Add DTMF callback support */ /* TODO Add DTMF callback support */
/* TODO add MOH infitite loop */ /* TODO add MOH infitite loop */
if (cc_moh_override) { if (cc_moh_override) {
cur_moh = switch_core_session_strdup(session, cc_moh_override); cur_moh = switch_core_session_strdup(member_session, cc_moh_override);
} else { } else {
cur_moh = switch_core_session_strdup(session, queue->moh); cur_moh = switch_core_session_strdup(member_session, queue->moh);
} }
queue_rwunlock(queue); queue_rwunlock(queue);
while (switch_channel_ready(member_channel)) {
switch_input_args_t args = { 0 };
/* An agent was found, time to exit and let the bridge do it job */
if ((agent_uuid = switch_channel_get_variable(member_channel, "cc_agent_uuid"))) {
break;
}
/* If the member thread set a different reason, we monitor it so we can quit the wait */
if (h->member_cancel_reason != CC_MEMBER_CANCEL_REASON_NONE) {
break;
}
switch_core_session_flush_private_events(member_session);
if (cur_moh) { if (cur_moh) {
switch_ivr_play_file(session, NULL, cur_moh, &args); switch_status_t status = switch_ivr_play_file(member_session, NULL, cur_moh, &args);
if (!SWITCH_READ_ACCEPTABLE(status)) {
break;
}
} else { } else {
switch_ivr_collect_digits_callback(session, &args, 0, 0); switch_ivr_collect_digits_callback(session, &args, 0, 0);
} }
}
/* Stop Member Thread */ /* Stop Member Thread */
if (h) { if (h) {
h->running = 0; h->running = 0;
@ -2114,33 +2242,42 @@ SWITCH_STANDARD_APP(callcenter_function)
/* Hangup any agents been callback */ /* Hangup any agents been callback */
if (!switch_channel_up(member_channel)) { /* If channel is still up, it mean that the member didn't hangup, so we should leave the agent alone */ if (!switch_channel_up(member_channel)) { /* If channel is still up, it mean that the member didn't hangup, so we should leave the agent alone */
switch_core_session_hupall_matching_var("cc_member_uuid", uuid, SWITCH_CAUSE_ORIGINATOR_CANCEL); switch_core_session_hupall_matching_var("cc_member_uuid", member_uuid, SWITCH_CAUSE_ORIGINATOR_CANCEL);
sql = switch_mprintf("UPDATE members SET state = '%q', uuid = '', abandoned_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q'", sql = switch_mprintf("UPDATE members SET state = '%q', uuid = '', abandoned_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q'",
cc_member_state2str(CC_MEMBER_STATE_ABANDONED), (long) switch_epoch_time_now(NULL), uuid); cc_member_state2str(CC_MEMBER_STATE_ABANDONED), (long) switch_epoch_time_now(NULL), member_uuid);
cc_execute_sql(NULL, sql, NULL); cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql); switch_safe_free(sql);
/* Generate an Event and update some channel variable */
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) { if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(member_channel, event); switch_channel_event_set_data(member_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", queue_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", queue_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "member-queue-end"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "member-queue-end");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Wait-Time", "%ld", (long) (switch_epoch_time_now(NULL) - t_member_called)); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Wait-Time", "%ld", (long) (switch_epoch_time_now(NULL) - t_member_called));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cause", "Abort"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Member \"%s\" <%s> exit queue %s due to %s\n",
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", uuid); switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")),
switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")),
queue_name, cc_member_cancel_reason2str(h->member_cancel_reason));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cause", cc_member_cancel_reason2str(h->member_cancel_reason));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name"))); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number"))); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
switch_event_fire(&event); switch_event_fire(&event);
} }
/* for xml_cdr needs */ /* for xml_cdr needs */
switch_channel_set_variable_printf(member_channel, "cc_queue_canceled_epoch", "%ld", (long) switch_epoch_time_now(NULL)); switch_channel_set_variable_printf(member_channel, "cc_queue_canceled_epoch", "%ld", (long) switch_epoch_time_now(NULL));
switch_channel_set_variable_printf(member_channel, "cc_cause", "%s", cc_member_cancel_reason2str(h->member_cancel_reason));
/* Send Event with queue count */ /* Send Event with queue count */
cc_queue_count(queue_name); cc_queue_count(queue_name);
} else { } else {
switch_channel_set_variable_printf(member_channel, "cc_cause", "%s", "answered");
sql = switch_mprintf("UPDATE members SET state = '%q', bridge_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q'", sql = switch_mprintf("UPDATE members SET state = '%q', bridge_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q'",
cc_member_state2str(CC_MEMBER_STATE_ANSWERED), (long) switch_epoch_time_now(NULL), uuid); cc_member_state2str(CC_MEMBER_STATE_ANSWERED), (long) switch_epoch_time_now(NULL), member_uuid);
cc_execute_sql(NULL, sql, NULL); cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql); switch_safe_free(sql);
@ -2516,7 +2653,7 @@ SWITCH_STANDARD_API(cc_config_api_function)
stream->write_function(stream, "%d\n", atoi(res)); stream->write_function(stream, "%d\n", atoi(res));
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) { if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", queue_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", queue_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "members-count"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "members-count");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Count", res); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Count", res);
switch_event_fire(&event); switch_event_fire(&event);

View File

@ -1002,7 +1002,7 @@ static int do_candidates(struct private_object *tech_pvt, int force)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Send Candidate %s:%d [%s]\n", cand[0].address, cand[0].port, switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Send Candidate %s:%d [%s]\n", cand[0].address, cand[0].port,
cand[0].username); cand[0].username);
if (ldl_session_gateway(tech_pvt->dlsession)) { if (ldl_session_gateway(tech_pvt->dlsession) && switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
tech_pvt->cand_id = ldl_session_transport(tech_pvt->dlsession, cand, 1); tech_pvt->cand_id = ldl_session_transport(tech_pvt->dlsession, cand, 1);
} else { } else {
tech_pvt->cand_id = ldl_session_candidates(tech_pvt->dlsession, cand, 1); tech_pvt->cand_id = ldl_session_candidates(tech_pvt->dlsession, cand, 1);
@ -1247,7 +1247,8 @@ static switch_status_t channel_on_destroy(switch_core_session_t *session)
tech_pvt->rtp_session = NULL; tech_pvt->rtp_session = NULL;
} }
if (globals.auto_nat && tech_pvt->profile->local_network && !switch_check_network_list_ip(tech_pvt->remote_ip, tech_pvt->profile->local_network)) { if (globals.auto_nat && tech_pvt->profile->local_network && tech_pvt->remote_ip && tech_pvt->profile->local_network &&
!switch_check_network_list_ip(tech_pvt->remote_ip, tech_pvt->profile->local_network)) {
switch_nat_del_mapping((switch_port_t) tech_pvt->local_port, SWITCH_NAT_UDP); switch_nat_del_mapping((switch_port_t) tech_pvt->local_port, SWITCH_NAT_UDP);
} }
@ -1259,6 +1260,10 @@ static switch_status_t channel_on_destroy(switch_core_session_t *session)
switch_core_codec_destroy(&tech_pvt->write_codec); switch_core_codec_destroy(&tech_pvt->write_codec);
} }
if (tech_pvt->dlsession) {
ldl_session_destroy(&tech_pvt->dlsession);
}
switch_thread_rwlock_unlock(tech_pvt->profile->rwlock); switch_thread_rwlock_unlock(tech_pvt->profile->rwlock);
if (tech_pvt->profile->purge) { if (tech_pvt->profile->purge) {
@ -1296,13 +1301,12 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session)
if ((tech_pvt->profile->user_flags & LDL_FLAG_COMPONENT) && is_special(tech_pvt->them)) { if ((tech_pvt->profile->user_flags & LDL_FLAG_COMPONENT) && is_special(tech_pvt->them)) {
ldl_handle_send_presence(tech_pvt->profile->handle, tech_pvt->them, tech_pvt->us, NULL, NULL, "Click To Call", tech_pvt->profile->avatar); ldl_handle_send_presence(tech_pvt->profile->handle, tech_pvt->them, tech_pvt->us, NULL, NULL, "Click To Call", tech_pvt->profile->avatar);
} }
if (tech_pvt->dlsession) {
if (!switch_test_flag(tech_pvt, TFLAG_TERM)) { if (!switch_test_flag(tech_pvt, TFLAG_TERM) && tech_pvt->dlsession) {
ldl_session_terminate(tech_pvt->dlsession); ldl_session_terminate(tech_pvt->dlsession);
switch_set_flag_locked(tech_pvt, TFLAG_TERM); switch_set_flag_locked(tech_pvt, TFLAG_TERM);
} }
ldl_session_destroy(&tech_pvt->dlsession);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP\n", switch_channel_get_name(channel)); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP\n", switch_channel_get_name(channel));
@ -1324,15 +1328,6 @@ static switch_status_t channel_kill_channel(switch_core_session_t *session, int
switch_clear_flag_locked(tech_pvt, TFLAG_VOICE); switch_clear_flag_locked(tech_pvt, TFLAG_VOICE);
switch_set_flag_locked(tech_pvt, TFLAG_BYE); switch_set_flag_locked(tech_pvt, TFLAG_BYE);
if (tech_pvt->dlsession) {
if (!switch_test_flag(tech_pvt, TFLAG_TERM)) {
ldl_session_terminate(tech_pvt->dlsession);
switch_set_flag_locked(tech_pvt, TFLAG_TERM);
}
ldl_session_destroy(&tech_pvt->dlsession);
}
if (switch_rtp_ready(tech_pvt->rtp_session)) { if (switch_rtp_ready(tech_pvt->rtp_session)) {
switch_rtp_kill_socket(tech_pvt->rtp_session); switch_rtp_kill_socket(tech_pvt->rtp_session);
} }
@ -2980,6 +2975,8 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
tech_pvt->flags |= profile->flags; tech_pvt->flags |= profile->flags;
channel = switch_core_session_get_channel(session); channel = switch_core_session_get_channel(session);
switch_core_session_set_private(session, tech_pvt); switch_core_session_set_private(session, tech_pvt);
tech_pvt->dlsession = dlsession;
tech_pvt->session = session; tech_pvt->session = session;
tech_pvt->codec_index = -1; tech_pvt->codec_index = -1;
tech_pvt->profile = profile; tech_pvt->profile = profile;
@ -3025,6 +3022,24 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
cid_num = tech_pvt->recip; cid_num = tech_pvt->recip;
} }
if (switch_stristr("voice.google.com", from)) {
char *id = switch_core_session_strdup(session, from);
char *p;
if ((p = strchr(id, '@'))) {
*p++ = '\0';
cid_name = "Google Voice";
cid_num = id;
}
ldl_session_set_gateway(dlsession);
do_candidates(tech_pvt, 1);
}
/* context of "_auto_" means set it to the domain */ /* context of "_auto_" means set it to the domain */
if (profile->context && !strcmp(profile->context, "_auto_")) { if (profile->context && !strcmp(profile->context, "_auto_")) {
context = profile->name; context = profile->name;
@ -3079,7 +3094,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
} }
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Creating a session for %s\n", ldl_session_get_id(dlsession)); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Creating a session for %s\n", ldl_session_get_id(dlsession));
ldl_session_set_private(dlsession, session); ldl_session_set_private(dlsession, session);
tech_pvt->dlsession = dlsession;
switch_channel_set_name(channel, "DingaLing/new"); switch_channel_set_name(channel, "DingaLing/new");
switch_channel_set_state(channel, CS_INIT); switch_channel_set_state(channel, CS_INIT);
if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) { if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) {
@ -3230,6 +3245,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
} }
} }
} }
} }
break; break;
@ -3259,7 +3275,15 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
if (profile->acl_count) { if (profile->acl_count) {
for (x = 0; x < len; x++) { for (x = 0; x < len; x++) {
uint32_t y = 0; uint32_t y = 0;
if (strcasecmp(candidates[x].protocol, "udp")) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "candidate %s:%d has an unsupported protocol!\n",
candidates[x].address, candidates[x].port);
continue;
}
for (y = 0; y < profile->acl_count; y++) { for (y = 0; y < profile->acl_count; y++) {
if (switch_check_network_list_ip(candidates[x].address, profile->acl[y])) { if (switch_check_network_list_ip(candidates[x].address, profile->acl[y])) {
choice = x; choice = x;
ok = 1; ok = 1;
@ -3268,7 +3292,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
if (ok) { if (ok) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "candidate %s:%d PASS ACL %s\n", switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "candidate %s:%d PASS ACL %s\n",
candidates[x].address, candidates[x].port, profile->acl[y]); candidates[x].address, candidates[x].port, profile->acl[y]);
break; goto end_candidates;
} else { } else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "candidate %s:%d FAIL ACL %s\n", switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "candidate %s:%d FAIL ACL %s\n",
candidates[x].address, candidates[x].port, profile->acl[y]); candidates[x].address, candidates[x].port, profile->acl[y]);
@ -3311,6 +3335,8 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
} }
} }
end_candidates:
if (ok) { if (ok) {
ldl_payload_t payloads[5]; ldl_payload_t payloads[5];

View File

@ -1233,7 +1233,6 @@ static void walk_listeners(skinny_listener_callback_func_t callback, void *pvt)
switch_hash_index_t *hi; switch_hash_index_t *hi;
void *val; void *val;
skinny_profile_t *profile; skinny_profile_t *profile;
listener_t *l;
/* walk listeners */ /* walk listeners */
switch_mutex_lock(globals.mutex); switch_mutex_lock(globals.mutex);
@ -1241,11 +1240,7 @@ static void walk_listeners(skinny_listener_callback_func_t callback, void *pvt)
switch_hash_this(hi, NULL, NULL, &val); switch_hash_this(hi, NULL, NULL, &val);
profile = (skinny_profile_t *) val; profile = (skinny_profile_t *) val;
switch_mutex_lock(profile->listener_mutex); profile_walk_listeners(profile, callback, pvt);
for (l = profile->listeners; l; l = l->next) {
callback(l, pvt);
}
switch_mutex_unlock(profile->listener_mutex);
} }
switch_mutex_unlock(globals.mutex); switch_mutex_unlock(globals.mutex);
} }
@ -1509,6 +1504,7 @@ static void *SWITCH_THREAD_FUNC skinny_profile_run(switch_thread_t *thread, void
new_socket: new_socket:
while(globals.running) { while(globals.running) {
switch_clear_flag_locked(profile, PFLAG_RESPAWN);
rv = switch_sockaddr_info_get(&sa, profile->ip, SWITCH_INET, profile->port, 0, tmp_pool); rv = switch_sockaddr_info_get(&sa, profile->ip, SWITCH_INET, profile->port, 0, tmp_pool);
if (rv) if (rv)
goto fail; goto fail;
@ -1546,8 +1542,10 @@ new_socket:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting Down\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting Down\n");
goto end; goto end;
} else if (switch_test_flag(profile, PFLAG_RESPAWN)) { } else if (switch_test_flag(profile, PFLAG_RESPAWN)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Creating a new socket\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Respawn in progress. Waiting for socket to close.\n");
switch_clear_flag_locked(profile, PFLAG_RESPAWN); while (profile->sock) {
switch_cond_next();
}
goto new_socket; goto new_socket;
} else { } else {
/* I wish we could use strerror_r here but its not defined everywhere =/ */ /* I wish we could use strerror_r here but its not defined everywhere =/ */
@ -1619,6 +1617,18 @@ switch_endpoint_interface_t *skinny_get_endpoint_interface()
return skinny_endpoint_interface; return skinny_endpoint_interface;
} }
switch_status_t skinny_profile_respawn(skinny_profile_t *profile, int force)
{
if (force || switch_test_flag(profile, PFLAG_SHOULD_RESPAWN)) {
switch_clear_flag_locked(profile, PFLAG_SHOULD_RESPAWN);
switch_set_flag_locked(profile, PFLAG_RESPAWN);
switch_clear_flag_locked(profile, PFLAG_LISTENER_READY);
profile_walk_listeners(profile, kill_listener, NULL);
close_socket(&profile->sock, profile);
}
return SWITCH_STATUS_SUCCESS;
}
switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, const char *val) switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, const char *val)
{ {
if (!var) if (!var)
@ -1633,9 +1643,15 @@ switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, c
if (!strcasecmp(var, "domain")) { if (!strcasecmp(var, "domain")) {
profile->domain = switch_core_strdup(profile->pool, val); profile->domain = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "ip")) { } else if (!strcasecmp(var, "ip")) {
if (!profile->ip || strcmp(val, profile->ip)) {
profile->ip = switch_core_strdup(profile->pool, val); profile->ip = switch_core_strdup(profile->pool, val);
switch_set_flag_locked(profile, PFLAG_SHOULD_RESPAWN);
}
} else if (!strcasecmp(var, "port")) { } else if (!strcasecmp(var, "port")) {
if (atoi(val) != profile->port) {
profile->port = atoi(val); profile->port = atoi(val);
switch_set_flag_locked(profile, PFLAG_SHOULD_RESPAWN);
}
} else if (!strcasecmp(var, "patterns-dialplan")) { } else if (!strcasecmp(var, "patterns-dialplan")) {
profile->patterns_dialplan = switch_core_strdup(profile->pool, val); profile->patterns_dialplan = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "patterns-context")) { } else if (!strcasecmp(var, "patterns-context")) {
@ -1669,15 +1685,21 @@ switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, c
} else { } else {
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
if (profile->sock && (!strcasecmp(var, "ip") || !strcasecmp(var, "port"))) {
switch_set_flag_locked(profile, PFLAG_RESPAWN);
switch_clear_flag_locked(profile, PFLAG_LISTENER_READY);
close_socket(&profile->sock, profile);
}
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
void profile_walk_listeners(skinny_profile_t *profile, skinny_listener_callback_func_t callback, void *pvt)
{
listener_t *l;
switch_mutex_lock(profile->listener_mutex);
for (l = profile->listeners; l; l = l->next) {
callback(l, pvt);
}
switch_mutex_unlock(profile->listener_mutex);
}
static switch_status_t load_skinny_config(void) static switch_status_t load_skinny_config(void)
{ {
char *cf = "skinny.conf"; char *cf = "skinny.conf";
@ -1692,8 +1714,7 @@ static switch_status_t load_skinny_config(void)
if ((xprofiles = switch_xml_child(xcfg, "profiles"))) { if ((xprofiles = switch_xml_child(xcfg, "profiles"))) {
for (xprofile = switch_xml_child(xprofiles, "profile"); xprofile; xprofile = xprofile->next) { for (xprofile = switch_xml_child(xprofiles, "profile"); xprofile; xprofile = xprofile->next) {
char *profile_name = (char *) switch_xml_attr_soft(xprofile, "name"); char *profile_name = (char *) switch_xml_attr_soft(xprofile, "name");
switch_xml_t xsettings; switch_xml_t xsettings, xdevice_types, xsoft_key_set_sets;
switch_xml_t xdevice_types;
if (zstr(profile_name)) { if (zstr(profile_name)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"<profile> is missing name attribute\n"); "<profile> is missing name attribute\n");
@ -1749,6 +1770,96 @@ static switch_status_t load_skinny_config(void)
profile->port = 2000; profile->port = 2000;
} }
/* Soft Key Set Sets */
switch_core_hash_init(&profile->soft_key_set_sets_hash, profile->pool);
if ((xsoft_key_set_sets = switch_xml_child(xprofile, "soft-key-set-sets"))) {
switch_xml_t xsoft_key_set_set;
for (xsoft_key_set_set = switch_xml_child(xsoft_key_set_sets, "soft-key-set-set"); xsoft_key_set_set; xsoft_key_set_set = xsoft_key_set_set->next) {
char *soft_key_set_set_name = (char *) switch_xml_attr_soft(xsoft_key_set_set, "name");
if (soft_key_set_set_name) {
switch_xml_t xsoft_key_set;
skinny_message_t *message;
message = switch_core_alloc(profile->pool, 12+sizeof(message->data.soft_key_set));
message->type = SOFT_KEY_SET_RES_MESSAGE;
message->length = 4 + sizeof(message->data.soft_key_set);
message->data.soft_key_set.soft_key_set_offset = 0;
message->data.soft_key_set.soft_key_set_count = 11;
message->data.soft_key_set.total_soft_key_set_count = 11;
for (xsoft_key_set = switch_xml_child(xsoft_key_set_set, "soft-key-set"); xsoft_key_set; xsoft_key_set = xsoft_key_set->next) {
uint32_t soft_key_set_id;
if ((soft_key_set_id = skinny_str2soft_key_set(switch_xml_attr_soft(xsoft_key_set, "name"))) != -1) {
char *val =switch_core_strdup(profile->pool, switch_xml_attr_soft(xsoft_key_set, "value"));
size_t string_len = strlen(val);
size_t string_pos, start = 0;
int field_no = 0;
if (soft_key_set_id > 15) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"soft-key-set name '%s' is greater than 15 in soft-key-set-set '%s' in profile %s.\n",
switch_xml_attr_soft(xsoft_key_set, "name"), soft_key_set_set_name, profile->name);
continue;
}
for (string_pos = 0; string_pos <= string_len; string_pos++) {
if ((val[string_pos] == ',') || (string_pos == string_len)) {
val[string_pos] = '\0';
if (field_no > 15) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"soft-key-set name '%s' is limited to 16 buttons in soft-key-set-set '%s' in profile %s.\n",
switch_xml_attr_soft(xsoft_key_set, "name"), soft_key_set_set_name, profile->name);
break;
}
message->data.soft_key_set.soft_key_set[soft_key_set_id].soft_key_template_index[field_no++] = skinny_str2soft_key_event(&val[start]);
start = string_pos+1;
}
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Unknown soft-key-set name '%s' in soft-key-set-set '%s' in profile %s.\n",
switch_xml_attr_soft(xsoft_key_set, "name"), soft_key_set_set_name, profile->name);
}
} /* soft-key-set */
switch_core_hash_insert(profile->soft_key_set_sets_hash, soft_key_set_set_name, message);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"<soft-key-set-set> is missing a name attribute in profile %s.\n", profile->name);
}
} /* soft-key-set-set */
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"<soft-key-set-sets> is missing in profile %s.\n", profile->name);
} /* soft-key-set-sets */
if (!switch_core_hash_find(profile->soft_key_set_sets_hash, "default")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Profile %s doesn't have a default <soft-key-set-set>. Profile ignored.\n", profile->name);
switch_core_destroy_memory_pool(&profile_pool);
continue;
}
/* Device types */
switch_core_hash_init(&profile->device_type_params_hash, profile->pool);
if ((xdevice_types = switch_xml_child(xprofile, "device-types"))) {
switch_xml_t xdevice_type;
for (xdevice_type = switch_xml_child(xdevice_types, "device-type"); xdevice_type; xdevice_type = xdevice_type->next) {
uint32_t id = skinny_str2device_type(switch_xml_attr_soft(xdevice_type, "id"));
if (id != 0) {
char *id_str = switch_mprintf("%d", id);
skinny_device_type_params_t *params = switch_core_alloc(profile->pool, sizeof(skinny_device_type_params_t));
for (param = switch_xml_child(xdevice_type, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
if (!strcasecmp(var, "firmware-version")) {
strncpy(params->firmware_version, val, 16);
}
} /* param */
switch_core_hash_insert(profile->device_type_params_hash, id_str, params);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Unknow device type %s in profile %s.\n", switch_xml_attr_soft(xdevice_type, "id"), profile->name);
}
}
}
/* Database */ /* Database */
switch_snprintf(dbname, sizeof(dbname), "skinny_%s", profile->name); switch_snprintf(dbname, sizeof(dbname), "skinny_%s", profile->name);
profile->dbname = switch_core_strdup(profile->pool, dbname); profile->dbname = switch_core_strdup(profile->pool, dbname);
@ -1787,30 +1898,7 @@ static switch_status_t load_skinny_config(void)
skinny_execute_sql_callback(profile, profile->sql_mutex, "DELETE FROM skinny_buttons", NULL, NULL); skinny_execute_sql_callback(profile, profile->sql_mutex, "DELETE FROM skinny_buttons", NULL, NULL);
skinny_execute_sql_callback(profile, profile->sql_mutex, "DELETE FROM skinny_active_lines", NULL, NULL); skinny_execute_sql_callback(profile, profile->sql_mutex, "DELETE FROM skinny_active_lines", NULL, NULL);
/* Device types */ skinny_profile_respawn(profile, 0);
switch_core_hash_init(&profile->device_type_params_hash, profile->pool);
if ((xdevice_types = switch_xml_child(xprofile, "device-types"))) {
switch_xml_t xdevice_type;
for (xdevice_type = switch_xml_child(xdevice_types, "device-type"); xdevice_type; xdevice_type = xdevice_type->next) {
uint32_t id = skinny_str2device_type(switch_xml_attr_soft(xdevice_type, "id"));
if (id != 0) {
char *id_str = switch_mprintf("%d", id);
skinny_device_type_params_t *params = switch_core_alloc(profile->pool, sizeof(skinny_device_type_params_t));
for (param = switch_xml_child(xdevice_type, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
if (!strcasecmp(var, "firmware-version")) {
strncpy(params->firmware_version, val, 16);
}
} /* param */
switch_core_hash_insert(profile->device_type_params_hash, id_str, params);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Unknow device type %s in profile %s.\n", switch_xml_attr_soft(xdevice_type, "id"), profile->name);
}
}
}
/* Register profile */ /* Register profile */
switch_mutex_lock(globals.mutex); switch_mutex_lock(globals.mutex);
@ -2009,6 +2097,7 @@ static void skinny_trap_event_handler(switch_event_t *event)
} else if (!strcmp(profile->ip, old_ip6)) { } else if (!strcmp(profile->ip, old_ip6)) {
skinny_profile_set(profile, "ip", new_ip6); skinny_profile_set(profile, "ip", new_ip6);
} }
skinny_profile_respawn(profile, 0);
} }
} }
} }
@ -2034,9 +2123,14 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load)
load_skinny_config(); load_skinny_config();
/* at least one profile */
if (!switch_hash_first(NULL, globals.profile_hash)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No profile found!\n");
return SWITCH_STATUS_TERM;
}
/* bind to events */ /* bind to events */
if ((switch_event_bind_removable(modname, SWITCH_EVENT_HEARTBEAT, NULL, skinny_heartbeat_event_handler, NULL, &globals.heartbeat_node) != SWITCH_STATUS_SUCCESS)) { if ((switch_event_bind_removable(modname, SWITCH_EVENT_HEARTBEAT, NULL, skinny_heartbeat_event_handler, NULL, &globals.heartbeat_node) != SWITCH_STATUS_SUCCESS)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our heartbeat handler!\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't bind our heartbeat handler!\n");
/* Not such severe to prevent loading */ /* Not such severe to prevent loading */
} }
if ((switch_event_bind_removable(modname, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_CALL_STATE, skinny_call_state_event_handler, NULL, &globals.call_state_node) != SWITCH_STATUS_SUCCESS)) { if ((switch_event_bind_removable(modname, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_CALL_STATE, skinny_call_state_event_handler, NULL, &globals.call_state_node) != SWITCH_STATUS_SUCCESS)) {
@ -2044,11 +2138,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load)
return SWITCH_STATUS_TERM; return SWITCH_STATUS_TERM;
} }
if ((switch_event_bind_removable(modname, SWITCH_EVENT_MESSAGE_WAITING, NULL, skinny_message_waiting_event_handler, NULL, &globals.message_waiting_node) != SWITCH_STATUS_SUCCESS)) { if ((switch_event_bind_removable(modname, SWITCH_EVENT_MESSAGE_WAITING, NULL, skinny_message_waiting_event_handler, NULL, &globals.message_waiting_node) != SWITCH_STATUS_SUCCESS)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our message waiting handler!\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't bind our message waiting handler!\n");
/* Not such severe to prevent loading */ /* Not such severe to prevent loading */
} }
if ((switch_event_bind_removable(modname, SWITCH_EVENT_TRAP, NULL, skinny_trap_event_handler, NULL, &globals.trap_node) != SWITCH_STATUS_SUCCESS)) { if ((switch_event_bind_removable(modname, SWITCH_EVENT_TRAP, NULL, skinny_trap_event_handler, NULL, &globals.trap_node) != SWITCH_STATUS_SUCCESS)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our trap handler!\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't bind our trap handler!\n");
/* Not such severe to prevent loading */ /* Not such severe to prevent loading */
} }

View File

@ -61,7 +61,8 @@ extern skinny_globals_t globals;
typedef enum { typedef enum {
PFLAG_LISTENER_READY = (1 << 0), PFLAG_LISTENER_READY = (1 << 0),
PFLAG_RESPAWN = (1 << 1), PFLAG_SHOULD_RESPAWN = (1 << 1),
PFLAG_RESPAWN = (1 << 2),
} profile_flag_t; } profile_flag_t;
struct skinny_profile { struct skinny_profile {
@ -78,6 +79,7 @@ struct skinny_profile {
char date_format[6]; char date_format[6];
int debug; int debug;
int auto_restart; int auto_restart;
switch_hash_t *soft_key_set_sets_hash;
switch_hash_t *device_type_params_hash; switch_hash_t *device_type_params_hash;
/* db */ /* db */
char *dbname; char *dbname;
@ -133,6 +135,7 @@ struct listener {
uint32_t device_type; uint32_t device_type;
char firmware_version[16]; char firmware_version[16];
char *soft_key_set_set;
switch_socket_t *sock; switch_socket_t *sock;
switch_memory_pool_t *pool; switch_memory_pool_t *pool;
@ -220,6 +223,9 @@ switch_core_session_t * skinny_profile_perform_find_session(skinny_profile_t *pr
switch_core_session_t * skinny_profile_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id); switch_core_session_t * skinny_profile_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id);
#endif #endif
switch_status_t dump_device(skinny_profile_t *profile, const char *device_name, switch_stream_handle_t *stream); switch_status_t dump_device(skinny_profile_t *profile, const char *device_name, switch_stream_handle_t *stream);
switch_status_t skinny_profile_respawn(skinny_profile_t *profile, int force);
switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, const char *val);
void profile_walk_listeners(skinny_profile_t *profile, skinny_listener_callback_func_t callback, void *pvt);
/*****************************************************************************/ /*****************************************************************************/
/* SQL FUNCTIONS */ /* SQL FUNCTIONS */
@ -262,7 +268,6 @@ switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
/* MODULE FUNCTIONS */ /* MODULE FUNCTIONS */
/*****************************************************************************/ /*****************************************************************************/
switch_endpoint_interface_t *skinny_get_endpoint_interface(); switch_endpoint_interface_t *skinny_get_endpoint_interface();
switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, const char *val);
#endif /* _MOD_SKINNY_H */ #endif /* _MOD_SKINNY_H */

View File

@ -275,6 +275,7 @@ static switch_status_t skinny_api_cmd_profile_device_send_ringer_message(const c
skinny_profile_find_listener_by_device_name(profile, device_name, &listener); skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
if(listener) { if(listener) {
send_set_ringer(listener, skinny_str2ring_type(ring_type), skinny_str2ring_mode(ring_mode), 0, 0); send_set_ringer(listener, skinny_str2ring_type(ring_type), skinny_str2ring_mode(ring_mode), 0, 0);
stream->write_function(stream, "+OK\n");
} else { } else {
stream->write_function(stream, "Listener not found!\n"); stream->write_function(stream, "Listener not found!\n");
} }
@ -294,6 +295,7 @@ static switch_status_t skinny_api_cmd_profile_device_send_lamp_message(const cha
skinny_profile_find_listener_by_device_name(profile, device_name, &listener); skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
if(listener) { if(listener) {
send_set_lamp(listener, skinny_str2button(stimulus), atoi(instance), skinny_str2lamp_mode(lamp_mode)); send_set_lamp(listener, skinny_str2button(stimulus), atoi(instance), skinny_str2lamp_mode(lamp_mode));
stream->write_function(stream, "+OK\n");
} else { } else {
stream->write_function(stream, "Listener not found!\n"); stream->write_function(stream, "Listener not found!\n");
} }
@ -313,6 +315,7 @@ static switch_status_t skinny_api_cmd_profile_device_send_speaker_mode_message(c
skinny_profile_find_listener_by_device_name(profile, device_name, &listener); skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
if(listener) { if(listener) {
send_set_speaker_mode(listener, skinny_str2speaker_mode(speaker_mode)); send_set_speaker_mode(listener, skinny_str2speaker_mode(speaker_mode));
stream->write_function(stream, "+OK\n");
} else { } else {
stream->write_function(stream, "Listener not found!\n"); stream->write_function(stream, "Listener not found!\n");
} }
@ -332,6 +335,7 @@ static switch_status_t skinny_api_cmd_profile_device_send_call_state_message(con
skinny_profile_find_listener_by_device_name(profile, device_name, &listener); skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
if(listener) { if(listener) {
send_call_state(listener, skinny_str2call_state(call_state), atoi(line_instance), atoi(call_id)); send_call_state(listener, skinny_str2call_state(call_state), atoi(line_instance), atoi(call_id));
stream->write_function(stream, "+OK\n");
} else { } else {
stream->write_function(stream, "Listener not found!\n"); stream->write_function(stream, "Listener not found!\n");
} }
@ -351,6 +355,7 @@ static switch_status_t skinny_api_cmd_profile_device_send_reset_message(const ch
skinny_profile_find_listener_by_device_name(profile, device_name, &listener); skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
if(listener) { if(listener) {
send_reset(listener, skinny_str2device_reset_type(reset_type)); send_reset(listener, skinny_str2device_reset_type(reset_type));
stream->write_function(stream, "+OK\n");
} else { } else {
stream->write_function(stream, "Listener not found!\n"); stream->write_function(stream, "Listener not found!\n");
} }
@ -366,7 +371,10 @@ static switch_status_t skinny_api_cmd_profile_set(const char *profile_name, cons
skinny_profile_t *profile; skinny_profile_t *profile;
if ((profile = skinny_find_profile(profile_name))) { if ((profile = skinny_find_profile(profile_name))) {
if (skinny_profile_set(profile, name, value) != SWITCH_STATUS_SUCCESS) { if (skinny_profile_set(profile, name, value) == SWITCH_STATUS_SUCCESS) {
skinny_profile_respawn(profile, 0);
stream->write_function(stream, "+OK\n");
} else {
stream->write_function(stream, "Unable to set skinny setting '%s'. Does it exists?\n", name); stream->write_function(stream, "Unable to set skinny setting '%s'. Does it exists?\n", name);
} }
} else { } else {

View File

@ -122,6 +122,9 @@ switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req)
while (listener_is_ready(listener)) { while (listener_is_ready(listener)) {
uint8_t do_sleep = 1; uint8_t do_sleep = 1;
if (listener->expire_time && listener->expire_time < switch_epoch_time_now(NULL)) {
return SWITCH_STATUS_TIMEOUT;
}
if(bytes < SKINNY_MESSAGE_FIELD_SIZE) { if(bytes < SKINNY_MESSAGE_FIELD_SIZE) {
/* We have nothing yet, get length header field */ /* We have nothing yet, get length header field */
mlen = SKINNY_MESSAGE_FIELD_SIZE - bytes; mlen = SKINNY_MESSAGE_FIELD_SIZE - bytes;
@ -171,9 +174,6 @@ switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req)
} }
} }
} }
if (listener->expire_time && listener->expire_time < switch_epoch_time_now(NULL)) {
return SWITCH_STATUS_TIMEOUT;
}
if (do_sleep) { if (do_sleep) {
switch_cond_next(); switch_cond_next();
} }

View File

@ -151,7 +151,7 @@ struct PACKED open_receive_channel_ack_message {
/* SoftKeyEventMessage */ /* SoftKeyEventMessage */
#define SOFT_KEY_EVENT_MESSAGE 0x0026 #define SOFT_KEY_EVENT_MESSAGE 0x0026
struct PACKED soft_key_event_message { struct PACKED soft_key_event_message {
uint32_t event; uint32_t event; /* See enum skinny_soft_key_event */
uint32_t line_instance; uint32_t line_instance;
uint32_t call_id; uint32_t call_id;
}; };

View File

@ -999,6 +999,8 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r
const char *value = switch_xml_attr_soft(xparam, "value"); const char *value = switch_xml_attr_soft(xparam, "value");
if (!strcasecmp(name, "skinny-firmware-version")) { if (!strcasecmp(name, "skinny-firmware-version")) {
strncpy(listener->firmware_version, value, 16); strncpy(listener->firmware_version, value, 16);
} else if (!strcasecmp(name, "skinny-soft-key-set-set")) {
listener->soft_key_set_set = switch_core_strdup(profile->pool, value);
} }
} }
} }
@ -1693,49 +1695,20 @@ end:
switch_status_t skinny_handle_soft_key_set_request(listener_t *listener, skinny_message_t *request) switch_status_t skinny_handle_soft_key_set_request(listener_t *listener, skinny_message_t *request)
{ {
skinny_message_t *message; skinny_message_t *message = NULL;
skinny_profile_t *profile;
switch_assert(listener->profile);
switch_assert(listener->device_name);
profile = listener->profile;
message = switch_core_alloc(listener->pool, 12+sizeof(message->data.soft_key_set));
message->type = SOFT_KEY_SET_RES_MESSAGE;
message->length = 4 + sizeof(message->data.soft_key_set);
message->data.soft_key_set.soft_key_set_offset = 0;
message->data.soft_key_set.soft_key_set_count = 11;
message->data.soft_key_set.total_soft_key_set_count = 11;
/* TODO fill the set */
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[0] = SOFTKEY_NEWCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[1] = SOFTKEY_REDIAL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK].soft_key_template_index[1] = SOFTKEY_REDIAL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK].soft_key_template_index[2] = SOFTKEY_ENDCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT].soft_key_template_index[0] = SOFTKEY_BACKSPACE;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT].soft_key_template_index[2] = SOFTKEY_ENDCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[0] = SOFTKEY_ENDCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[1] = SOFTKEY_HOLD;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[2] = SOFTKEY_NEWCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[3] = SOFTKEY_TRANSFER;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[0] = SOFTKEY_ANSWER;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[1] = SOFTKEY_ENDCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[2] = SOFTKEY_NEWCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[0] = SOFTKEY_NEWCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[1] = SOFTKEY_RESUME;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[2] = SOFTKEY_ENDCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK_WITH_FEATURES].soft_key_template_index[1] = SOFTKEY_REDIAL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK_WITH_FEATURES].soft_key_template_index[2] = SOFTKEY_ENDCALL;
if (listener->soft_key_set_set) {
message = switch_core_hash_find(listener->profile->soft_key_set_sets_hash, listener->soft_key_set_set);
}
if (!message) {
message = switch_core_hash_find(listener->profile->soft_key_set_sets_hash, "default");
}
if (message) {
skinny_send_reply(listener, message); skinny_send_reply(listener, message);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Profile %s doesn't have a default <soft-key-set-set>.\n", listener->profile->name);
}
/* Init the states */ /* Init the states */
send_select_soft_keys(listener, 0, 0, SKINNY_KEY_SET_ON_HOOK, 0xffff); send_select_soft_keys(listener, 0, 0, SKINNY_KEY_SET_ON_HOOK, 0xffff);

View File

@ -152,6 +152,32 @@ struct skinny_table SKINNY_BUTTONS[] = {
SKINNY_DECLARE_ID2STR(skinny_button2str, SKINNY_BUTTONS, "Unknown") SKINNY_DECLARE_ID2STR(skinny_button2str, SKINNY_BUTTONS, "Unknown")
SKINNY_DECLARE_STR2ID(skinny_str2button, SKINNY_BUTTONS, -1) SKINNY_DECLARE_STR2ID(skinny_str2button, SKINNY_BUTTONS, -1)
struct skinny_table SKINNY_SOFT_KEY_EVENTS[] = {
{"SoftkeyRedial", SOFTKEY_REDIAL},
{"SoftkeyNewcall", SOFTKEY_NEWCALL},
{"SoftkeyHold", SOFTKEY_HOLD},
{"SoftkeyTransfer", SOFTKEY_TRANSFER},
{"SoftkeyCfwdall", SOFTKEY_CFWDALL},
{"SoftkeyCfwdbusy", SOFTKEY_CFWDBUSY},
{"SoftkeyCfwdnoanswer", SOFTKEY_CFWDNOANSWER},
{"SoftkeyBackspace", SOFTKEY_BACKSPACE},
{"SoftkeyEndcall", SOFTKEY_ENDCALL},
{"SoftkeyResume", SOFTKEY_RESUME},
{"SoftkeyAnswer", SOFTKEY_ANSWER },
{"SoftkeyInfo", SOFTKEY_INFO},
{"SoftkeyConfrm", SOFTKEY_CONFRM},
{"SoftkeyPark", SOFTKEY_PARK},
{"SoftkeyJoin", SOFTKEY_JOIN},
{"SoftkeyMeetmeconfrm", SOFTKEY_MEETMECONFRM},
{"SoftkeyCallpickup", SOFTKEY_CALLPICKUP},
{"SoftkeyGrpcallpickup", SOFTKEY_GRPCALLPICKUP},
{"SoftkeyDnd", SOFTKEY_DND},
{"SoftkeyIdivert", SOFTKEY_IDIVERT},
{NULL, 0}
};
SKINNY_DECLARE_ID2STR(skinny_soft_key_event2str, SKINNY_SOFT_KEY_EVENTS, "SoftkeyUnknown")
SKINNY_DECLARE_STR2ID(skinny_str2soft_key_event, SKINNY_SOFT_KEY_EVENTS, 0)
struct skinny_table SKINNY_LAMP_MODES[] = { struct skinny_table SKINNY_LAMP_MODES[] = {
{"Off", SKINNY_LAMP_OFF}, {"Off", SKINNY_LAMP_OFF},
{"On", SKINNY_LAMP_ON}, {"On", SKINNY_LAMP_ON},

View File

@ -194,6 +194,10 @@ enum skinny_soft_key_event {
SOFTKEY_DND = 0x13, SOFTKEY_DND = 0x13,
SOFTKEY_IDIVERT = 0x14, SOFTKEY_IDIVERT = 0x14,
}; };
extern struct skinny_table SKINNY_SOFT_KEY_EVENTS[21];
const char *skinny_soft_key_event2str(uint32_t id);
uint32_t skinny_str2soft_key_event(const char *str);
#define SKINNY_PUSH_SOFT_KEY_EVENTS SKINNY_DECLARE_PUSH_MATCH(SOFT_KEY_EVENTS)
enum skinny_key_set { enum skinny_key_set {
SKINNY_KEY_SET_ON_HOOK = 0, SKINNY_KEY_SET_ON_HOOK = 0,

View File

@ -697,7 +697,11 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) { if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_RESPONSE_HEADER_PREFIX); char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_RESPONSE_HEADER_PREFIX);
char *cid = generate_pai_str(session); char *cid = NULL;
if (sofia_test_pflag(tech_pvt->profile, PFLAG_PASS_CALLEE_ID)) {
cid = generate_pai_str(session);
}
if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) && tech_pvt->early_sdp && strcmp(tech_pvt->early_sdp, tech_pvt->local_sdp_str)) { if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) && tech_pvt->early_sdp && strcmp(tech_pvt->early_sdp, tech_pvt->local_sdp_str)) {
/* The SIP RFC for SOA forbids sending a 183 with one sdp then a 200 with another but it won't do us much good unless /* The SIP RFC for SOA forbids sending a 183 with one sdp then a 200 with another but it won't do us much good unless
@ -1757,6 +1761,13 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
} else if ((ua && (switch_stristr("aastra", ua)))) { } else if ((ua && (switch_stristr("aastra", ua)))) {
snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <sip:%s@%s>", name, number, tech_pvt->profile->sipip); snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <sip:%s@%s>", name, number, tech_pvt->profile->sipip);
sofia_set_flag_locked(tech_pvt, TFLAG_UPDATING_DISPLAY);
nua_update(tech_pvt->nh,
TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message)),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), TAG_END());
} else if ((ua && (switch_stristr("cisco", ua)))) {
snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <sip:%s@%s>", name, number, tech_pvt->profile->sipip);
sofia_set_flag_locked(tech_pvt, TFLAG_UPDATING_DISPLAY); sofia_set_flag_locked(tech_pvt, TFLAG_UPDATING_DISPLAY);
nua_update(tech_pvt->nh, nua_update(tech_pvt->nh,
TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message)), TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message)),
@ -2158,7 +2169,11 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) { if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
char *extra_header = sofia_glue_get_extra_headers(channel, SOFIA_SIP_PROGRESS_HEADER_PREFIX); char *extra_header = sofia_glue_get_extra_headers(channel, SOFIA_SIP_PROGRESS_HEADER_PREFIX);
char *cid = generate_pai_str(session); char *cid = NULL;
if (sofia_test_pflag(tech_pvt->profile, PFLAG_PASS_CALLEE_ID)) {
cid = generate_pai_str(session);
}
if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) && if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) &&
tech_pvt->early_sdp && strcmp(tech_pvt->early_sdp, tech_pvt->local_sdp_str)) { tech_pvt->early_sdp && strcmp(tech_pvt->early_sdp, tech_pvt->local_sdp_str)) {

View File

@ -4664,22 +4664,22 @@ void sofia_glue_tech_track(sofia_profile_t *profile, switch_core_session_t *sess
return; return;
} }
if (sofia_test_flag(tech_pvt, TFLAG_TRACKED)) {
sofia_glue_tech_untrack(profile, session, SWITCH_TRUE);
}
if (switch_ivr_generate_xml_cdr(session, &cdr) == SWITCH_STATUS_SUCCESS) { if (switch_ivr_generate_xml_cdr(session, &cdr) == SWITCH_STATUS_SUCCESS) {
xml_cdr_text = switch_xml_toxml(cdr, SWITCH_FALSE); xml_cdr_text = switch_xml_toxml(cdr, SWITCH_FALSE);
switch_xml_free(cdr); switch_xml_free(cdr);
} }
if (xml_cdr_text) { if (xml_cdr_text) {
if (sofia_test_flag(tech_pvt, TFLAG_TRACKED)) {
sql = switch_mprintf("update sip_recovery set metadata='%q' where uuid='%q'", xml_cdr_text, switch_core_session_get_uuid(session));
} else {
sql = switch_mprintf("insert into sip_recovery (runtime_uuid, profile_name, hostname, uuid, metadata) values ('%q','%q','%q','%q','%q')", sql = switch_mprintf("insert into sip_recovery (runtime_uuid, profile_name, hostname, uuid, metadata) values ('%q','%q','%q','%q','%q')",
switch_core_get_uuid(), profile->name, mod_sofia_globals.hostname, switch_core_session_get_uuid(session), xml_cdr_text); switch_core_get_uuid(), profile->name, mod_sofia_globals.hostname, switch_core_session_get_uuid(session), xml_cdr_text);
}
if (sofia_test_pflag(profile, PFLAG_TRACK_CALLS_EVENTS)) { if (sofia_test_pflag(profile, PFLAG_TRACK_CALLS_EVENTS)) {
switch_event_t *event = NULL; switch_event_t *event = NULL;
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_RECOVERY_SEND) == SWITCH_STATUS_SUCCESS) { if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_RECOVERY_SEND) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "profile_name", profile->name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "profile_name", profile->name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "sql", sql); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "sql", sql);
@ -4687,8 +4687,8 @@ void sofia_glue_tech_track(sofia_profile_t *profile, switch_core_session_t *sess
} }
} }
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
free(xml_cdr_text); free(xml_cdr_text);
sofia_set_flag(tech_pvt, TFLAG_TRACKED); sofia_set_flag(tech_pvt, TFLAG_TRACKED);

View File

@ -673,8 +673,8 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot)
if (now && sofia_test_pflag(profile, PFLAG_NAT_OPTIONS_PING)) { if (now && sofia_test_pflag(profile, PFLAG_NAT_OPTIONS_PING)) {
switch_snprintf(sql, sizeof(sql), "select call_id,sip_user,sip_host,contact,status,rpid," switch_snprintf(sql, sizeof(sql), "select call_id,sip_user,sip_host,contact,status,rpid,"
"expires,user_agent,server_user,server_host,profile_name" "expires,user_agent,server_user,server_host,profile_name"
" from sip_registrations where (status like '%%AUTO-NAT%%' " " from sip_registrations where (status like '%%NAT%%' "
"or status like '%%UDP-NAT%%') and hostname='%s'", mod_sofia_globals.hostname); "or contact like '%%fs_nat=true%%') and hostname='%s'", mod_sofia_globals.hostname);
sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_nat_callback, profile); sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_nat_callback, profile);
} }
@ -1178,17 +1178,6 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_find_local_ip(guess_ip4, sizeof(guess_ip4), NULL, AF_INET); switch_find_local_ip(guess_ip4, sizeof(guess_ip4), NULL, AF_INET);
if (profile->reg_db_domain) {
if (!sofia_glue_profile_exists(to_host)) {
if (sofia_glue_add_profile(switch_core_strdup(profile->pool, to_host), profile) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Auto-Adding Alias [%s] for profile [%s]\n", to_host, profile->name);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Alias [%s] for profile [%s] (already exists)\n",
to_host, profile->name);
}
}
}
sql = switch_mprintf("insert into sip_registrations " sql = switch_mprintf("insert into sip_registrations "
"(call_id,sip_user,sip_host,presence_hosts,contact,status,rpid,expires," "(call_id,sip_user,sip_host,presence_hosts,contact,status,rpid,expires,"
@ -1430,6 +1419,17 @@ void sofia_reg_handle_sip_i_register(nua_t *nua, sofia_profile_t *profile, nua_h
int network_port = 0; int network_port = 0;
char *is_nat = NULL; char *is_nat = NULL;
if (sip->sip_to && sip->sip_to->a_url && sip->sip_to->a_url->url_host) {
const char *to_host = sip->sip_to->a_url->url_host;
if (profile->reg_db_domain) {
if (!sofia_glue_profile_exists(to_host)) {
if (sofia_glue_add_profile(switch_core_strdup(profile->pool, to_host), profile) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Auto-Adding Alias [%s] for profile [%s]\n", to_host, profile->name);
}
}
}
}
sofia_glue_get_addr(nua_current_request(nua), network_ip, sizeof(network_ip), &network_port); sofia_glue_get_addr(nua_current_request(nua), network_ip, sizeof(network_ip), &network_port);
if (!(sip->sip_contact && sip->sip_contact->m_url)) { if (!(sip->sip_contact && sip->sip_contact->m_url)) {

View File

@ -18,6 +18,10 @@
%} %}
/* Lua function typemap */
%typemap(in,checkfn="lua_isfunction") SWIGLUA_FN
%{ $1.L=L; $1.idx=$input; %}
%ignore SwitchToMempool; %ignore SwitchToMempool;
%newobject EventConsumer::pop; %newobject EventConsumer::pop;
@ -25,6 +29,7 @@
%newobject CoreSession; %newobject CoreSession;
%newobject Event; %newobject Event;
%newobject Stream; %newobject Stream;
%newobject Dbh;
/** /**
* tell swig to grok everything defined in these header files and * tell swig to grok everything defined in these header files and
@ -66,9 +71,18 @@ class Session : public CoreSession {
void setLUA(lua_State *state); void setLUA(lua_State *state);
}; };
class Dbh {
private:
switch_cache_db_handle_t *dbh;
bool connected;
static int query_callback(void *pArg, int argc, char **argv, char **cargv);
public:
Dbh(char *dsn, char *user = NULL, char *pass = NULL);
~Dbh();
bool release();
bool query(char *sql, SWIGLUA_FN lua_fun);
};
} }

View File

@ -308,3 +308,69 @@ switch_status_t Session::run_dtmf_callback(void *input, switch_input_type_t ityp
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
Dbh::Dbh(char *dsn, char *user, char *pass)
{
switch_cache_db_connection_options_t options = { {0} };
options.odbc_options.dsn = dsn;
options.odbc_options.user = user;
options.odbc_options.pass = pass;
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) == SWITCH_STATUS_SUCCESS) {
connected = true;
} else {
connected = false;
}
}
Dbh::~Dbh()
{
release();
}
bool Dbh::release()
{
if (connected) {
switch_cache_db_release_db_handle(&dbh);
connected = false;
return true;
}
return false;
}
int Dbh::query_callback(void *pArg, int argc, char **argv, char **cargv)
{
SWIGLUA_FN *lua_fun = (SWIGLUA_FN *)pArg;
lua_pushvalue(lua_fun->L, lua_fun->idx); /* get the lua callback function onto the stack */
lua_newtable(lua_fun->L); /* push a row (table) */
for (int i = 0; i < argc; i++) {
lua_pushstring(lua_fun->L, switch_str_nil(cargv[i]));
lua_pushstring(lua_fun->L, switch_str_nil(argv[i]));
lua_settable(lua_fun->L, -3);
}
lua_call(lua_fun->L, 1, 1); /* 1 in, 1 out */
if (lua_isnumber(lua_fun->L, -1)) {
if (lua_tonumber(lua_fun->L, -1) != 0) {
return 1;
}
}
return 0; /* 0 to continue with next row */
}
bool Dbh::query(char *sql, SWIGLUA_FN lua_fun)
{
if (connected) {
if (switch_cache_db_execute_sql_callback(dbh, sql, query_callback, &lua_fun, NULL) == SWITCH_STATUS_SUCCESS) {
return true;
}
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no workie workie :(\n");
return false;
}

View File

@ -8,6 +8,16 @@ extern "C" {
#include "mod_lua_extra.h" #include "mod_lua_extra.h"
} }
#include <switch_cpp.h> #include <switch_cpp.h>
typedef struct{
lua_State* L;
int idx;
}SWIGLUA_FN;
#define SWIGLUA_FN_GET(fn) {lua_pushvalue(fn.L,fn.idx);}
namespace LUA { namespace LUA {
class Session:public CoreSession { class Session:public CoreSession {
private: private:
@ -41,5 +51,17 @@ namespace LUA {
void setLUA(lua_State * state); void setLUA(lua_State * state);
}; };
class Dbh {
protected:
switch_cache_db_handle_t *dbh;
bool connected;
static int query_callback(void *pArg, int argc, char **argv, char **cargv);
public:
Dbh(char *dsn, char *user = NULL, char *pass = NULL);
~Dbh();
bool release();
bool query(char *sql, SWIGLUA_FN lua_fun);
};
} }
#endif #endif

View File

@ -1,24 +1,24 @@
--- mod_lua_wrap.cpp 2008-07-16 16:58:58.000000000 -0400 --- mod_lua_wrap.cpp.orig 2010-09-05 16:39:26.000000000 +0200
+++ old.cpp 2008-07-16 16:58:42.000000000 -0400 +++ mod_lua_wrap.cpp 2010-09-05 16:39:44.000000000 +0200
@@ -6731,7 +6731,7 @@ @@ -4913,7 +4913,7 @@
SWIG_check_num_args("LUA::Session",0,0)
result = (LUA::Session *)new LUA::Session(); result = (LUA::Session *)new LUA::Session();
SWIG_arg=0; SWIG_arg=0;
- SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; - SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++;
+ SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; result->setLUA(L); + SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; result->setLUA(L);
return SWIG_arg; return SWIG_arg;
if(0) SWIG_fail; fail:
@@ -6759,7 +6759,7 @@ @@ -4934,7 +4934,7 @@
arg2=(CoreSession *)SWIG_MustGetPtr(L,2,SWIGTYPE_p_CoreSession,0,2,"new_Session");
result = (LUA::Session *)new LUA::Session(arg1,arg2); result = (LUA::Session *)new LUA::Session(arg1,arg2);
SWIG_arg=0; SWIG_arg=0;
- SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; - SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++;
+ SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; result->setLUA(L); + SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; result->setLUA(L);
return SWIG_arg; return SWIG_arg;
if(0) SWIG_fail; fail:
@@ -6780,7 +6780,7 @@ @@ -4952,7 +4952,7 @@
arg1 = (char*)lua_tostring(L, 1); arg1 = (char*)lua_tostring(L, 1);
result = (LUA::Session *)new LUA::Session(arg1); result = (LUA::Session *)new LUA::Session(arg1);
SWIG_arg=0; SWIG_arg=0;
@ -26,13 +26,13 @@
+ SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; result->setLUA(L); + SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; result->setLUA(L);
return SWIG_arg; return SWIG_arg;
if(0) SWIG_fail; fail:
@@ -6805,7 +6805,7 @@ @@ -4970,7 +4970,7 @@
arg1=(switch_core_session_t *)SWIG_MustGetPtr(L,1,SWIGTYPE_p_switch_core_session_t,0,1,"new_Session");
result = (LUA::Session *)new LUA::Session(arg1); result = (LUA::Session *)new LUA::Session(arg1);
SWIG_arg=0; SWIG_arg=0;
- SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; - SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++;
+ SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; result->setLUA(L); + SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; result->setLUA(L);
return SWIG_arg; return SWIG_arg;
if(0) SWIG_fail; fail:

View File

@ -1490,29 +1490,31 @@ SWIG_Lua_dostring(lua_State *L, const char* str) {
#define SWIGTYPE_p_Event swig_types[3] #define SWIGTYPE_p_Event swig_types[3]
#define SWIGTYPE_p_EventConsumer swig_types[4] #define SWIGTYPE_p_EventConsumer swig_types[4]
#define SWIGTYPE_p_IVRMenu swig_types[5] #define SWIGTYPE_p_IVRMenu swig_types[5]
#define SWIGTYPE_p_LUA__Session swig_types[6] #define SWIGTYPE_p_LUA__Dbh swig_types[6]
#define SWIGTYPE_p_Stream swig_types[7] #define SWIGTYPE_p_LUA__Session swig_types[7]
#define SWIGTYPE_p_input_callback_state swig_types[8] #define SWIGTYPE_p_SWIGLUA_FN swig_types[8]
#define SWIGTYPE_p_lua_State swig_types[9] #define SWIGTYPE_p_Stream swig_types[9]
#define SWIGTYPE_p_p_switch_event_node_t swig_types[10] #define SWIGTYPE_p_input_callback_state swig_types[10]
#define SWIGTYPE_p_session_flag_t swig_types[11] #define SWIGTYPE_p_lua_State swig_types[11]
#define SWIGTYPE_p_switch_call_cause_t swig_types[12] #define SWIGTYPE_p_p_switch_event_node_t swig_types[12]
#define SWIGTYPE_p_switch_channel_state_t swig_types[13] #define SWIGTYPE_p_session_flag_t swig_types[13]
#define SWIGTYPE_p_switch_channel_t swig_types[14] #define SWIGTYPE_p_switch_call_cause_t swig_types[14]
#define SWIGTYPE_p_switch_core_session_t swig_types[15] #define SWIGTYPE_p_switch_channel_state_t swig_types[15]
#define SWIGTYPE_p_switch_event_t swig_types[16] #define SWIGTYPE_p_switch_channel_t swig_types[16]
#define SWIGTYPE_p_switch_event_types_t swig_types[17] #define SWIGTYPE_p_switch_core_session_t swig_types[17]
#define SWIGTYPE_p_switch_input_args_t swig_types[18] #define SWIGTYPE_p_switch_event_t swig_types[18]
#define SWIGTYPE_p_switch_input_type_t swig_types[19] #define SWIGTYPE_p_switch_event_types_t swig_types[19]
#define SWIGTYPE_p_switch_priority_t swig_types[20] #define SWIGTYPE_p_switch_input_args_t swig_types[20]
#define SWIGTYPE_p_switch_queue_t swig_types[21] #define SWIGTYPE_p_switch_input_type_t swig_types[21]
#define SWIGTYPE_p_switch_state_handler_table_t swig_types[22] #define SWIGTYPE_p_switch_priority_t swig_types[22]
#define SWIGTYPE_p_switch_status_t swig_types[23] #define SWIGTYPE_p_switch_queue_t swig_types[23]
#define SWIGTYPE_p_switch_stream_handle_t swig_types[24] #define SWIGTYPE_p_switch_state_handler_table_t swig_types[24]
#define SWIGTYPE_p_uint32_t swig_types[25] #define SWIGTYPE_p_switch_status_t swig_types[25]
#define SWIGTYPE_p_void swig_types[26] #define SWIGTYPE_p_switch_stream_handle_t swig_types[26]
static swig_type_info *swig_types[28]; #define SWIGTYPE_p_uint32_t swig_types[27]
static swig_module_info swig_module = {swig_types, 27, 0, 0, 0, 0}; #define SWIGTYPE_p_void swig_types[28]
static swig_type_info *swig_types[30];
static swig_module_info swig_module = {swig_types, 29, 0, 0, 0, 0};
#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
@ -7005,6 +7007,230 @@ static swig_lua_class *swig_LUA_Session_bases[] = {0,0};
static const char *swig_LUA_Session_base_names[] = {"CoreSession *",0}; static const char *swig_LUA_Session_base_names[] = {"CoreSession *",0};
static swig_lua_class _wrap_class_LUA_Session = { "Session", &SWIGTYPE_p_LUA__Session,_wrap_new_Session, swig_delete_Session, swig_LUA_Session_methods, swig_LUA_Session_attributes, swig_LUA_Session_bases, swig_LUA_Session_base_names }; static swig_lua_class _wrap_class_LUA_Session = { "Session", &SWIGTYPE_p_LUA__Session,_wrap_new_Session, swig_delete_Session, swig_LUA_Session_methods, swig_LUA_Session_attributes, swig_LUA_Session_bases, swig_LUA_Session_base_names };
static int _wrap_new_Dbh__SWIG_0(lua_State* L) {
int SWIG_arg = -1;
char *arg1 = (char *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ;
LUA::Dbh *result = 0 ;
SWIG_check_num_args("LUA::Dbh",3,3)
if(!lua_isstring(L,1)) SWIG_fail_arg("LUA::Dbh",1,"char *");
if(!lua_isstring(L,2)) SWIG_fail_arg("LUA::Dbh",2,"char *");
if(!lua_isstring(L,3)) SWIG_fail_arg("LUA::Dbh",3,"char *");
arg1 = (char *)lua_tostring(L, 1);
arg2 = (char *)lua_tostring(L, 2);
arg3 = (char *)lua_tostring(L, 3);
result = (LUA::Dbh *)new LUA::Dbh(arg1,arg2,arg3);
SWIG_arg=0;
SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Dbh,1); SWIG_arg++;
return SWIG_arg;
if(0) SWIG_fail;
fail:
lua_error(L);
return SWIG_arg;
}
static int _wrap_new_Dbh__SWIG_1(lua_State* L) {
int SWIG_arg = -1;
char *arg1 = (char *) 0 ;
char *arg2 = (char *) 0 ;
LUA::Dbh *result = 0 ;
SWIG_check_num_args("LUA::Dbh",2,2)
if(!lua_isstring(L,1)) SWIG_fail_arg("LUA::Dbh",1,"char *");
if(!lua_isstring(L,2)) SWIG_fail_arg("LUA::Dbh",2,"char *");
arg1 = (char *)lua_tostring(L, 1);
arg2 = (char *)lua_tostring(L, 2);
result = (LUA::Dbh *)new LUA::Dbh(arg1,arg2);
SWIG_arg=0;
SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Dbh,1); SWIG_arg++;
return SWIG_arg;
if(0) SWIG_fail;
fail:
lua_error(L);
return SWIG_arg;
}
static int _wrap_new_Dbh__SWIG_2(lua_State* L) {
int SWIG_arg = -1;
char *arg1 = (char *) 0 ;
LUA::Dbh *result = 0 ;
SWIG_check_num_args("LUA::Dbh",1,1)
if(!lua_isstring(L,1)) SWIG_fail_arg("LUA::Dbh",1,"char *");
arg1 = (char *)lua_tostring(L, 1);
result = (LUA::Dbh *)new LUA::Dbh(arg1);
SWIG_arg=0;
SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Dbh,1); SWIG_arg++;
return SWIG_arg;
if(0) SWIG_fail;
fail:
lua_error(L);
return SWIG_arg;
}
static int _wrap_new_Dbh(lua_State* L) {
int argc;
int argv[4]={
1,2,3,4
};
argc = lua_gettop(L);
if (argc == 1) {
int _v;
{
_v = lua_isstring(L,argv[0]);
}
if (_v) {
return _wrap_new_Dbh__SWIG_2(L);
}
}
if (argc == 2) {
int _v;
{
_v = lua_isstring(L,argv[0]);
}
if (_v) {
{
_v = lua_isstring(L,argv[1]);
}
if (_v) {
return _wrap_new_Dbh__SWIG_1(L);
}
}
}
if (argc == 3) {
int _v;
{
_v = lua_isstring(L,argv[0]);
}
if (_v) {
{
_v = lua_isstring(L,argv[1]);
}
if (_v) {
{
_v = lua_isstring(L,argv[2]);
}
if (_v) {
return _wrap_new_Dbh__SWIG_0(L);
}
}
}
}
lua_pushstring(L,"No matching function for overloaded 'new_Dbh'");
lua_error(L);return 0;
}
static int _wrap_delete_Dbh(lua_State* L) {
int SWIG_arg = -1;
LUA::Dbh *arg1 = (LUA::Dbh *) 0 ;
SWIG_check_num_args("LUA::~Dbh",1,1)
if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("LUA::~Dbh",1,"LUA::Dbh *");
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_LUA__Dbh,SWIG_POINTER_DISOWN))){
SWIG_fail_ptr("delete_Dbh",1,SWIGTYPE_p_LUA__Dbh);
}
delete arg1;
SWIG_arg=0;
return SWIG_arg;
if(0) SWIG_fail;
fail:
lua_error(L);
return SWIG_arg;
}
static int _wrap_Dbh_release(lua_State* L) {
int SWIG_arg = -1;
LUA::Dbh *arg1 = (LUA::Dbh *) 0 ;
bool result;
SWIG_check_num_args("release",1,1)
if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("release",1,"LUA::Dbh *");
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_LUA__Dbh,0))){
SWIG_fail_ptr("Dbh_release",1,SWIGTYPE_p_LUA__Dbh);
}
result = (bool)(arg1)->release();
SWIG_arg=0;
lua_pushboolean(L,(int)(result==true)); SWIG_arg++;
return SWIG_arg;
if(0) SWIG_fail;
fail:
lua_error(L);
return SWIG_arg;
}
static int _wrap_Dbh_query(lua_State* L) {
int SWIG_arg = -1;
LUA::Dbh *arg1 = (LUA::Dbh *) 0 ;
char *arg2 = (char *) 0 ;
SWIGLUA_FN arg3 ;
bool result;
SWIG_check_num_args("query",3,3)
if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("query",1,"LUA::Dbh *");
if(!lua_isstring(L,2)) SWIG_fail_arg("query",2,"char *");
if(!lua_isfunction(L,3)) SWIG_fail_arg("query",3,"SWIGLUA_FN");
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_LUA__Dbh,0))){
SWIG_fail_ptr("Dbh_query",1,SWIGTYPE_p_LUA__Dbh);
}
arg2 = (char *)lua_tostring(L, 2);
(&arg3)->L=L; (&arg3)->idx=3;
result = (bool)(arg1)->query(arg2,arg3);
SWIG_arg=0;
lua_pushboolean(L,(int)(result==true)); SWIG_arg++;
return SWIG_arg;
if(0) SWIG_fail;
fail:
lua_error(L);
return SWIG_arg;
}
static void swig_delete_Dbh(void *obj) {
LUA::Dbh *arg1 = (LUA::Dbh *) obj;
delete arg1;
}
static swig_lua_method swig_LUA_Dbh_methods[] = {
{"release", _wrap_Dbh_release},
{"query", _wrap_Dbh_query},
{0,0}
};
static swig_lua_attribute swig_LUA_Dbh_attributes[] = {
{0,0,0}
};
static swig_lua_class *swig_LUA_Dbh_bases[] = {0};
static const char *swig_LUA_Dbh_base_names[] = {0};
static swig_lua_class _wrap_class_LUA_Dbh = { "Dbh", &SWIGTYPE_p_LUA__Dbh,_wrap_new_Dbh, swig_delete_Dbh, swig_LUA_Dbh_methods, swig_LUA_Dbh_attributes, swig_LUA_Dbh_bases, swig_LUA_Dbh_base_names };
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
@ -7043,7 +7269,9 @@ static swig_type_info _swigt__p_DTMF = {"_p_DTMF", "DTMF *", 0, 0, (void*)&_wrap
static swig_type_info _swigt__p_Event = {"_p_Event", "Event *", 0, 0, (void*)&_wrap_class_Event, 0}; static swig_type_info _swigt__p_Event = {"_p_Event", "Event *", 0, 0, (void*)&_wrap_class_Event, 0};
static swig_type_info _swigt__p_EventConsumer = {"_p_EventConsumer", "EventConsumer *", 0, 0, (void*)&_wrap_class_EventConsumer, 0}; static swig_type_info _swigt__p_EventConsumer = {"_p_EventConsumer", "EventConsumer *", 0, 0, (void*)&_wrap_class_EventConsumer, 0};
static swig_type_info _swigt__p_IVRMenu = {"_p_IVRMenu", "IVRMenu *", 0, 0, (void*)&_wrap_class_IVRMenu, 0}; static swig_type_info _swigt__p_IVRMenu = {"_p_IVRMenu", "IVRMenu *", 0, 0, (void*)&_wrap_class_IVRMenu, 0};
static swig_type_info _swigt__p_LUA__Dbh = {"_p_LUA__Dbh", "LUA::Dbh *", 0, 0, (void*)&_wrap_class_LUA_Dbh, 0};
static swig_type_info _swigt__p_LUA__Session = {"_p_LUA__Session", "LUA::Session *", 0, 0, (void*)&_wrap_class_LUA_Session, 0}; static swig_type_info _swigt__p_LUA__Session = {"_p_LUA__Session", "LUA::Session *", 0, 0, (void*)&_wrap_class_LUA_Session, 0};
static swig_type_info _swigt__p_SWIGLUA_FN = {"_p_SWIGLUA_FN", "SWIGLUA_FN *", 0, 0, (void*)0, 0};
static swig_type_info _swigt__p_Stream = {"_p_Stream", "Stream *", 0, 0, (void*)&_wrap_class_Stream, 0}; static swig_type_info _swigt__p_Stream = {"_p_Stream", "Stream *", 0, 0, (void*)&_wrap_class_Stream, 0};
static swig_type_info _swigt__p_input_callback_state = {"_p_input_callback_state", "input_callback_state_t *|input_callback_state *", 0, 0, (void*)&_wrap_class_input_callback_state_t, 0}; static swig_type_info _swigt__p_input_callback_state = {"_p_input_callback_state", "input_callback_state_t *|input_callback_state *", 0, 0, (void*)&_wrap_class_input_callback_state_t, 0};
static swig_type_info _swigt__p_lua_State = {"_p_lua_State", "lua_State *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_lua_State = {"_p_lua_State", "lua_State *", 0, 0, (void*)0, 0};
@ -7072,7 +7300,9 @@ static swig_type_info *swig_type_initial[] = {
&_swigt__p_Event, &_swigt__p_Event,
&_swigt__p_EventConsumer, &_swigt__p_EventConsumer,
&_swigt__p_IVRMenu, &_swigt__p_IVRMenu,
&_swigt__p_LUA__Dbh,
&_swigt__p_LUA__Session, &_swigt__p_LUA__Session,
&_swigt__p_SWIGLUA_FN,
&_swigt__p_Stream, &_swigt__p_Stream,
&_swigt__p_input_callback_state, &_swigt__p_input_callback_state,
&_swigt__p_lua_State, &_swigt__p_lua_State,
@ -7101,7 +7331,9 @@ static swig_cast_info _swigc__p_DTMF[] = { {&_swigt__p_DTMF, 0, 0, 0},{0, 0, 0,
static swig_cast_info _swigc__p_Event[] = { {&_swigt__p_Event, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_Event[] = { {&_swigt__p_Event, 0, 0, 0},{0, 0, 0, 0}};
static swig_cast_info _swigc__p_EventConsumer[] = { {&_swigt__p_EventConsumer, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_EventConsumer[] = { {&_swigt__p_EventConsumer, 0, 0, 0},{0, 0, 0, 0}};
static swig_cast_info _swigc__p_IVRMenu[] = { {&_swigt__p_IVRMenu, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_IVRMenu[] = { {&_swigt__p_IVRMenu, 0, 0, 0},{0, 0, 0, 0}};
static swig_cast_info _swigc__p_LUA__Dbh[] = { {&_swigt__p_LUA__Dbh, 0, 0, 0},{0, 0, 0, 0}};
static swig_cast_info _swigc__p_LUA__Session[] = { {&_swigt__p_LUA__Session, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_LUA__Session[] = { {&_swigt__p_LUA__Session, 0, 0, 0},{0, 0, 0, 0}};
static swig_cast_info _swigc__p_SWIGLUA_FN[] = { {&_swigt__p_SWIGLUA_FN, 0, 0, 0},{0, 0, 0, 0}};
static swig_cast_info _swigc__p_Stream[] = { {&_swigt__p_Stream, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_Stream[] = { {&_swigt__p_Stream, 0, 0, 0},{0, 0, 0, 0}};
static swig_cast_info _swigc__p_input_callback_state[] = { {&_swigt__p_input_callback_state, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_input_callback_state[] = { {&_swigt__p_input_callback_state, 0, 0, 0},{0, 0, 0, 0}};
static swig_cast_info _swigc__p_lua_State[] = { {&_swigt__p_lua_State, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_lua_State[] = { {&_swigt__p_lua_State, 0, 0, 0},{0, 0, 0, 0}};
@ -7130,7 +7362,9 @@ static swig_cast_info *swig_cast_initial[] = {
_swigc__p_Event, _swigc__p_Event,
_swigc__p_EventConsumer, _swigc__p_EventConsumer,
_swigc__p_IVRMenu, _swigc__p_IVRMenu,
_swigc__p_LUA__Dbh,
_swigc__p_LUA__Session, _swigc__p_LUA__Session,
_swigc__p_SWIGLUA_FN,
_swigc__p_Stream, _swigc__p_Stream,
_swigc__p_input_callback_state, _swigc__p_input_callback_state,
_swigc__p_lua_State, _swigc__p_lua_State,

View File

@ -49,6 +49,19 @@ class Event {
}; };
class Dbh {
protected:
switch_cache_db_handle_t *dbh;
bool connected;
static int query_callback(void *pArg, int argc, char **argv, char **cargv);
public:
Dbh(char *dsn, char *user = NULL, char *pass = NULL);
~Dbh();
bool release();
bool query(char *sql, SWIGLUA_FN lua_fun);
};
class CoreSession { class CoreSession {
protected: protected:
switch_input_args_t args; switch_input_args_t args;

View File

@ -2035,6 +2035,36 @@ SWITCH_DECLARE(void) switch_channel_set_hunt_caller_profile(switch_channel_t *ch
switch_mutex_unlock(channel->profile_mutex); switch_mutex_unlock(channel->profile_mutex);
} }
SWITCH_DECLARE(void) switch_channel_set_origination_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
{
switch_assert(channel != NULL);
switch_assert(channel->caller_profile != NULL);
switch_mutex_lock(channel->profile_mutex);
if (channel->caller_profile) {
caller_profile->next = channel->caller_profile->origination_caller_profile;
channel->caller_profile->origination_caller_profile = caller_profile;
}
switch_assert(channel->caller_profile->origination_caller_profile->next != channel->caller_profile->origination_caller_profile);
switch_mutex_unlock(channel->profile_mutex);
}
SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_origination_caller_profile(switch_channel_t *channel)
{
switch_caller_profile_t *profile = NULL;
switch_assert(channel != NULL);
switch_mutex_lock(channel->profile_mutex);
if (channel->caller_profile) {
profile = channel->caller_profile->origination_caller_profile;
}
switch_mutex_unlock(channel->profile_mutex);
return profile;
}
SWITCH_DECLARE(void) switch_channel_set_originatee_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile) SWITCH_DECLARE(void) switch_channel_set_originatee_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
{ {
switch_assert(channel != NULL); switch_assert(channel != NULL);

View File

@ -524,6 +524,14 @@ SWITCH_DECLARE(switch_call_cause_t) switch_core_session_outgoing_channel(switch_
switch_channel_set_originator_caller_profile(peer_channel, cloned_profile); switch_channel_set_originator_caller_profile(peer_channel, cloned_profile);
} }
} }
if ((profile = switch_channel_get_caller_profile(peer_channel))) {
if ((cloned_profile = switch_caller_profile_clone(session, profile)) != 0) {
switch_channel_set_origination_caller_profile(channel, cloned_profile);
}
}
} }
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_OUTGOING) == SWITCH_STATUS_SUCCESS) { if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_OUTGOING) == SWITCH_STATUS_SUCCESS) {

View File

@ -35,6 +35,8 @@
#include <switch.h> #include <switch.h>
#include "private/switch_core_pvt.h" #include "private/switch_core_pvt.h"
#define SQLLEN 32768
static struct { static struct {
switch_cache_db_handle_t *event_db; switch_cache_db_handle_t *event_db;
switch_queue_t *sql_queue[2]; switch_queue_t *sql_queue[2];
@ -537,7 +539,7 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_execute_sql(switch_cache_db_hand
switch (dbh->type) { switch (dbh->type) {
default: default:
{ {
status = switch_cache_db_execute_sql_chunked(dbh, (char *) sql, 32768, err); status = switch_cache_db_execute_sql_chunked(dbh, (char *) sql, SQLLEN, err);
} }
break; break;
} }
@ -845,7 +847,7 @@ SWITCH_DECLARE(switch_bool_t) switch_cache_db_test_reactive(switch_cache_db_hand
#define SQLLEN 1024 * 1024
static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, void *obj) static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, void *obj)
{ {
void *pop; void *pop;
@ -853,13 +855,14 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread,
uint8_t trans = 0, nothing_in_queue = 0; uint8_t trans = 0, nothing_in_queue = 0;
uint32_t target = 100000; uint32_t target = 100000;
switch_size_t len = 0, sql_len = SQLLEN; switch_size_t len = 0, sql_len = SQLLEN;
char *tmp, *sqlbuf = (char *) malloc(sql_len); char *sqlbuf = (char *) malloc(sql_len);
char *sql; char *sql = NULL;
switch_size_t newlen; switch_size_t newlen;
int lc = 0; int lc = 0;
uint32_t loops = 0, sec = 0; uint32_t loops = 0, sec = 0;
uint32_t l1 = 1000; uint32_t l1 = 1000;
uint32_t sanity = 120; uint32_t sanity = 120;
int item_remained = 0;
switch_assert(sqlbuf); switch_assert(sqlbuf);
@ -897,9 +900,16 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread,
continue; continue;
} }
if (switch_queue_trypop(sql_manager.sql_queue[0], &pop) == SWITCH_STATUS_SUCCESS || //printf("SIZE %d %d\n", switch_queue_size(sql_manager.sql_queue[0]), switch_queue_size(sql_manager.sql_queue[1]));
if (item_remained || switch_queue_trypop(sql_manager.sql_queue[0], &pop) == SWITCH_STATUS_SUCCESS ||
switch_queue_trypop(sql_manager.sql_queue[1], &pop) == SWITCH_STATUS_SUCCESS) { switch_queue_trypop(sql_manager.sql_queue[1], &pop) == SWITCH_STATUS_SUCCESS) {
if (item_remained) {
item_remained = 0;
} else {
sql = (char *) pop; sql = (char *) pop;
}
if (sql) { if (sql) {
newlen = strlen(sql) + 2; newlen = strlen(sql) + 2;
@ -911,20 +921,18 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread,
/* ignore abnormally large strings sql strings as potential buffer overflow */ /* ignore abnormally large strings sql strings as potential buffer overflow */
if (newlen < SQLLEN) { if (newlen < SQLLEN) {
itterations++; itterations++;
if (len + newlen > sql_len) {
sql_len = len + SQLLEN; if (len + newlen < sql_len) {
if (!(tmp = realloc(sqlbuf, sql_len))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL thread ending on mem err\n");
abort();
break;
}
sqlbuf = tmp;
}
sprintf(sqlbuf + len, "%s;\n", sql); sprintf(sqlbuf + len, "%s;\n", sql);
len += newlen; len += newlen;
} else {
item_remained = 1;
} }
}
if (!item_remained) {
free(sql); free(sql);
}
} else { } else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "SQL thread ending\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "SQL thread ending\n");
break; break;
@ -934,7 +942,8 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread,
} }
if (trans && ((itterations == target) || (nothing_in_queue && ++lc >= 500))) { if ((item_remained || (trans && ((itterations == target) || (nothing_in_queue && ++lc >= 500)))) &&
(sql_manager.event_db->native_handle.core_db_dbh)) {
if (switch_cache_db_persistant_execute_trans(sql_manager.event_db, sqlbuf, 1) != SWITCH_STATUS_SUCCESS) { if (switch_cache_db_persistant_execute_trans(sql_manager.event_db, sqlbuf, 1) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL thread unable to commit transaction, records lost!\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL thread unable to commit transaction, records lost!\n");
} }

View File

@ -2012,6 +2012,21 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_generate_xml_cdr(switch_core_session_
cp_off += switch_ivr_set_xml_profile_data(x_main_cp, caller_profile, 0); cp_off += switch_ivr_set_xml_profile_data(x_main_cp, caller_profile, 0);
if (caller_profile->origination_caller_profile) {
switch_caller_profile_t *cp = NULL;
int off = 0;
if (!(x_o = switch_xml_add_child_d(x_main_cp, "origination", cp_off++))) {
goto error;
}
for (cp = caller_profile->origination_caller_profile; cp; cp = cp->next) {
if (!(x_caller_profile = switch_xml_add_child_d(x_o, "origination_caller_profile", off++))) {
goto error;
}
switch_ivr_set_xml_profile_data(x_caller_profile, cp, 0);
}
}
if (caller_profile->originator_caller_profile) { if (caller_profile->originator_caller_profile) {
switch_caller_profile_t *cp = NULL; switch_caller_profile_t *cp = NULL;
int off = 0; int off = 0;

View File

@ -1683,16 +1683,20 @@ SWITCH_DECLARE(switch_status_t) switch_api_execute(const char *cmd, const char *
{ {
switch_api_interface_t *api; switch_api_interface_t *api;
switch_status_t status; switch_status_t status;
char *arg_no_spaces; char *arg_used;
char *cmd_no_spaces; char *cmd_used;
switch_assert(stream != NULL); switch_assert(stream != NULL);
switch_assert(stream->data != NULL); switch_assert(stream->data != NULL);
switch_assert(stream->write_function != NULL); switch_assert(stream->write_function != NULL);
if (strcasecmp(cmd, "console_complete")) {
cmd_no_spaces = switch_strip_whitespace(cmd); cmd_used = switch_strip_whitespace(cmd);
arg_no_spaces = switch_strip_whitespace(arg); arg_used = switch_strip_whitespace(arg);
} else {
cmd_used = (char *) cmd;
arg_used = (char *) arg;
}
if (!stream->param_event) { if (!stream->param_event) {
@ -1700,17 +1704,17 @@ SWITCH_DECLARE(switch_status_t) switch_api_execute(const char *cmd, const char *
} }
if (stream->param_event) { if (stream->param_event) {
if (cmd_no_spaces) { if (cmd_used) {
switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command", cmd_no_spaces); switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command", cmd_used);
} }
if (arg_no_spaces) { if (arg_used) {
switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command-Argument", arg_no_spaces); switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command-Argument", arg_used);
} }
} }
if (cmd_no_spaces && (api = switch_loadable_module_get_api_interface(cmd_no_spaces)) != 0) { if (cmd_used && (api = switch_loadable_module_get_api_interface(cmd_used)) != 0) {
if ((status = api->function(arg_no_spaces, session, stream)) != SWITCH_STATUS_SUCCESS) { if ((status = api->function(arg_used, session, stream)) != SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "COMMAND RETURNED ERROR!\n"); stream->write_function(stream, "COMMAND RETURNED ERROR!\n");
} }
UNPROTECT_INTERFACE(api); UNPROTECT_INTERFACE(api);
@ -1723,8 +1727,13 @@ SWITCH_DECLARE(switch_status_t) switch_api_execute(const char *cmd, const char *
switch_event_fire(&stream->param_event); switch_event_fire(&stream->param_event);
} }
switch_safe_free(cmd_no_spaces); if (cmd_used != cmd) {
switch_safe_free(arg_no_spaces); switch_safe_free(cmd_used);
}
if (arg_used != arg) {
switch_safe_free(arg_used);
}
return status; return status;
} }