mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-06-12 10:17:32 +00:00
Merge branch 'master' into smgmaster
This commit is contained in:
commit
92e1a8186e
@ -10,6 +10,8 @@
|
||||
<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="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-rule-wait-second" value="300"/>
|
||||
<param name="tier-rule-wait-multiply-level" value="true"/>
|
||||
|
@ -715,15 +715,6 @@
|
||||
-->
|
||||
<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">
|
||||
<condition field="${sip_refer_to}">
|
||||
@ -758,7 +749,12 @@
|
||||
</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>
|
||||
</include>
|
||||
|
@ -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>
|
@ -3,6 +3,7 @@
|
||||
<params>
|
||||
<!-- for devices requesting firmware via SCCP, like ATA186
|
||||
<param name="skinny-firmware-version" value="ATA030101SCCP04"
|
||||
<param name="skinny-soft-key-set-set" value="default"
|
||||
-->
|
||||
<param name="foo" value="bar"/>
|
||||
</params>
|
||||
|
@ -13,6 +13,17 @@
|
||||
<param name="debug" value="4"/>
|
||||
<param name="auto-restart" value="true"/>
|
||||
</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-type id="Cisco ATA 186">
|
||||
<param name="firmware-version" value="ATA030101SCCP04"/>
|
||||
|
@ -15,6 +15,7 @@ freeswitch (1.0.7)
|
||||
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: 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: 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)
|
||||
@ -30,7 +31,7 @@ freeswitch (1.0.7)
|
||||
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: 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 'critical' param on modules.conf to abort on mod load failure from Moc
|
||||
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: 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: 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)
|
||||
libdingaling: fix race on shutdown causing crash (FSMOD-47)
|
||||
libesl: Fix potential race condition (ESL-36)
|
||||
@ -88,8 +95,10 @@ freeswitch (1.0.7)
|
||||
libfreetdm: implemented freetdm config nodes and ss7 initial configuration
|
||||
libopenzap: Add CLI tracing
|
||||
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 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: 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)
|
||||
@ -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: 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: 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_cid_lookup: honor skipcitystate when using whitepages (r:a66654de/FSMOD-53)
|
||||
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: fix relate nohear (r:f029ce07/MODAPP-428)
|
||||
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_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_dptools: add eavesdrop_enable_dtmf chan var (r:596c0012)
|
||||
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: Add 3 new commands; session_event, session_noevents, session_nixevent (r:698fa045)
|
||||
mod_erlang_event: generate long node names the same as erlang does (r:9ad509c2)
|
||||
mod_erlang_event: Improve some logging to include UUIDs (r:c0d51b83)
|
||||
mod_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: cancel outbound call if customer hangs up (r:cadb4d94)
|
||||
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: 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: 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_hash: free all hashtables on shutdown (r:e76d7d92)
|
||||
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 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: 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: 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)
|
||||
@ -210,7 +235,9 @@ freeswitch (1.0.7)
|
||||
mod_sangoma_codec: rename load/noload to register/noregister
|
||||
mod_sangoma_codec: silence suppression (r:73d9d56f)
|
||||
mod_say_es: fix grammar when saying dates and time (r:6bed19b2/MODAPP-429)
|
||||
mod_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_silk: Fix mod_silk compliance and performance issues (r:2ddbc457/MODCODEC-20)
|
||||
mod_skinny: Add the missing api files
|
||||
mod_skinny: add example dialplan and directory config (r:1bfcc17e)
|
||||
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: blind transfer MODSKINNY-10 (r:53f75e9c/MODSKINNY-10)
|
||||
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: 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: fix callee being updated with callee information
|
||||
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: 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: 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: 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)
|
||||
@ -276,6 +321,7 @@ freeswitch (1.0.7)
|
||||
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: 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 leg param to query string (XML-24)
|
||||
mod_xml_cdr: fix locked sessions (XML-26)
|
||||
|
@ -3896,7 +3896,7 @@ SWITCH_STANDARD_API(ft_function)
|
||||
ftdm_channel_t *fchan = NULL;
|
||||
ftdm_span_t *span = NULL;
|
||||
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;
|
||||
}
|
||||
ftdm_span_find_by_name(argv[1], &span);
|
||||
|
@ -338,6 +338,10 @@
|
||||
RelativePath="..\src\include\private\ftdm_buffer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\include\private\ftdm_call_utils.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\include\private\ftdm_config.h"
|
||||
>
|
||||
@ -416,6 +420,10 @@
|
||||
RelativePath="..\src\ftdm_buffer.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\ftdm_call_utils.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\ftdm_callerid.c"
|
||||
>
|
||||
|
@ -1805,6 +1805,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open(uint32_t span_id, uint32_t chan_id,
|
||||
status = FTDM_SUCCESS;
|
||||
}
|
||||
ftdm_set_flag(check, FTDM_CHANNEL_INUSE);
|
||||
ftdm_set_flag(check, FTDM_CHANNEL_OUTBOUND);
|
||||
*ftdmchan = check;
|
||||
}
|
||||
|
||||
|
@ -189,7 +189,8 @@ ftdm_state_map_t sangoma_isdn_state_map = {
|
||||
ZSD_OUTBOUND,
|
||||
ZSM_UNACCEPTABLE,
|
||||
{FTDM_CHANNEL_STATE_DIALING, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_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,
|
||||
@ -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
|
||||
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");
|
||||
} 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 {
|
||||
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 ||
|
||||
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)) {
|
||||
sng_isdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
|
||||
}
|
||||
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
|
||||
sngisdn_snd_release(ftdmchan, 0);
|
||||
} else {
|
||||
sngisdn_snd_disconnect(ftdmchan);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* now go to the HANGUP complete state */
|
||||
|
@ -68,6 +68,7 @@ typedef enum {
|
||||
FLAG_GLARE = (1 << 6),
|
||||
FLAG_DELAYED_REL = (1 << 7),
|
||||
FLAG_SENT_PROCEED = (1 << 8),
|
||||
FLAG_SEND_DISC = (1 << 9),
|
||||
} sngisdn_flag_t;
|
||||
|
||||
|
||||
@ -127,6 +128,13 @@ typedef enum {
|
||||
SNGISDN_EVENT_RST_IND,
|
||||
} 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 {
|
||||
int16_t suId;
|
||||
uint32_t suInstId;
|
||||
@ -148,6 +156,7 @@ typedef struct sngisdn_chan_data {
|
||||
|
||||
uint8_t globalFlg;
|
||||
sngisdn_glare_data_t glare;
|
||||
ftdm_timer_t *timers[SNGISDN_NUM_TIMERS];
|
||||
} sngisdn_chan_data_t;
|
||||
|
||||
/* Span specific data */
|
||||
@ -165,6 +174,7 @@ typedef struct sngisdn_span_data {
|
||||
uint8_t overlap_dial;
|
||||
uint8_t setup_arb;
|
||||
uint8_t facility;
|
||||
int8_t facility_timeout;
|
||||
ftdm_sched_t *sched;
|
||||
ftdm_queue_t *event_queue;
|
||||
} sngisdn_span_data_t;
|
||||
@ -223,8 +233,8 @@ typedef struct sngisdn_cc {
|
||||
ftdm_trunk_type_t trunktype;
|
||||
uint32_t last_suInstId;
|
||||
ftdm_mutex_t *mutex;
|
||||
sngisdn_chan_data_t *active_spInstIds[MAX_INSTID];
|
||||
sngisdn_chan_data_t *active_suInstIds[MAX_INSTID];
|
||||
sngisdn_chan_data_t *active_spInstIds[MAX_INSTID+1];
|
||||
sngisdn_chan_data_t *active_suInstIds[MAX_INSTID+1];
|
||||
}sngisdn_cc_t;
|
||||
|
||||
/* 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_connect(void* p_sngisdn_info);
|
||||
void sngisdn_delayed_disconnect(void* p_sngisdn_info);
|
||||
void sngisdn_facility_timeout(void* p_sngisdn_info);
|
||||
|
||||
/* Stack management functions */
|
||||
ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span);
|
||||
|
@ -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);
|
||||
} else if (!strcasecmp(var, "outbound-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 {
|
||||
ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var);
|
||||
}
|
||||
|
@ -78,14 +78,13 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
|
||||
}
|
||||
|
||||
sngisdn_info->suInstId = get_unique_suInstId(suId);
|
||||
sngisdn_info->spInstId = spInstId;
|
||||
sngisdn_info->spInstId = spInstId;
|
||||
|
||||
/* 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 */
|
||||
|
||||
if (sngisdn_info->glare.spInstId == spInstId) {
|
||||
clear_call_glare_data(sngisdn_info);
|
||||
}
|
||||
}
|
||||
|
||||
ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
|
||||
g_sngisdn_data.ccs[suId].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info;
|
||||
@ -105,7 +104,8 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
|
||||
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE;
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill in call information */
|
||||
cpy_calling_num_from_stack(&ftdmchan->caller_data, &conEvnt->cgPtyNmb);
|
||||
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) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n");
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID);
|
||||
/* Launch timer in case we never get a FACILITY msg */
|
||||
if (signal_data->facility_timeout) {
|
||||
ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout, sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]);
|
||||
}
|
||||
break;
|
||||
} else if (ret_val == 0) {
|
||||
strcpy(ftdmchan->caller_data.cid_name, retrieved_str);
|
||||
@ -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;
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
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_CALLPROC:
|
||||
case MI_PROGRESS:
|
||||
|
||||
switch(ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_DIALING:
|
||||
if (evntType == MI_PROGRESS) {
|
||||
case FTDM_CHANNEL_STATE_DIALING:
|
||||
if (evntType == MI_PROGRESS ||
|
||||
(cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL)) {
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
|
||||
} else {
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
|
||||
}
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_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);
|
||||
}
|
||||
break;
|
||||
@ -371,6 +407,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
|
||||
break;
|
||||
}
|
||||
|
||||
sngisdn_process_cnst_ind_end:
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
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)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
|
||||
int16_t suId = sngisdn_event->suId;
|
||||
uint32_t suInstId = sngisdn_event->suInstId;
|
||||
uint32_t spInstId = sngisdn_event->spInstId;
|
||||
|
||||
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
|
||||
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
|
||||
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
|
||||
|
||||
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) {
|
||||
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);
|
||||
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:
|
||||
/* We do not support other FACILITY types for now, so do nothing */
|
||||
break;
|
||||
@ -794,6 +839,14 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
|
||||
break;
|
||||
case 3:
|
||||
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:
|
||||
/* Remote side is still waiting for our CONNECT message */
|
||||
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
|
||||
|
@ -45,8 +45,8 @@ void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, Co
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
uint8_t bchan_no = 0;
|
||||
sngisdn_chan_data_t *sngisdn_info;
|
||||
sngisdn_event_data_t *sngisdn_event;
|
||||
sngisdn_chan_data_t *sngisdn_info = NULL;
|
||||
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.dchans[dChan].num_spans != 0, "Con Ind on unconfigured dchan\n");
|
||||
@ -96,7 +96,7 @@ void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, Co
|
||||
ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);
|
||||
|
||||
memcpy(&sngisdn_event->event.conEvnt, conEvnt, sizeof(*conEvnt));
|
||||
|
||||
|
||||
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
}
|
||||
@ -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)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
sngisdn_chan_data_t *sngisdn_info;
|
||||
sngisdn_event_data_t *sngisdn_event;
|
||||
sngisdn_chan_data_t *sngisdn_info = NULL;
|
||||
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.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) {
|
||||
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);
|
||||
@ -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)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
sngisdn_chan_data_t *sngisdn_info;
|
||||
sngisdn_event_data_t *sngisdn_event;
|
||||
sngisdn_chan_data_t *sngisdn_info = NULL;
|
||||
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.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) {
|
||||
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);
|
||||
@ -188,15 +190,15 @@ void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, C
|
||||
|
||||
memcpy(&sngisdn_event->event.cnStEvnt, cnStEvnt, sizeof(*cnStEvnt));
|
||||
|
||||
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
|
||||
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
}
|
||||
|
||||
void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
sngisdn_chan_data_t *sngisdn_info;
|
||||
sngisdn_event_data_t *sngisdn_event;
|
||||
sngisdn_chan_data_t *sngisdn_info = NULL;
|
||||
sngisdn_event_data_t *sngisdn_event = NULL;
|
||||
|
||||
ftdm_assert(spInstId != 0, "Received DISCONNECT with invalid id");
|
||||
|
||||
@ -207,13 +209,6 @@ void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, D
|
||||
ftdm_assert(0, "Inconsistent call states\n");
|
||||
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);
|
||||
|
||||
@ -229,7 +224,7 @@ void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, D
|
||||
|
||||
memcpy(&sngisdn_event->event.discEvnt, discEvnt, sizeof(*discEvnt));
|
||||
|
||||
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
|
||||
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
|
||||
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
}
|
||||
@ -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)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
sngisdn_chan_data_t *sngisdn_info;
|
||||
sngisdn_event_data_t *sngisdn_event;
|
||||
sngisdn_chan_data_t *sngisdn_info = NULL;
|
||||
sngisdn_event_data_t *sngisdn_event = NULL;
|
||||
|
||||
if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &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);
|
||||
|
||||
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));
|
||||
|
||||
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__);
|
||||
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) &&
|
||||
!(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);
|
||||
|
||||
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));
|
||||
|
||||
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__);
|
||||
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) &&
|
||||
!(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);
|
||||
|
||||
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));
|
||||
|
||||
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__);
|
||||
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) &&
|
||||
!(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);
|
||||
|
||||
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));
|
||||
|
||||
sngisdn_event->event_id = SNGISDN_EVENT_SSHL_CFM;
|
||||
@ -360,14 +355,14 @@ void sngisdn_rcv_sshl_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, S
|
||||
|
||||
memcpy(&sngisdn_event->event.ssHlEvnt, ssHlEvnt, sizeof(*ssHlEvnt));
|
||||
|
||||
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
|
||||
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
}
|
||||
void sngisdn_rcv_rmrt_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
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) &&
|
||||
!(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);
|
||||
|
||||
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));
|
||||
|
||||
sngisdn_event->event_id = SNGISDN_EVENT_RMRT_IND;
|
||||
@ -392,7 +387,7 @@ void sngisdn_rcv_rmrt_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, R
|
||||
|
||||
memcpy(&sngisdn_event->event.rmRtEvnt, rmRtEvnt, sizeof(*rmRtEvnt));
|
||||
|
||||
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
|
||||
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
}
|
||||
|
||||
@ -400,7 +395,7 @@ void sngisdn_rcv_rmrt_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, R
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
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) &&
|
||||
!(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);
|
||||
|
||||
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));
|
||||
|
||||
sngisdn_event->event_id = SNGISDN_EVENT_RMRT_CFM;
|
||||
@ -425,7 +420,7 @@ void sngisdn_rcv_rmrt_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, R
|
||||
|
||||
memcpy(&sngisdn_event->event.rmRtEvnt, rmRtEvnt, sizeof(*rmRtEvnt));
|
||||
|
||||
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
|
||||
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
}
|
||||
|
||||
@ -433,7 +428,7 @@ void sngisdn_rcv_flc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, St
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
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) &&
|
||||
!(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);
|
||||
|
||||
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));
|
||||
|
||||
sngisdn_event->event_id = SNGISDN_EVENT_FLC_IND;
|
||||
@ -457,7 +452,7 @@ void sngisdn_rcv_flc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, St
|
||||
|
||||
memcpy(&sngisdn_event->event.staEvnt, staEvnt, sizeof(*staEvnt));
|
||||
|
||||
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
|
||||
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
}
|
||||
|
||||
@ -466,7 +461,7 @@ void sngisdn_rcv_fac_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, Fa
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
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) &&
|
||||
!(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);
|
||||
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));
|
||||
|
||||
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__);
|
||||
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) &&
|
||||
!(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);
|
||||
|
||||
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));
|
||||
|
||||
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__);
|
||||
unsigned i;
|
||||
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);
|
||||
|
||||
@ -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++) {
|
||||
signal_data = g_sngisdn_data.dchans[dChan].spans[i];
|
||||
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));
|
||||
|
||||
sngisdn_event->event_id = SNGISDN_EVENT_SRV_IND;
|
||||
@ -550,7 +545,7 @@ void sngisdn_rcv_srv_ind (int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces
|
||||
sngisdn_event->signal_data = signal_data;
|
||||
|
||||
memcpy(&sngisdn_event->event.srvEvnt, srvEvnt, sizeof(*srvEvnt));
|
||||
ftdm_queue_enqueue((signal_data)->event_queue, sngisdn_event);
|
||||
ftdm_queue_enqueue((signal_data)->event_queue, sngisdn_event);
|
||||
}
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
}
|
||||
@ -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__);
|
||||
unsigned i;
|
||||
sngisdn_span_data_t *signal_data;
|
||||
sngisdn_event_data_t *sngisdn_event;
|
||||
sngisdn_span_data_t *signal_data = NULL;
|
||||
sngisdn_event_data_t *sngisdn_event = NULL;
|
||||
|
||||
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++) {
|
||||
signal_data = g_sngisdn_data.dchans[dChan].spans[i];
|
||||
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));
|
||||
|
||||
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__);
|
||||
unsigned i;
|
||||
sngisdn_span_data_t *signal_data;
|
||||
sngisdn_event_data_t *sngisdn_event;
|
||||
sngisdn_span_data_t *signal_data = NULL;
|
||||
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);
|
||||
|
||||
@ -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++) {
|
||||
signal_data = g_sngisdn_data.dchans[dChan].spans[i];
|
||||
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));
|
||||
|
||||
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__);
|
||||
unsigned i;
|
||||
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);
|
||||
|
||||
@ -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++) {
|
||||
signal_data = g_sngisdn_data.dchans[dChan].spans[i];
|
||||
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));
|
||||
|
||||
sngisdn_event->event_id = SNGISDN_EVENT_RST_CFM;
|
||||
|
@ -73,8 +73,10 @@ void __inline__ clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info)
|
||||
sngisdn_info->glare.suInstId, sngisdn_info->glare.spInstId,
|
||||
sngisdn_info->suInstId, sngisdn_info->spInstId);
|
||||
|
||||
ftdm_mutex_lock(g_sngisdn_data.ccs[sngisdn_info->glare.suId].mutex);
|
||||
g_sngisdn_data.ccs[sngisdn_info->glare.suId].active_spInstIds[sngisdn_info->glare.spInstId]=NULL;
|
||||
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_suInstIds[sngisdn_info->glare.suInstId]=NULL;
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
unsigned i;
|
||||
|
@ -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.val = 650;
|
||||
# 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.t26.val = 600;
|
||||
cfg.t.cfg.s.snGen.tmr.t26.enb = TRUE; /* t26 - waiting to repeat traffic restart waiting message for ANSI */
|
||||
cfg.t.cfg.s.snGen.tmr.t26.val = 600;
|
||||
# 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.lnkType = k->mtp3.linkType; /* link type ANSI, ITU, BICI or CHINA */
|
||||
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.p0QLen = 32; /* size of the priority 0 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.mem.region = S_REG; /* memory region 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 */
|
||||
#if (SS7_ITU88 || SS7_CHINA || SS7_TTC || SS7_NTT || SS7_BICI )
|
||||
cfg.t.cfg.s.snDLSAP.flushContFlag = FALSE; /* flush continue handling */
|
||||
#else
|
||||
cfg.t.cfg.s.snDLSAP.flushContFlag = TRUE; /* flush continue handling */
|
||||
#endif
|
||||
|
||||
switch (k->mtp3.linkType) {
|
||||
/**************************************************************************/
|
||||
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 */
|
||||
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.val = k->mtp3.t1;
|
||||
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.contReq = FALSE; /* continuity check required */
|
||||
#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.numCir =; /* Number of circuits in the circuit group */
|
||||
cfg.t.cfg.s.siCir.firstCic = 1; /* First cic 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.outTrkGrpN =; /* outgoing trunk group number (For EXM) */
|
||||
cfg.t.cfg.s.siCir.cvrTrkClli =; /* Trunk Group number (For CVR validation) */
|
||||
cfg.t.cfg.s.siCir.clli =; /* common language location identifier */
|
||||
cfg.t.cfg.s.siCir.outTrkGrpN.length = 0; /* outgoing trunk group number (For EXM) */
|
||||
cfg.t.cfg.s.siCir.cvrTrkClli.length = 0; /* Trunk Group number (For CVR validation) */
|
||||
cfg.t.cfg.s.siCir.clli.length = 0; /* common language location identifier */
|
||||
#endif
|
||||
cfg.t.cfg.s.siCir.cirTmr.t3.enb = TRUE; /* t3 timer - overload received */
|
||||
cfg.t.cfg.s.siCir.cirTmr.t3.val = k->t3;
|
||||
|
@ -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_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_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 ******************************************************************/
|
||||
@ -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 */
|
||||
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;
|
||||
/**************************************************************************/
|
||||
case SIT_STA_CGUREQ: /* CGU request */
|
||||
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;
|
||||
/**************************************************************************/
|
||||
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 */
|
||||
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;
|
||||
/**************************************************************************/
|
||||
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;
|
||||
/**************************************************************************/
|
||||
case SIT_STA_CGBINFOIND: /* circuit grp blking ind , no resp req */
|
||||
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGB no resp req\n");
|
||||
SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
|
||||
/*SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGB no resp req\n");*/
|
||||
/* handle_cgb_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);*/
|
||||
break;
|
||||
/**************************************************************************/
|
||||
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;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
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:
|
||||
|
@ -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_span_t *ftdmspan = (ftdm_span_t *) obj;
|
||||
ftdm_channel_t *ftdmchan = NULL;
|
||||
sngss7_chan_data_t *sngss7_info = NULL;
|
||||
sngss7_event_data_t *sngss7_event = NULL;
|
||||
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);
|
||||
|
||||
@ -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))) */
|
||||
|
||||
/* 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 */
|
||||
if (sngss7_span->rx_grs.range > 0) {
|
||||
ftdm_log(FTDM_LOG_DEBUG, "Found Rx GRS on span %d...checking circuits\n", ftdmspan->span_id);
|
||||
/*SS7_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);
|
||||
}
|
||||
|
||||
} /* if (ftdmspan->grs.range > 0) */
|
||||
/* check if the rx_grs has cleared */
|
||||
check_if_rx_grs_processed(ftdmspan);
|
||||
} /* if (sngss7_span->rx_grs.range > 0) */
|
||||
} /* master while loop */
|
||||
|
||||
/* clear the IN_THREAD flag so that we know the thread is done */
|
||||
|
@ -139,7 +139,6 @@ typedef struct sng_mtp_link {
|
||||
uint32_t t23;
|
||||
uint32_t t24;
|
||||
uint32_t t25;
|
||||
uint32_t t26;
|
||||
uint32_t t27;
|
||||
uint32_t t28;
|
||||
uint32_t t29;
|
||||
@ -188,6 +187,7 @@ typedef struct sng_route {
|
||||
uint32_t t19;
|
||||
uint32_t t21;
|
||||
uint32_t t25;
|
||||
uint32_t t26;
|
||||
} sng_route_t;
|
||||
|
||||
typedef struct sng_isup_intf {
|
||||
@ -329,6 +329,8 @@ typedef struct sngss7_glare_data {
|
||||
typedef struct sngss7_group_data {
|
||||
uint32_t circuit;
|
||||
uint32_t range;
|
||||
uint8_t status[255];
|
||||
uint8_t type;
|
||||
}sngss7_group_data_t;
|
||||
|
||||
typedef struct sngss7_chan_data {
|
||||
@ -348,6 +350,10 @@ typedef struct sngss7_span_data {
|
||||
ftdm_sched_t *sched;
|
||||
sngss7_group_data_t rx_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;
|
||||
}sngss7_span_data_t;
|
||||
|
||||
@ -376,8 +382,8 @@ typedef struct sngss7_event_data
|
||||
|
||||
|
||||
typedef enum {
|
||||
FLAG_RESET_RX = (1 << 0),
|
||||
FLAG_RESET_TX = (1 << 1),
|
||||
FLAG_RESET_RX = (1 << 0),
|
||||
FLAG_RESET_TX = (1 << 1),
|
||||
FLAG_RESET_SENT = (1 << 2),
|
||||
FLAG_RESET_TX_RSP = (1 << 3),
|
||||
FLAG_GRP_RESET_RX = (1 << 4),
|
||||
@ -387,27 +393,25 @@ typedef enum {
|
||||
FLAG_GRP_RESET_TX = (1 << 8),
|
||||
FLAG_GRP_RESET_SENT = (1 << 9),
|
||||
FLAG_GRP_RESET_TX_RSP = (1 << 10),
|
||||
FLAG_REMOTE_REL = (1 << 11),
|
||||
FLAG_LOCAL_REL = (1 << 12),
|
||||
FLAG_GLARE = (1 << 13),
|
||||
FLAG_INFID_RESUME = (1 << 14),
|
||||
FLAG_INFID_PAUSED = (1 << 15),
|
||||
FLAG_REMOTE_REL = (1 << 11),
|
||||
FLAG_LOCAL_REL = (1 << 12),
|
||||
FLAG_GLARE = (1 << 13),
|
||||
FLAG_INFID_RESUME = (1 << 14),
|
||||
FLAG_INFID_PAUSED = (1 << 15),
|
||||
FLAG_CKT_UCIC_BLOCK = (1 << 16),
|
||||
FLAG_CKT_UCIC_UNBLK = (1 << 17),
|
||||
FLAG_CKT_LC_BLOCK_RX = (1 << 18),
|
||||
FLAG_CKT_LC_UNBLK_RX = (1 << 19),
|
||||
FLAG_CKT_MN_BLOCK_RX = (1 << 20),
|
||||
FLAG_CKT_MN_BLOCK_TX = (1 << 21),
|
||||
FLAG_CKT_MN_UNBLK_RX = (1 << 22),
|
||||
FLAG_CKT_MN_UNBLK_RX = (1 << 21),
|
||||
FLAG_CKT_MN_BLOCK_TX = (1 << 22),
|
||||
FLAG_CKT_MN_UNBLK_TX = (1 << 23),
|
||||
FLAG_GRP_HW_BLOCK_RX = (1 << 24),
|
||||
FLAG_GRP_HW_BLOCK_TX = (1 << 25),
|
||||
FLAG_GRP_MN_BLOCK_RX = (1 << 26),
|
||||
FLAG_GRP_MN_BLOCK_TX = (1 << 27),
|
||||
FLAG_GRP_HW_UNBLK_RX = (1 << 28),
|
||||
FLAG_GRP_HW_UNBLK_TX = (1 << 29),
|
||||
FLAG_GRP_MN_UNBLK_RX = (1 << 30),
|
||||
FLAG_GRP_MN_UNBLK_TX = (1 << 31)
|
||||
FLAG_GRP_HW_UNBLK_TX = (1 << 28),
|
||||
FLAG_GRP_MN_UNBLK_TX = (1 << 29)
|
||||
} 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_gra(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_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);
|
||||
|
||||
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 *********************************************************************/
|
||||
|
@ -42,24 +42,27 @@
|
||||
/******************************************************************************/
|
||||
|
||||
/* PROTOTYPES *****************************************************************/
|
||||
void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan);
|
||||
void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan);
|
||||
void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan);
|
||||
void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan);
|
||||
void ft_to_sngss7_rlc (ftdm_channel_t * ftdmchan);
|
||||
void ft_to_sngss7_iam(ftdm_channel_t * ftdmchan);
|
||||
void ft_to_sngss7_acm(ftdm_channel_t * ftdmchan);
|
||||
void ft_to_sngss7_anm(ftdm_channel_t * ftdmchan);
|
||||
void ft_to_sngss7_rel(ftdm_channel_t * ftdmchan);
|
||||
void ft_to_sngss7_rlc(ftdm_channel_t * ftdmchan);
|
||||
|
||||
void ft_to_sngss7_rsc (ftdm_channel_t * ftdmchan);
|
||||
void ft_to_sngss7_rsca (ftdm_channel_t * ftdmchan);
|
||||
void ft_to_sngss7_rsc(ftdm_channel_t * ftdmchan);
|
||||
void ft_to_sngss7_rsca(ftdm_channel_t * ftdmchan);
|
||||
|
||||
void ft_to_sngss7_blo (ftdm_channel_t * ftdmchan);
|
||||
void ft_to_sngss7_bla (ftdm_channel_t * ftdmchan);
|
||||
void ft_to_sngss7_ubl (ftdm_channel_t * ftdmchan);
|
||||
void ft_to_sngss7_uba (ftdm_channel_t * ftdmchan);
|
||||
void ft_to_sngss7_blo(ftdm_channel_t * ftdmchan);
|
||||
void ft_to_sngss7_bla(ftdm_channel_t * ftdmchan);
|
||||
void ft_to_sngss7_ubl(ftdm_channel_t * ftdmchan);
|
||||
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_grs (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_cgba(ftdm_channel_t * ftdmchan);
|
||||
void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan);
|
||||
/******************************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
@ -113,6 +116,56 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
|
||||
iam.txMedReq.eh.pres = PRSNT_NODEF;
|
||||
iam.txMedReq.trMedReq.pres = PRSNT_NODEF;
|
||||
iam.txMedReq.trMedReq.val = ftdmchan->caller_data.bearer_capability;
|
||||
|
||||
if ((g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].switchType == LSI_SW_ANS88) ||
|
||||
(g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].switchType == LSI_SW_ANS92) ||
|
||||
(g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].switchType == LSI_SW_ANS95)) {
|
||||
|
||||
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_cdPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cdPtyNum);
|
||||
@ -126,7 +179,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
|
||||
sngss7_info->circuit->id,
|
||||
&iam,
|
||||
0);
|
||||
|
||||
|
||||
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx IAM\n");
|
||||
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
@ -463,7 +516,7 @@ void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan)
|
||||
|
||||
SiStaEvnt grs;
|
||||
|
||||
memset (&grs, 0x0, sizeof (grs));
|
||||
memset (&grs, 0x0, sizeof(grs));
|
||||
|
||||
grs.rangStat.eh.pres = PRSNT_NODEF;
|
||||
grs.rangStat.range.pres = PRSNT_NODEF;
|
||||
@ -485,6 +538,101 @@ void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan)
|
||||
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:
|
||||
* Local Variables:
|
||||
|
@ -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 check_if_rx_grs_processed(ftdm_span_t *ftdmspan);
|
||||
/******************************************************************************/
|
||||
|
||||
/* 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:
|
||||
|
@ -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")) {
|
||||
mtpLink->mtp3.switchType = LSI_SW_INDIA;
|
||||
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 {
|
||||
SS7_ERROR("\tFound an invalid linktype of \"%s\"!\n", parm->val);
|
||||
return FTDM_FAIL;
|
||||
@ -1159,6 +1168,11 @@ static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route)
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
@ -259,7 +259,10 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
|
||||
chan->physical_chan_id = x;
|
||||
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;
|
||||
|
||||
dtmf = "software";
|
||||
|
@ -1974,10 +1974,19 @@ unsigned int ldl_session_terminate(ldl_session_t *session)
|
||||
{
|
||||
iks *iq, *sess;
|
||||
unsigned int id;
|
||||
apr_hash_t *hash = session->handle->sessions;
|
||||
|
||||
new_session_iq(session, &iq, &sess, &id, "terminate");
|
||||
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;
|
||||
|
||||
}
|
||||
@ -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)
|
||||
{
|
||||
return ldl_test_flag(session, LDL_FLAG_GATEWAY) ? 1 : 0;
|
||||
|
@ -593,6 +593,7 @@ ldl_status ldl_handle_init(ldl_handle_t **handle,
|
||||
void ldl_handle_run(ldl_handle_t *handle);
|
||||
|
||||
int ldl_session_gateway(ldl_session_t *handle);
|
||||
void ldl_session_set_gateway(ldl_session_t *session);
|
||||
|
||||
/*!
|
||||
\brief Stop a libDingaLing handle
|
||||
|
@ -207,6 +207,13 @@ struct t30_state_s
|
||||
/*! \brief This is only used in full duplex (e.g. ISDN) modes. */
|
||||
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. */
|
||||
int far_end_detected;
|
||||
|
||||
|
@ -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. */
|
||||
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)
|
||||
}
|
||||
#endif
|
||||
|
@ -2377,6 +2377,8 @@ static int send_response_to_pps(t30_state_t *s)
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#define VET_ALL_FCD_FRAMES
|
||||
|
||||
static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len)
|
||||
{
|
||||
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 first_bad_frame;
|
||||
int image_ended;
|
||||
#if defined(VET_ALL_FCD_FRAMES)
|
||||
int first;
|
||||
int expected_len;
|
||||
#endif
|
||||
|
||||
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 */
|
||||
first_bad_frame = 256;
|
||||
#if defined(VET_ALL_FCD_FRAMES)
|
||||
first = TRUE;
|
||||
expected_len = 256;
|
||||
#endif
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
s->ecm_frame_map[i + 3] = 0;
|
||||
for (j = 0; j < 8; 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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_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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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];
|
||||
/* 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 */
|
||||
s->short_train = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
unexpected_frame_length(s, msg, len);
|
||||
}
|
||||
/* 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;
|
||||
@ -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:
|
||||
/* Just ignore this. It must be an extra RCP. Several are usually sent, to maximise the chance
|
||||
of receiving a correct one. */
|
||||
timer_t2_start(s);
|
||||
break;
|
||||
default:
|
||||
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:
|
||||
process_rx_dcs(s, msg, len);
|
||||
break;
|
||||
case T30_PRI_MPS:
|
||||
if (s->remote_interrupts_allowed)
|
||||
{
|
||||
}
|
||||
/* Fall through */
|
||||
case T30_MPS:
|
||||
/* Treat this as a bad quality page. */
|
||||
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);
|
||||
send_simple_frame(s, T30_RTN);
|
||||
break;
|
||||
case T30_PRI_MPS:
|
||||
/* Treat this as a bad quality page. */
|
||||
if (s->phase_d_handler)
|
||||
case T30_PRI_EOM:
|
||||
if (s->remote_interrupts_allowed)
|
||||
{
|
||||
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;
|
||||
/* Fall through */
|
||||
case T30_EOM:
|
||||
case T30_EOS:
|
||||
/* 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);
|
||||
send_simple_frame(s, T30_RTN);
|
||||
break;
|
||||
case T30_PRI_EOM:
|
||||
/* Treat this as a bad quality page. */
|
||||
if (s->phase_d_handler)
|
||||
case T30_PRI_EOP:
|
||||
if (s->remote_interrupts_allowed)
|
||||
{
|
||||
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;
|
||||
set_state(s, T30_STATE_III_Q_RTN);
|
||||
break;
|
||||
/* Fall through */
|
||||
case T30_EOP:
|
||||
/* Treat this as a bad quality page. */
|
||||
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);
|
||||
send_simple_frame(s, T30_RTN);
|
||||
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:
|
||||
s->current_status = T30_ERR_RX_DCNDATA;
|
||||
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;
|
||||
switch (fcf)
|
||||
{
|
||||
case T30_PRI_MPS:
|
||||
if (s->remote_interrupts_allowed)
|
||||
{
|
||||
}
|
||||
/* Fall through */
|
||||
case T30_MPS:
|
||||
s->next_rx_step = fcf;
|
||||
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;
|
||||
case T30_PRI_MPS:
|
||||
s->next_rx_step = fcf;
|
||||
switch (copy_quality(s))
|
||||
case T30_PRI_EOM:
|
||||
if (s->remote_interrupts_allowed)
|
||||
{
|
||||
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;
|
||||
/* Fall through */
|
||||
case T30_EOM:
|
||||
case T30_EOS:
|
||||
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;
|
||||
case T30_PRI_EOM:
|
||||
s->next_rx_step = fcf;
|
||||
switch (copy_quality(s))
|
||||
case T30_PRI_EOP:
|
||||
if (s->remote_interrupts_allowed)
|
||||
{
|
||||
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;
|
||||
/* Fall through */
|
||||
case T30_EOP:
|
||||
s->next_rx_step = fcf;
|
||||
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;
|
||||
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:
|
||||
s->current_status = T30_ERR_RX_DCNFAX;
|
||||
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:
|
||||
/* 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. */
|
||||
if (s->state == T30_STATE_F_DOC_ECM)
|
||||
{
|
||||
/* 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. */
|
||||
}
|
||||
process_rx_rcp(s, msg, len);
|
||||
break;
|
||||
case T30_EOR:
|
||||
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_EOM:
|
||||
case T30_PRI_MPS:
|
||||
/* TODO: Alert operator */
|
||||
if (s->remote_interrupts_allowed)
|
||||
{
|
||||
/* TODO: Alert operator */
|
||||
}
|
||||
/* Fall through */
|
||||
case T30_NULL:
|
||||
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;
|
||||
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:
|
||||
switch (s->next_tx_step)
|
||||
{
|
||||
case T30_MPS:
|
||||
case T30_PRI_MPS:
|
||||
case T30_MPS:
|
||||
tx_end_page(s);
|
||||
if (s->phase_d_handler)
|
||||
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);
|
||||
queue_phase(s, T30_PHASE_C_NON_ECM_TX);
|
||||
break;
|
||||
case T30_EOM:
|
||||
case T30_PRI_EOM:
|
||||
case T30_EOM:
|
||||
case T30_EOS:
|
||||
tx_end_page(s);
|
||||
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);
|
||||
return_to_phase_b(s, FALSE);
|
||||
break;
|
||||
case T30_EOP:
|
||||
case T30_PRI_EOP:
|
||||
case T30_EOP:
|
||||
tx_end_page(s);
|
||||
if (s->phase_d_handler)
|
||||
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;
|
||||
case T30_RTP:
|
||||
#if 0
|
||||
s->rtp_events++;
|
||||
#endif
|
||||
switch (s->next_tx_step)
|
||||
{
|
||||
case T30_MPS:
|
||||
case T30_PRI_MPS:
|
||||
case T30_MPS:
|
||||
tx_end_page(s);
|
||||
if (s->phase_d_handler)
|
||||
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);
|
||||
restart_sending_document(s);
|
||||
break;
|
||||
case T30_EOM:
|
||||
case T30_PRI_EOM:
|
||||
case T30_EOM:
|
||||
case T30_EOS:
|
||||
tx_end_page(s);
|
||||
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 */
|
||||
return_to_phase_b(s, TRUE);
|
||||
break;
|
||||
case T30_EOP:
|
||||
case T30_PRI_EOP:
|
||||
case T30_EOP:
|
||||
tx_end_page(s);
|
||||
if (s->phase_d_handler)
|
||||
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;
|
||||
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:
|
||||
#if 0
|
||||
s->rtn_events++;
|
||||
#endif
|
||||
switch (s->next_tx_step)
|
||||
{
|
||||
case T30_MPS:
|
||||
case T30_PRI_MPS:
|
||||
case T30_MPS:
|
||||
s->retries = 0;
|
||||
if (s->phase_d_handler)
|
||||
s->phase_d_handler(s, s->phase_d_user_data, fcf);
|
||||
#if 0
|
||||
if (!s->retransmit_capable)
|
||||
#endif
|
||||
{
|
||||
/* Send the next page, regardless of the problem with the current one. */
|
||||
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);
|
||||
restart_sending_document(s);
|
||||
break;
|
||||
case T30_EOM:
|
||||
case T30_PRI_EOM:
|
||||
case T30_EOM:
|
||||
case T30_EOS:
|
||||
s->retries = 0;
|
||||
if (s->phase_d_handler)
|
||||
s->phase_d_handler(s, s->phase_d_user_data, fcf);
|
||||
#if 0
|
||||
if (s->retransmit_capable)
|
||||
{
|
||||
/* Wait for DIS */
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
return_to_phase_b(s, TRUE);
|
||||
}
|
||||
break;
|
||||
case T30_EOP:
|
||||
case T30_PRI_EOP:
|
||||
case T30_EOP:
|
||||
s->retries = 0;
|
||||
if (s->phase_d_handler)
|
||||
s->phase_d_handler(s, s->phase_d_user_data, fcf);
|
||||
#if 0
|
||||
if (s->retransmit_capable)
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
send_dcn(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:
|
||||
switch (s->next_tx_step)
|
||||
{
|
||||
case T30_MPS:
|
||||
case T30_PRI_MPS:
|
||||
case T30_EOM:
|
||||
case T30_PRI_EOM:
|
||||
case T30_MPS:
|
||||
case T30_EOM:
|
||||
case T30_EOS:
|
||||
/* Unexpected DCN after EOM, EOS or MPS sequence */
|
||||
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");
|
||||
switch (s->next_tx_step)
|
||||
{
|
||||
case T30_MPS:
|
||||
case T30_PRI_MPS:
|
||||
case T30_MPS:
|
||||
tx_end_page(s);
|
||||
if (s->phase_d_handler)
|
||||
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);
|
||||
}
|
||||
break;
|
||||
case T30_EOM:
|
||||
case T30_PRI_EOM:
|
||||
case T30_EOM:
|
||||
case T30_EOS:
|
||||
tx_end_page(s);
|
||||
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);
|
||||
return_to_phase_b(s, FALSE);
|
||||
break;
|
||||
case T30_EOP:
|
||||
case T30_PRI_EOP:
|
||||
case T30_EOP:
|
||||
tx_end_page(s);
|
||||
if (s->phase_d_handler)
|
||||
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;
|
||||
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:
|
||||
s->retries = 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");
|
||||
switch (s->next_tx_step)
|
||||
{
|
||||
case T30_MPS:
|
||||
case T30_PRI_MPS:
|
||||
case T30_MPS:
|
||||
tx_end_page(s);
|
||||
if (s->phase_d_handler)
|
||||
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);
|
||||
}
|
||||
break;
|
||||
case T30_EOM:
|
||||
case T30_PRI_EOM:
|
||||
case T30_EOM:
|
||||
case T30_EOS:
|
||||
tx_end_page(s);
|
||||
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);
|
||||
return_to_phase_b(s, FALSE);
|
||||
break;
|
||||
case T30_EOP:
|
||||
case T30_PRI_EOP:
|
||||
case T30_EOP:
|
||||
tx_end_page(s);
|
||||
if (s->phase_d_handler)
|
||||
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);
|
||||
send_rr(s);
|
||||
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:
|
||||
process_rx_ppr(s, msg, len);
|
||||
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:
|
||||
process_rx_fnv(s, msg, len);
|
||||
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:
|
||||
/* We don't know what to do with this. */
|
||||
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;
|
||||
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:
|
||||
s->retries = 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");
|
||||
switch (s->next_tx_step)
|
||||
{
|
||||
case T30_MPS:
|
||||
case T30_PRI_MPS:
|
||||
case T30_MPS:
|
||||
tx_end_page(s);
|
||||
if (s->phase_d_handler)
|
||||
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);
|
||||
}
|
||||
break;
|
||||
case T30_EOM:
|
||||
case T30_PRI_EOM:
|
||||
case T30_EOM:
|
||||
case T30_EOS:
|
||||
tx_end_page(s);
|
||||
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);
|
||||
return_to_phase_b(s, FALSE);
|
||||
break;
|
||||
case T30_EOP:
|
||||
case T30_PRI_EOP:
|
||||
case T30_EOP:
|
||||
tx_end_page(s);
|
||||
if (s->phase_d_handler)
|
||||
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);
|
||||
send_rr(s);
|
||||
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:
|
||||
s->current_status = T30_ERR_RX_DCNRRD;
|
||||
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:
|
||||
process_rx_fnv(s, msg, len);
|
||||
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:
|
||||
/* We don't know what to do with this. */
|
||||
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);
|
||||
send_rr(s);
|
||||
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:
|
||||
/* TODO: Continue with the next message if MPS or EOM? */
|
||||
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:
|
||||
process_rx_fnv(s, msg, len);
|
||||
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:
|
||||
/* We don't know what to do with this. */
|
||||
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);
|
||||
send_rr(s);
|
||||
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:
|
||||
/* TODO: Continue with the next message if MPS or EOM? */
|
||||
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:
|
||||
process_rx_fnv(s, msg, len);
|
||||
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:
|
||||
/* We don't know what to do with this. */
|
||||
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
|
||||
occur at the end of message sequences. They should, therefore have
|
||||
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)
|
||||
{
|
||||
@ -5082,11 +5016,11 @@ static void timer_t2_expired(t30_state_t *s)
|
||||
case T30_STATE_F_POST_RCP_MCF:
|
||||
switch (s->next_rx_step)
|
||||
{
|
||||
case T30_EOM:
|
||||
case T30_PRI_EOM:
|
||||
case T30_EOM:
|
||||
case T30_EOS:
|
||||
/* 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));
|
||||
set_phase(s, T30_PHASE_B_TX);
|
||||
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_NON_ECM:
|
||||
/* 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;
|
||||
break;
|
||||
#if 0
|
||||
@ -5873,8 +5809,8 @@ SPAN_DECLARE(void) t30_front_end_status(void *user_data, int status)
|
||||
{
|
||||
switch (s->next_rx_step)
|
||||
{
|
||||
case T30_MPS:
|
||||
case T30_PRI_MPS:
|
||||
case T30_MPS:
|
||||
/* We should now start to get another page */
|
||||
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);
|
||||
break;
|
||||
case T30_EOM:
|
||||
case T30_PRI_EOM:
|
||||
case T30_EOM:
|
||||
case T30_EOS:
|
||||
/* See if we get something back, before moving to phase B. */
|
||||
timer_t2_start(s);
|
||||
set_phase(s, T30_PHASE_D_RX);
|
||||
break;
|
||||
case T30_EOP:
|
||||
case T30_PRI_EOP:
|
||||
case T30_EOP:
|
||||
/* Wait for a DCN. */
|
||||
set_phase(s, T30_PHASE_D_RX);
|
||||
timer_t4_start(s);
|
||||
@ -6256,6 +6192,12 @@ SPAN_DECLARE(void) t30_local_interrupt_request(t30_state_t *s, int state)
|
||||
}
|
||||
/*- 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)
|
||||
{
|
||||
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 */
|
||||
s->rx_page_number = 0;
|
||||
s->tx_page_number = 0;
|
||||
#if 0
|
||||
s->rtn_events = 0;
|
||||
s->rtp_events = 0;
|
||||
#endif
|
||||
s->local_interrupt_pending = FALSE;
|
||||
s->far_end_detected = FALSE;
|
||||
s->timer_t0_t1 = ms_to_samples(DEFAULT_TIMER_T0);
|
||||
if (s->calling_party)
|
||||
|
@ -2602,7 +2602,9 @@ SPAN_DECLARE(t31_state_t *) t31_init(t31_state_t *s,
|
||||
t38_tx_packet_handler_t *tx_t38_packet_handler,
|
||||
void *tx_t38_packet_user_data)
|
||||
{
|
||||
#if 0
|
||||
v8_parms_t v8_parms;
|
||||
#endif
|
||||
int alloced;
|
||||
|
||||
if (at_tx_handler == NULL || modem_control_handler == NULL)
|
||||
|
@ -426,7 +426,6 @@ static int set_next_tx_type(t38_gateway_state_t *s)
|
||||
t38_gateway_hdlc_state_t *u;
|
||||
|
||||
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);
|
||||
if (t->next_tx_handler)
|
||||
{
|
||||
@ -447,6 +446,7 @@ static int set_next_tx_type(t38_gateway_state_t *s)
|
||||
return TRUE;
|
||||
}
|
||||
/*endif*/
|
||||
u = &s->core.hdlc_to_modem;
|
||||
if (u->in == u->out)
|
||||
return FALSE;
|
||||
/*endif*/
|
||||
@ -1057,7 +1057,9 @@ 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)
|
||||
{
|
||||
t38_gateway_state_t *s;
|
||||
|
||||
t38_gateway_hdlc_state_t *u;
|
||||
int immediate;
|
||||
|
||||
s = (t38_gateway_state_t *) user_data;
|
||||
|
||||
t38_non_ecm_buffer_report_input_status(&s->core.non_ecm_to_modem, &s->logging);
|
||||
@ -1067,25 +1069,50 @@ static int process_rx_indicator(t38_core_state_t *t, void *user_data, int indica
|
||||
return 0;
|
||||
}
|
||||
/*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)
|
||||
s->core.hdlc_to_modem.in = 0;
|
||||
if (++u->in >= T38_TX_HDLC_BUFS)
|
||||
u->in = 0;
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in].contents = (indicator | FLAG_INDICATOR);
|
||||
if (++s->core.hdlc_to_modem.in >= T38_TX_HDLC_BUFS)
|
||||
s->core.hdlc_to_modem.in = 0;
|
||||
u->buf[u->in].contents = (indicator | FLAG_INDICATOR);
|
||||
if (++u->in >= T38_TX_HDLC_BUFS)
|
||||
u->in = 0;
|
||||
/*endif*/
|
||||
t38_non_ecm_buffer_set_mode(&s->core.non_ecm_to_modem, s->core.image_data_mode, s->core.min_row_bits);
|
||||
|
||||
span_log(&s->logging,
|
||||
SPAN_LOG_FLOW,
|
||||
"Queued change - (%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));
|
||||
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_FLOW,
|
||||
"Queued change - (%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));
|
||||
}
|
||||
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
|
||||
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;
|
||||
break;
|
||||
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;
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
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;
|
||||
break;
|
||||
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];
|
||||
/* 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
|
||||
@ -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.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;
|
||||
t38_non_ecm_buffer_init(&s->core.non_ecm_to_modem, FALSE, 0);
|
||||
restart_rx_modem(s);
|
||||
s->core.timed_mode = TIMED_MODE_STARTUP;
|
||||
s->core.samples_to_timeout = 1;
|
||||
|
@ -111,7 +111,7 @@ static const struct dtmf_to_ascii_s dtmf_to_ascii[] =
|
||||
{"##8", 'W'},
|
||||
{"##9", 'Z'},
|
||||
{"##0", ' '},
|
||||
#if defined(WIN32) || ( defined(__SVR4) && defined (__sun))
|
||||
#if defined(WIN32) || ( defined(__SVR4) && defined (__sun))
|
||||
{"#*1", 'X'}, // (Note 1) 111 1011
|
||||
{"#*2", 'X'}, // (Note 1) 111 1100
|
||||
{"#*3", 'X'}, // (Note 1) 111 1101
|
||||
|
@ -103,6 +103,7 @@ SWITCH_BEGIN_EXTERN_C
|
||||
switch_caller_profile_flag_t flags;
|
||||
struct switch_caller_profile *originator_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_channel_timetable *times;
|
||||
struct switch_caller_extension *caller_extension;
|
||||
|
@ -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);
|
||||
|
||||
/*!
|
||||
\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
|
||||
|
@ -37,6 +37,7 @@
|
||||
#define CC_AGENT_TYPE_UUID_STANDBY "uuid-standby"
|
||||
#define CC_SQLITE_DB_NAME "callcenter"
|
||||
|
||||
#define CC_MAX_TIME_DIFF_CHECK 5
|
||||
/* TODO
|
||||
drop caller if no agent login
|
||||
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";
|
||||
|
||||
struct cc_status_table {
|
||||
const char *name;
|
||||
int status;
|
||||
};
|
||||
|
||||
struct cc_state_table {
|
||||
const char *name;
|
||||
int state;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
CC_STATUS_SUCCESS,
|
||||
CC_STATUS_FALSE,
|
||||
@ -77,12 +88,7 @@ typedef enum {
|
||||
CC_TIER_STATE_STANDBY = 5
|
||||
} cc_tier_state_t;
|
||||
|
||||
struct cc_tier_state_table {
|
||||
const char *name;
|
||||
cc_tier_state_t state;
|
||||
};
|
||||
|
||||
static struct cc_tier_state_table STATE_CHART[] = {
|
||||
static struct cc_state_table STATE_CHART[] = {
|
||||
{"Unknown", CC_TIER_STATE_UNKNOWN},
|
||||
{"No Answer", CC_TIER_STATE_NO_ANSWER},
|
||||
{"Ready", CC_TIER_STATE_READY},
|
||||
@ -101,12 +107,7 @@ typedef enum {
|
||||
CC_AGENT_STATUS_ON_BREAK = 4
|
||||
} cc_agent_status_t;
|
||||
|
||||
struct cc_agent_status_table {
|
||||
const char *name;
|
||||
cc_agent_status_t status;
|
||||
};
|
||||
|
||||
static struct cc_agent_status_table AGENT_STATUS_CHART[] = {
|
||||
static struct cc_status_table AGENT_STATUS_CHART[] = {
|
||||
{"Unknown", CC_AGENT_STATUS_UNKNOWN},
|
||||
{"Logged Out", CC_AGENT_STATUS_LOGGED_OUT},
|
||||
{"Available", CC_AGENT_STATUS_AVAILABLE},
|
||||
@ -124,12 +125,7 @@ typedef enum {
|
||||
CC_AGENT_STATE_IDLE = 4
|
||||
} cc_agent_state_t;
|
||||
|
||||
struct cc_agent_state_table {
|
||||
const char *name;
|
||||
cc_agent_state_t state;
|
||||
};
|
||||
|
||||
static struct cc_agent_state_table AGENT_STATE_CHART[] = {
|
||||
static struct cc_state_table AGENT_STATE_CHART[] = {
|
||||
{"Unknown", CC_AGENT_STATE_UNKNOWN},
|
||||
{"Waiting", CC_AGENT_STATE_WAITING},
|
||||
{"Receiving", CC_AGENT_STATE_RECEIVING},
|
||||
@ -147,12 +143,7 @@ typedef enum {
|
||||
CC_MEMBER_STATE_ABANDONED = 4
|
||||
} cc_member_state_t;
|
||||
|
||||
struct cc_member_state_table {
|
||||
const char *name;
|
||||
cc_member_state_t state;
|
||||
};
|
||||
|
||||
static struct cc_member_state_table MEMBER_STATE_CHART[] = {
|
||||
static struct cc_state_table MEMBER_STATE_CHART[] = {
|
||||
{"Unknown", CC_MEMBER_STATE_UNKNOWN},
|
||||
{"Waiting", CC_MEMBER_STATE_WAITING},
|
||||
{"Trying", CC_MEMBER_STATE_TRYING},
|
||||
@ -162,10 +153,24 @@ static struct cc_member_state_table MEMBER_STATE_CHART[] = {
|
||||
|
||||
};
|
||||
|
||||
/*static char queues_sql[] =
|
||||
"CREATE TABLE queues (\n"
|
||||
" name VARCHAR(255)\n" ");\n";
|
||||
*/
|
||||
struct cc_member_cancel_reason_table {
|
||||
const char *name;
|
||||
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[] =
|
||||
"CREATE TABLE members (\n"
|
||||
" queue VARCHAR(255),\n"
|
||||
@ -222,7 +227,6 @@ static char agents_sql[] =
|
||||
" ready_time INTEGER NOT NULL DEFAULT 0\n"
|
||||
");\n";
|
||||
|
||||
|
||||
static char tiers_sql[] =
|
||||
"CREATE TABLE tiers (\n"
|
||||
" queue VARCHAR(255),\n"
|
||||
@ -247,7 +251,7 @@ const char * cc_tier_state2str(cc_tier_state_t state)
|
||||
uint8_t x;
|
||||
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) {
|
||||
str = STATE_CHART[x].name;
|
||||
break;
|
||||
@ -262,7 +266,7 @@ cc_tier_state_t cc_tier_str2state(const char *str)
|
||||
uint8_t x;
|
||||
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)) {
|
||||
state = STATE_CHART[x].state;
|
||||
break;
|
||||
@ -271,12 +275,41 @@ cc_tier_state_t cc_tier_str2state(const char *str)
|
||||
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)
|
||||
{
|
||||
uint8_t x;
|
||||
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) {
|
||||
str = AGENT_STATUS_CHART[x].name;
|
||||
break;
|
||||
@ -291,7 +324,7 @@ cc_agent_status_t cc_agent_str2status(const char *str)
|
||||
uint8_t x;
|
||||
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)) {
|
||||
status = AGENT_STATUS_CHART[x].status;
|
||||
break;
|
||||
@ -305,7 +338,7 @@ const char * cc_agent_state2str(cc_agent_state_t state)
|
||||
uint8_t x;
|
||||
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) {
|
||||
str = AGENT_STATE_CHART[x].name;
|
||||
break;
|
||||
@ -320,7 +353,7 @@ cc_agent_state_t cc_agent_str2state(const char *str)
|
||||
uint8_t x;
|
||||
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)) {
|
||||
state = AGENT_STATE_CHART[x].state;
|
||||
break;
|
||||
@ -334,7 +367,7 @@ const char * cc_member_state2str(cc_member_state_t state)
|
||||
uint8_t x;
|
||||
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) {
|
||||
str = MEMBER_STATE_CHART[x].name;
|
||||
break;
|
||||
@ -349,7 +382,7 @@ cc_member_state_t cc_member_str2state(const char *str)
|
||||
uint8_t x;
|
||||
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)) {
|
||||
state = MEMBER_STATE_CHART[x].state;
|
||||
break;
|
||||
@ -384,19 +417,27 @@ struct cc_queue {
|
||||
char *moh;
|
||||
char *record_template;
|
||||
char *time_base_score;
|
||||
|
||||
switch_bool_t tier_rules_apply;
|
||||
uint32_t tier_rule_wait_second;
|
||||
switch_bool_t tier_rule_wait_multiply_level;
|
||||
switch_bool_t tier_rule_no_agent_no_wait;
|
||||
|
||||
uint32_t discard_abandoned_after;
|
||||
switch_bool_t abandoned_resume_allowed;
|
||||
|
||||
uint32_t max_wait_time;
|
||||
uint32_t max_wait_time_with_no_agent;
|
||||
|
||||
switch_mutex_t *mutex;
|
||||
|
||||
switch_thread_rwlock_t *rwlock;
|
||||
switch_memory_pool_t *pool;
|
||||
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_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++], "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++], "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-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++], "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);
|
||||
|
||||
return queue;
|
||||
@ -646,6 +691,9 @@ static cc_queue_t *load_queue(const char *queue_name)
|
||||
switch_thread_rwlock_create(&queue->rwlock, pool);
|
||||
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())) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot open DB!\n");
|
||||
goto end;
|
||||
@ -702,7 +750,7 @@ static cc_queue_t *get_queue(const char *queue_name)
|
||||
|
||||
struct call_helper {
|
||||
const char *member_uuid;
|
||||
const char *queue;
|
||||
const char *queue_name;
|
||||
const char *queue_strategy;
|
||||
const char *member_joined_epoch;
|
||||
const char *member_caller_name;
|
||||
@ -744,7 +792,7 @@ int cc_queue_count(const char *queue)
|
||||
count = atoi(res);
|
||||
|
||||
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-Count", res);
|
||||
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;
|
||||
|
||||
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-Agent-Status", res);
|
||||
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;
|
||||
|
||||
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-Agent-Status", value);
|
||||
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;
|
||||
|
||||
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-Agent-State", value);
|
||||
switch_event_fire(&event);
|
||||
@ -1118,13 +1166,13 @@ done:
|
||||
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;
|
||||
char *sql;
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Deleted tier Agent %s in Queue %s\n", agent, queue);
|
||||
sql = switch_mprintf("DELETE FROM tiers WHERE queue = '%q' AND agent = '%q';", queue, agent);
|
||||
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_name, agent);
|
||||
cc_execute_sql(NULL, sql, NULL);
|
||||
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)) {
|
||||
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_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");
|
||||
|
||||
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_event_t *event;
|
||||
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 */
|
||||
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");
|
||||
@ -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) {
|
||||
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-Agent", h->agent_name);
|
||||
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);
|
||||
|
||||
/* Change the agents Status in the tiers */
|
||||
sql = switch_mprintf("UPDATE tiers SET state = '%q' WHERE agent = '%q' AND queue = '%q'",
|
||||
cc_tier_state2str(CC_TIER_STATE_ACTIVE_INBOUND), h->agent_name, h->queue);
|
||||
cc_execute_sql(NULL, sql, NULL);
|
||||
switch_safe_free(sql);
|
||||
|
||||
cc_tier_update("state", cc_tier_state2str(CC_TIER_STATE_ACTIVE_INBOUND), h->queue_name, 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 */
|
||||
@ -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",
|
||||
h->agent_name, h->member_caller_name, h->member_caller_number, h->queue, (h->record_template?" (Recorded)":""));
|
||||
switch_ivr_uuid_bridge(switch_core_session_get_uuid(agent_session), h->member_uuid);
|
||||
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_name, (h->record_template?" (Recorded)":""));
|
||||
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 */
|
||||
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) {
|
||||
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-Agent", h->agent_name);
|
||||
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 */
|
||||
/* 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';"
|
||||
, (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);
|
||||
switch_safe_free(sql);
|
||||
|
||||
@ -1455,7 +1511,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
|
||||
/* Caller off event */
|
||||
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
|
||||
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-Cause", "Terminated");
|
||||
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-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-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-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_fire(&event);
|
||||
}
|
||||
|
||||
@ -1529,8 +1587,8 @@ done:
|
||||
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 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(CC_TIER_STATE_READY), h->agent_name, h->queue, cc_tier_state2str(CC_TIER_STATE_STANDBY));
|
||||
, 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_name, cc_tier_state2str(CC_TIER_STATE_STANDBY));
|
||||
cc_execute_sql(NULL, sql, NULL);
|
||||
switch_safe_free(sql);
|
||||
|
||||
@ -1558,7 +1616,7 @@ done:
|
||||
}
|
||||
|
||||
struct agent_callback {
|
||||
const char *queue;
|
||||
const char *queue_name;
|
||||
const char *system;
|
||||
const char *uuid;
|
||||
const char *caller_number;
|
||||
@ -1570,6 +1628,7 @@ struct agent_callback {
|
||||
uint32_t tier_rule_wait_second;
|
||||
switch_bool_t tier_rule_wait_multiply_level;
|
||||
switch_bool_t tier_rule_no_agent_no_wait;
|
||||
switch_bool_t agent_found;
|
||||
|
||||
int tier;
|
||||
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;
|
||||
|
||||
cbt->agent_found = SWITCH_TRUE;
|
||||
|
||||
/* 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) {
|
||||
@ -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_caller_name = switch_core_strdup(h->pool, cbt->caller_name);
|
||||
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->no_answer_count = atoi(argv[4]);
|
||||
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(
|
||||
"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';",
|
||||
cc_tier_state2str(CC_TIER_STATE_OFFERING), h->agent_name, h->queue,
|
||||
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_OFFERING), h->agent_name, h->queue_name,
|
||||
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);
|
||||
switch_safe_free(sql);
|
||||
|
||||
@ -1772,7 +1833,7 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
|
||||
switch_safe_free(sql);
|
||||
}
|
||||
/* Skip this member */
|
||||
return 0;
|
||||
goto end;
|
||||
}
|
||||
memset(&cbt, 0, sizeof(cbt));
|
||||
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_name = argv[3];
|
||||
cbt.joined_epoch = argv[4];
|
||||
cbt.queue = argv[0];
|
||||
cbt.queue_name = argv[0];
|
||||
cbt.strategy = queue_strategy;
|
||||
cbt.record_template = queue_record_template;
|
||||
cbt.agent_found = SWITCH_FALSE;
|
||||
|
||||
if (!strcasecmp(queue->strategy, "longest-idle-agent")) {
|
||||
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_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:
|
||||
switch_safe_free(queue_name);
|
||||
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);
|
||||
}
|
||||
|
||||
struct member_helper {
|
||||
const char *uuid;
|
||||
struct member_thread_helper {
|
||||
const char *member_uuid;
|
||||
const char *queue_name;
|
||||
switch_time_t t_member_called;
|
||||
cc_member_cancel_reason_t member_cancel_reason;
|
||||
|
||||
int running;
|
||||
switch_memory_pool_t *pool;
|
||||
};
|
||||
|
||||
void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj)
|
||||
{
|
||||
struct member_helper *m = (struct member_helper *) obj;
|
||||
switch_core_session_t *member_session = switch_core_session_locate(m->uuid);
|
||||
switch_channel_t *channel = NULL;
|
||||
struct member_thread_helper *m = (struct member_thread_helper *) obj;
|
||||
switch_core_session_t *member_session = switch_core_session_locate(m->member_uuid);
|
||||
switch_channel_t *member_channel = NULL;
|
||||
|
||||
switch_mutex_lock(globals.mutex);
|
||||
globals.threads++;
|
||||
switch_mutex_unlock(globals.mutex);
|
||||
|
||||
if (member_session) {
|
||||
channel = switch_core_session_get_channel(member_session);
|
||||
member_channel = switch_core_session_get_channel(member_session);
|
||||
} else {
|
||||
switch_core_destroy_memory_pool(&m->pool);
|
||||
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 */
|
||||
/* 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 */
|
||||
/* Play Announcement in order */
|
||||
switch_yield(100000);
|
||||
|
||||
queue_rwunlock(queue);
|
||||
|
||||
switch_yield(500000);
|
||||
}
|
||||
|
||||
switch_core_session_rwunlock(member_session);
|
||||
switch_core_destroy_memory_pool(&m->pool);
|
||||
|
||||
@ -1962,26 +2063,27 @@ SWITCH_STANDARD_APP(callcenter_function)
|
||||
char *mydata = NULL;
|
||||
cc_queue_t *queue = 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 *uuid = switch_core_session_get_uuid(session);
|
||||
switch_input_args_t args = { 0 };
|
||||
struct member_helper *h = NULL;
|
||||
char *member_uuid = switch_core_session_get_uuid(member_session);
|
||||
struct member_thread_helper *h = NULL;
|
||||
switch_thread_t *thread;
|
||||
switch_threadattr_t *thd_attr = NULL;
|
||||
switch_memory_pool_t *pool;
|
||||
int cc_base_score_int = 0;
|
||||
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_base_score = switch_channel_get_variable(member_channel, "cc_base_score");
|
||||
int cc_base_score_int = 0;
|
||||
const char *cur_moh = NULL;
|
||||
char start_epoch[64];
|
||||
switch_event_t *event;
|
||||
switch_time_t t_member_called = switch_epoch_time_now(NULL);
|
||||
long abandoned_epoch = 0;
|
||||
const char *agent_uuid = NULL;
|
||||
|
||||
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])));
|
||||
} else {
|
||||
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);
|
||||
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) {
|
||||
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) {
|
||||
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_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-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
|
||||
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)"
|
||||
" VALUES('%q','single_box','%q','%q','%ld','%d','%d','%q','%q','%q','','%q')",
|
||||
queue_name,
|
||||
uuid,
|
||||
member_uuid,
|
||||
start_epoch,
|
||||
(long) switch_epoch_time_now(NULL),
|
||||
cc_base_score_int,
|
||||
@ -2060,12 +2162,12 @@ SWITCH_STANDARD_APP(callcenter_function)
|
||||
char res[256];
|
||||
/* 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'",
|
||||
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);
|
||||
switch_safe_free(sql);
|
||||
|
||||
/* 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));
|
||||
switch_safe_free(sql);
|
||||
|
||||
@ -2083,9 +2185,14 @@ SWITCH_STANDARD_APP(callcenter_function)
|
||||
/* Start Thread that will playback different prompt to the channel */
|
||||
switch_core_new_memory_pool(&pool);
|
||||
h = switch_core_alloc(pool, sizeof(*h));
|
||||
|
||||
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;
|
||||
|
||||
switch_threadattr_create(&thd_attr, h->pool);
|
||||
switch_threadattr_detach_set(thd_attr, 1);
|
||||
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
|
||||
@ -2095,16 +2202,37 @@ SWITCH_STANDARD_APP(callcenter_function)
|
||||
/* TODO Add DTMF callback support */
|
||||
/* TODO add MOH infitite loop */
|
||||
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 {
|
||||
cur_moh = switch_core_session_strdup(session, queue->moh);
|
||||
cur_moh = switch_core_session_strdup(member_session, queue->moh);
|
||||
}
|
||||
queue_rwunlock(queue);
|
||||
|
||||
if (cur_moh) {
|
||||
switch_ivr_play_file(session, NULL, cur_moh, &args);
|
||||
} else {
|
||||
switch_ivr_collect_digits_callback(session, &args, 0, 0);
|
||||
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) {
|
||||
switch_status_t status = switch_ivr_play_file(member_session, NULL, cur_moh, &args);
|
||||
|
||||
if (!SWITCH_READ_ACCEPTABLE(status)) {
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
switch_ivr_collect_digits_callback(session, &args, 0, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Stop Member Thread */
|
||||
@ -2114,33 +2242,42 @@ SWITCH_STANDARD_APP(callcenter_function)
|
||||
|
||||
/* 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 */
|
||||
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'",
|
||||
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);
|
||||
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) {
|
||||
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(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_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", uuid);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Member \"%s\" <%s> exit queue %s due to %s\n",
|
||||
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-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
|
||||
/* 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_cause", "%s", cc_member_cancel_reason2str(h->member_cancel_reason));
|
||||
|
||||
|
||||
/* Send Event with queue count */
|
||||
cc_queue_count(queue_name);
|
||||
|
||||
} 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'",
|
||||
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);
|
||||
switch_safe_free(sql);
|
||||
|
||||
@ -2516,7 +2653,7 @@ SWITCH_STANDARD_API(cc_config_api_function)
|
||||
stream->write_function(stream, "%d\n", atoi(res));
|
||||
|
||||
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-Count", res);
|
||||
switch_event_fire(&event);
|
||||
|
@ -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,
|
||||
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);
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1259,6 +1260,10 @@ static switch_status_t channel_on_destroy(switch_core_session_t *session)
|
||||
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);
|
||||
|
||||
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)) {
|
||||
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)) {
|
||||
ldl_session_terminate(tech_pvt->dlsession);
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_TERM);
|
||||
}
|
||||
ldl_session_destroy(&tech_pvt->dlsession);
|
||||
|
||||
if (!switch_test_flag(tech_pvt, TFLAG_TERM) && tech_pvt->dlsession) {
|
||||
ldl_session_terminate(tech_pvt->dlsession);
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_TERM);
|
||||
}
|
||||
|
||||
|
||||
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_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)) {
|
||||
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;
|
||||
channel = switch_core_session_get_channel(session);
|
||||
switch_core_session_set_private(session, tech_pvt);
|
||||
tech_pvt->dlsession = dlsession;
|
||||
|
||||
tech_pvt->session = session;
|
||||
tech_pvt->codec_index = -1;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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 */
|
||||
if (profile->context && !strcmp(profile->context, "_auto_")) {
|
||||
context = profile->name;
|
||||
@ -3047,7 +3062,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
|
||||
|
||||
switch_safe_free(tmp);
|
||||
}
|
||||
|
||||
|
||||
if (!tech_pvt->caller_profile) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||
"Creating an identity for %s %s <%s> %s\n", ldl_session_get_id(dlsession), cid_name, cid_num, exten);
|
||||
@ -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));
|
||||
ldl_session_set_private(dlsession, session);
|
||||
tech_pvt->dlsession = dlsession;
|
||||
|
||||
switch_channel_set_name(channel, "DingaLing/new");
|
||||
switch_channel_set_state(channel, CS_INIT);
|
||||
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;
|
||||
@ -3259,7 +3275,15 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
|
||||
if (profile->acl_count) {
|
||||
for (x = 0; x < len; x++) {
|
||||
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++) {
|
||||
|
||||
if (switch_check_network_list_ip(candidates[x].address, profile->acl[y])) {
|
||||
choice = x;
|
||||
ok = 1;
|
||||
@ -3268,7 +3292,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
|
||||
if (ok) {
|
||||
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]);
|
||||
break;
|
||||
goto end_candidates;
|
||||
} else {
|
||||
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]);
|
||||
@ -3311,6 +3335,8 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
|
||||
}
|
||||
}
|
||||
|
||||
end_candidates:
|
||||
|
||||
if (ok) {
|
||||
ldl_payload_t payloads[5];
|
||||
|
||||
|
@ -1233,7 +1233,6 @@ static void walk_listeners(skinny_listener_callback_func_t callback, void *pvt)
|
||||
switch_hash_index_t *hi;
|
||||
void *val;
|
||||
skinny_profile_t *profile;
|
||||
listener_t *l;
|
||||
|
||||
/* walk listeners */
|
||||
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);
|
||||
profile = (skinny_profile_t *) val;
|
||||
|
||||
switch_mutex_lock(profile->listener_mutex);
|
||||
for (l = profile->listeners; l; l = l->next) {
|
||||
callback(l, pvt);
|
||||
}
|
||||
switch_mutex_unlock(profile->listener_mutex);
|
||||
profile_walk_listeners(profile, callback, pvt);
|
||||
}
|
||||
switch_mutex_unlock(globals.mutex);
|
||||
}
|
||||
@ -1509,6 +1504,7 @@ static void *SWITCH_THREAD_FUNC skinny_profile_run(switch_thread_t *thread, void
|
||||
|
||||
new_socket:
|
||||
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);
|
||||
if (rv)
|
||||
goto fail;
|
||||
@ -1546,8 +1542,10 @@ new_socket:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting Down\n");
|
||||
goto end;
|
||||
} else if (switch_test_flag(profile, PFLAG_RESPAWN)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Creating a new socket\n");
|
||||
switch_clear_flag_locked(profile, PFLAG_RESPAWN);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Respawn in progress. Waiting for socket to close.\n");
|
||||
while (profile->sock) {
|
||||
switch_cond_next();
|
||||
}
|
||||
goto new_socket;
|
||||
} else {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (!var)
|
||||
@ -1633,9 +1643,15 @@ switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, c
|
||||
if (!strcasecmp(var, "domain")) {
|
||||
profile->domain = switch_core_strdup(profile->pool, val);
|
||||
} else if (!strcasecmp(var, "ip")) {
|
||||
profile->ip = switch_core_strdup(profile->pool, val);
|
||||
if (!profile->ip || strcmp(val, profile->ip)) {
|
||||
profile->ip = switch_core_strdup(profile->pool, val);
|
||||
switch_set_flag_locked(profile, PFLAG_SHOULD_RESPAWN);
|
||||
}
|
||||
} else if (!strcasecmp(var, "port")) {
|
||||
profile->port = atoi(val);
|
||||
if (atoi(val) != profile->port) {
|
||||
profile->port = atoi(val);
|
||||
switch_set_flag_locked(profile, PFLAG_SHOULD_RESPAWN);
|
||||
}
|
||||
} else if (!strcasecmp(var, "patterns-dialplan")) {
|
||||
profile->patterns_dialplan = switch_core_strdup(profile->pool, val);
|
||||
} 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 {
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
char *cf = "skinny.conf";
|
||||
@ -1692,8 +1714,7 @@ static switch_status_t load_skinny_config(void)
|
||||
if ((xprofiles = switch_xml_child(xcfg, "profiles"))) {
|
||||
for (xprofile = switch_xml_child(xprofiles, "profile"); xprofile; xprofile = xprofile->next) {
|
||||
char *profile_name = (char *) switch_xml_attr_soft(xprofile, "name");
|
||||
switch_xml_t xsettings;
|
||||
switch_xml_t xdevice_types;
|
||||
switch_xml_t xsettings, xdevice_types, xsoft_key_set_sets;
|
||||
if (zstr(profile_name)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"<profile> is missing name attribute\n");
|
||||
@ -1749,6 +1770,96 @@ static switch_status_t load_skinny_config(void)
|
||||
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 */
|
||||
switch_snprintf(dbname, sizeof(dbname), "skinny_%s", profile->name);
|
||||
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_active_lines", NULL, NULL);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
skinny_profile_respawn(profile, 0);
|
||||
|
||||
/* Register profile */
|
||||
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)) {
|
||||
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();
|
||||
|
||||
/* 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 */
|
||||
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 */
|
||||
}
|
||||
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;
|
||||
}
|
||||
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 */
|
||||
}
|
||||
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 */
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,8 @@ extern skinny_globals_t globals;
|
||||
|
||||
typedef enum {
|
||||
PFLAG_LISTENER_READY = (1 << 0),
|
||||
PFLAG_RESPAWN = (1 << 1),
|
||||
PFLAG_SHOULD_RESPAWN = (1 << 1),
|
||||
PFLAG_RESPAWN = (1 << 2),
|
||||
} profile_flag_t;
|
||||
|
||||
struct skinny_profile {
|
||||
@ -78,6 +79,7 @@ struct skinny_profile {
|
||||
char date_format[6];
|
||||
int debug;
|
||||
int auto_restart;
|
||||
switch_hash_t *soft_key_set_sets_hash;
|
||||
switch_hash_t *device_type_params_hash;
|
||||
/* db */
|
||||
char *dbname;
|
||||
@ -133,6 +135,7 @@ struct listener {
|
||||
uint32_t device_type;
|
||||
|
||||
char firmware_version[16];
|
||||
char *soft_key_set_set;
|
||||
|
||||
switch_socket_t *sock;
|
||||
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);
|
||||
#endif
|
||||
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 */
|
||||
@ -262,7 +268,6 @@ switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
|
||||
/* MODULE FUNCTIONS */
|
||||
/*****************************************************************************/
|
||||
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 */
|
||||
|
||||
|
@ -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);
|
||||
if(listener) {
|
||||
send_set_ringer(listener, skinny_str2ring_type(ring_type), skinny_str2ring_mode(ring_mode), 0, 0);
|
||||
stream->write_function(stream, "+OK\n");
|
||||
} else {
|
||||
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);
|
||||
if(listener) {
|
||||
send_set_lamp(listener, skinny_str2button(stimulus), atoi(instance), skinny_str2lamp_mode(lamp_mode));
|
||||
stream->write_function(stream, "+OK\n");
|
||||
} else {
|
||||
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);
|
||||
if(listener) {
|
||||
send_set_speaker_mode(listener, skinny_str2speaker_mode(speaker_mode));
|
||||
stream->write_function(stream, "+OK\n");
|
||||
} else {
|
||||
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);
|
||||
if(listener) {
|
||||
send_call_state(listener, skinny_str2call_state(call_state), atoi(line_instance), atoi(call_id));
|
||||
stream->write_function(stream, "+OK\n");
|
||||
} else {
|
||||
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);
|
||||
if(listener) {
|
||||
send_reset(listener, skinny_str2device_reset_type(reset_type));
|
||||
stream->write_function(stream, "+OK\n");
|
||||
} else {
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
|
@ -122,6 +122,9 @@ switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req)
|
||||
|
||||
while (listener_is_ready(listener)) {
|
||||
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) {
|
||||
/* We have nothing yet, get length header field */
|
||||
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) {
|
||||
switch_cond_next();
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ struct PACKED open_receive_channel_ack_message {
|
||||
/* SoftKeyEventMessage */
|
||||
#define SOFT_KEY_EVENT_MESSAGE 0x0026
|
||||
struct PACKED soft_key_event_message {
|
||||
uint32_t event;
|
||||
uint32_t event; /* See enum skinny_soft_key_event */
|
||||
uint32_t line_instance;
|
||||
uint32_t call_id;
|
||||
};
|
||||
|
@ -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");
|
||||
if (!strcasecmp(name, "skinny-firmware-version")) {
|
||||
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)
|
||||
{
|
||||
skinny_message_t *message;
|
||||
skinny_profile_t *profile;
|
||||
skinny_message_t *message = NULL;
|
||||
|
||||
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;
|
||||
|
||||
skinny_send_reply(listener, message);
|
||||
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);
|
||||
} 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 */
|
||||
send_select_soft_keys(listener, 0, 0, SKINNY_KEY_SET_ON_HOOK, 0xffff);
|
||||
|
@ -152,6 +152,32 @@ struct skinny_table SKINNY_BUTTONS[] = {
|
||||
SKINNY_DECLARE_ID2STR(skinny_button2str, SKINNY_BUTTONS, "Unknown")
|
||||
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[] = {
|
||||
{"Off", SKINNY_LAMP_OFF},
|
||||
{"On", SKINNY_LAMP_ON},
|
||||
|
@ -194,6 +194,10 @@ enum skinny_soft_key_event {
|
||||
SOFTKEY_DND = 0x13,
|
||||
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 {
|
||||
SKINNY_KEY_SET_ON_HOOK = 0,
|
||||
|
@ -697,7 +697,11 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
|
||||
|
||||
if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
|
||||
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)) {
|
||||
/* 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
|
||||
@ -1761,7 +1765,14 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
|
||||
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);
|
||||
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());
|
||||
}
|
||||
|
||||
tech_pvt->last_sent_callee_id_name = switch_core_session_strdup(tech_pvt->session, name);
|
||||
tech_pvt->last_sent_callee_id_number = switch_core_session_strdup(tech_pvt->session, number);
|
||||
@ -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)) {
|
||||
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) &&
|
||||
tech_pvt->early_sdp && strcmp(tech_pvt->early_sdp, tech_pvt->local_sdp_str)) {
|
||||
|
@ -4664,22 +4664,22 @@ void sofia_glue_tech_track(sofia_profile_t *profile, switch_core_session_t *sess
|
||||
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) {
|
||||
xml_cdr_text = switch_xml_toxml(cdr, SWITCH_FALSE);
|
||||
switch_xml_free(cdr);
|
||||
}
|
||||
|
||||
if (xml_cdr_text) {
|
||||
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);
|
||||
|
||||
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')",
|
||||
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)) {
|
||||
switch_event_t *event = NULL;
|
||||
|
||||
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, "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);
|
||||
sofia_set_flag(tech_pvt, TFLAG_TRACKED);
|
||||
|
||||
|
@ -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)) {
|
||||
switch_snprintf(sql, sizeof(sql), "select call_id,sip_user,sip_host,contact,status,rpid,"
|
||||
"expires,user_agent,server_user,server_host,profile_name"
|
||||
" from sip_registrations where (status like '%%AUTO-NAT%%' "
|
||||
"or status like '%%UDP-NAT%%') and hostname='%s'", mod_sofia_globals.hostname);
|
||||
" from sip_registrations where (status like '%%NAT%%' "
|
||||
"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);
|
||||
}
|
||||
@ -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);
|
||||
|
||||
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 "
|
||||
"(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;
|
||||
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);
|
||||
|
||||
if (!(sip->sip_contact && sip->sip_contact->m_url)) {
|
||||
|
@ -18,6 +18,10 @@
|
||||
%}
|
||||
|
||||
|
||||
/* Lua function typemap */
|
||||
%typemap(in,checkfn="lua_isfunction") SWIGLUA_FN
|
||||
%{ $1.L=L; $1.idx=$input; %}
|
||||
|
||||
|
||||
%ignore SwitchToMempool;
|
||||
%newobject EventConsumer::pop;
|
||||
@ -25,6 +29,7 @@
|
||||
%newobject CoreSession;
|
||||
%newobject Event;
|
||||
%newobject Stream;
|
||||
%newobject Dbh;
|
||||
|
||||
/**
|
||||
* tell swig to grok everything defined in these header files and
|
||||
@ -66,9 +71,18 @@ class Session : public CoreSession {
|
||||
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);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -308,3 +308,69 @@ switch_status_t Session::run_dtmf_callback(void *input, switch_input_type_t ityp
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -8,6 +8,16 @@ extern "C" {
|
||||
#include "mod_lua_extra.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 {
|
||||
class Session:public CoreSession {
|
||||
private:
|
||||
@ -41,5 +51,17 @@ namespace LUA {
|
||||
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
|
||||
|
@ -1,38 +1,38 @@
|
||||
--- mod_lua_wrap.cpp 2008-07-16 16:58:58.000000000 -0400
|
||||
+++ old.cpp 2008-07-16 16:58:42.000000000 -0400
|
||||
@@ -6731,7 +6731,7 @@
|
||||
SWIG_check_num_args("LUA::Session",0,0)
|
||||
--- mod_lua_wrap.cpp.orig 2010-09-05 16:39:26.000000000 +0200
|
||||
+++ mod_lua_wrap.cpp 2010-09-05 16:39:44.000000000 +0200
|
||||
@@ -4913,7 +4913,7 @@
|
||||
|
||||
result = (LUA::Session *)new LUA::Session();
|
||||
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++; result->setLUA(L);
|
||||
return SWIG_arg;
|
||||
|
||||
if(0) SWIG_fail;
|
||||
@@ -6759,7 +6759,7 @@
|
||||
|
||||
fail:
|
||||
@@ -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);
|
||||
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++; result->setLUA(L);
|
||||
return SWIG_arg;
|
||||
|
||||
if(0) SWIG_fail;
|
||||
@@ -6780,7 +6780,7 @@
|
||||
arg1 = (char *)lua_tostring(L, 1);
|
||||
fail:
|
||||
@@ -4952,7 +4952,7 @@
|
||||
arg1 = (char*)lua_tostring(L, 1);
|
||||
result = (LUA::Session *)new LUA::Session(arg1);
|
||||
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++; result->setLUA(L);
|
||||
return SWIG_arg;
|
||||
|
||||
if(0) SWIG_fail;
|
||||
@@ -6805,7 +6805,7 @@
|
||||
|
||||
fail:
|
||||
@@ -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);
|
||||
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++; result->setLUA(L);
|
||||
return SWIG_arg;
|
||||
|
||||
if(0) SWIG_fail;
|
||||
fail:
|
||||
|
@ -1490,29 +1490,31 @@ SWIG_Lua_dostring(lua_State *L, const char* str) {
|
||||
#define SWIGTYPE_p_Event swig_types[3]
|
||||
#define SWIGTYPE_p_EventConsumer swig_types[4]
|
||||
#define SWIGTYPE_p_IVRMenu swig_types[5]
|
||||
#define SWIGTYPE_p_LUA__Session swig_types[6]
|
||||
#define SWIGTYPE_p_Stream swig_types[7]
|
||||
#define SWIGTYPE_p_input_callback_state swig_types[8]
|
||||
#define SWIGTYPE_p_lua_State swig_types[9]
|
||||
#define SWIGTYPE_p_p_switch_event_node_t swig_types[10]
|
||||
#define SWIGTYPE_p_session_flag_t swig_types[11]
|
||||
#define SWIGTYPE_p_switch_call_cause_t swig_types[12]
|
||||
#define SWIGTYPE_p_switch_channel_state_t swig_types[13]
|
||||
#define SWIGTYPE_p_switch_channel_t swig_types[14]
|
||||
#define SWIGTYPE_p_switch_core_session_t swig_types[15]
|
||||
#define SWIGTYPE_p_switch_event_t swig_types[16]
|
||||
#define SWIGTYPE_p_switch_event_types_t swig_types[17]
|
||||
#define SWIGTYPE_p_switch_input_args_t swig_types[18]
|
||||
#define SWIGTYPE_p_switch_input_type_t swig_types[19]
|
||||
#define SWIGTYPE_p_switch_priority_t swig_types[20]
|
||||
#define SWIGTYPE_p_switch_queue_t swig_types[21]
|
||||
#define SWIGTYPE_p_switch_state_handler_table_t swig_types[22]
|
||||
#define SWIGTYPE_p_switch_status_t swig_types[23]
|
||||
#define SWIGTYPE_p_switch_stream_handle_t swig_types[24]
|
||||
#define SWIGTYPE_p_uint32_t swig_types[25]
|
||||
#define SWIGTYPE_p_void swig_types[26]
|
||||
static swig_type_info *swig_types[28];
|
||||
static swig_module_info swig_module = {swig_types, 27, 0, 0, 0, 0};
|
||||
#define SWIGTYPE_p_LUA__Dbh swig_types[6]
|
||||
#define SWIGTYPE_p_LUA__Session swig_types[7]
|
||||
#define SWIGTYPE_p_SWIGLUA_FN swig_types[8]
|
||||
#define SWIGTYPE_p_Stream swig_types[9]
|
||||
#define SWIGTYPE_p_input_callback_state swig_types[10]
|
||||
#define SWIGTYPE_p_lua_State swig_types[11]
|
||||
#define SWIGTYPE_p_p_switch_event_node_t swig_types[12]
|
||||
#define SWIGTYPE_p_session_flag_t swig_types[13]
|
||||
#define SWIGTYPE_p_switch_call_cause_t swig_types[14]
|
||||
#define SWIGTYPE_p_switch_channel_state_t swig_types[15]
|
||||
#define SWIGTYPE_p_switch_channel_t swig_types[16]
|
||||
#define SWIGTYPE_p_switch_core_session_t swig_types[17]
|
||||
#define SWIGTYPE_p_switch_event_t swig_types[18]
|
||||
#define SWIGTYPE_p_switch_event_types_t swig_types[19]
|
||||
#define SWIGTYPE_p_switch_input_args_t swig_types[20]
|
||||
#define SWIGTYPE_p_switch_input_type_t swig_types[21]
|
||||
#define SWIGTYPE_p_switch_priority_t swig_types[22]
|
||||
#define SWIGTYPE_p_switch_queue_t swig_types[23]
|
||||
#define SWIGTYPE_p_switch_state_handler_table_t swig_types[24]
|
||||
#define SWIGTYPE_p_switch_status_t swig_types[25]
|
||||
#define SWIGTYPE_p_switch_stream_handle_t swig_types[26]
|
||||
#define SWIGTYPE_p_uint32_t swig_types[27]
|
||||
#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_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 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
|
||||
}
|
||||
#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_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_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_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_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};
|
||||
@ -7072,7 +7300,9 @@ static swig_type_info *swig_type_initial[] = {
|
||||
&_swigt__p_Event,
|
||||
&_swigt__p_EventConsumer,
|
||||
&_swigt__p_IVRMenu,
|
||||
&_swigt__p_LUA__Dbh,
|
||||
&_swigt__p_LUA__Session,
|
||||
&_swigt__p_SWIGLUA_FN,
|
||||
&_swigt__p_Stream,
|
||||
&_swigt__p_input_callback_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_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_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_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_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}};
|
||||
@ -7130,7 +7362,9 @@ static swig_cast_info *swig_cast_initial[] = {
|
||||
_swigc__p_Event,
|
||||
_swigc__p_EventConsumer,
|
||||
_swigc__p_IVRMenu,
|
||||
_swigc__p_LUA__Dbh,
|
||||
_swigc__p_LUA__Session,
|
||||
_swigc__p_SWIGLUA_FN,
|
||||
_swigc__p_Stream,
|
||||
_swigc__p_input_callback_state,
|
||||
_swigc__p_lua_State,
|
||||
|
@ -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 {
|
||||
protected:
|
||||
switch_input_args_t args;
|
||||
|
@ -2035,6 +2035,36 @@ SWITCH_DECLARE(void) switch_channel_set_hunt_caller_profile(switch_channel_t *ch
|
||||
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_assert(channel != NULL);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
|
@ -35,6 +35,8 @@
|
||||
#include <switch.h>
|
||||
#include "private/switch_core_pvt.h"
|
||||
|
||||
#define SQLLEN 32768
|
||||
|
||||
static struct {
|
||||
switch_cache_db_handle_t *event_db;
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
@ -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)
|
||||
{
|
||||
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;
|
||||
uint32_t target = 100000;
|
||||
switch_size_t len = 0, sql_len = SQLLEN;
|
||||
char *tmp, *sqlbuf = (char *) malloc(sql_len);
|
||||
char *sql;
|
||||
char *sqlbuf = (char *) malloc(sql_len);
|
||||
char *sql = NULL;
|
||||
switch_size_t newlen;
|
||||
int lc = 0;
|
||||
uint32_t loops = 0, sec = 0;
|
||||
uint32_t l1 = 1000;
|
||||
uint32_t sanity = 120;
|
||||
int item_remained = 0;
|
||||
|
||||
switch_assert(sqlbuf);
|
||||
|
||||
@ -897,10 +900,17 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (switch_queue_trypop(sql_manager.sql_queue[0], &pop) == SWITCH_STATUS_SUCCESS ||
|
||||
switch_queue_trypop(sql_manager.sql_queue[1], &pop) == SWITCH_STATUS_SUCCESS) {
|
||||
sql = (char *) pop;
|
||||
//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) {
|
||||
|
||||
if (item_remained) {
|
||||
item_remained = 0;
|
||||
} else {
|
||||
sql = (char *) pop;
|
||||
}
|
||||
|
||||
if (sql) {
|
||||
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 */
|
||||
if (newlen < SQLLEN) {
|
||||
itterations++;
|
||||
if (len + newlen > sql_len) {
|
||||
sql_len = len + SQLLEN;
|
||||
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;
|
||||
|
||||
if (len + newlen < sql_len) {
|
||||
sprintf(sqlbuf + len, "%s;\n", sql);
|
||||
len += newlen;
|
||||
} else {
|
||||
item_remained = 1;
|
||||
}
|
||||
sprintf(sqlbuf + len, "%s;\n", sql);
|
||||
len += newlen;
|
||||
|
||||
}
|
||||
free(sql);
|
||||
|
||||
if (!item_remained) {
|
||||
free(sql);
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "SQL thread ending\n");
|
||||
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) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL thread unable to commit transaction, records lost!\n");
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
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) {
|
||||
switch_caller_profile_t *cp = NULL;
|
||||
int off = 0;
|
||||
|
@ -1683,16 +1683,20 @@ SWITCH_DECLARE(switch_status_t) switch_api_execute(const char *cmd, const char *
|
||||
{
|
||||
switch_api_interface_t *api;
|
||||
switch_status_t status;
|
||||
char *arg_no_spaces;
|
||||
char *cmd_no_spaces;
|
||||
char *arg_used;
|
||||
char *cmd_used;
|
||||
|
||||
switch_assert(stream != NULL);
|
||||
switch_assert(stream->data != NULL);
|
||||
switch_assert(stream->write_function != NULL);
|
||||
|
||||
|
||||
cmd_no_spaces = switch_strip_whitespace(cmd);
|
||||
arg_no_spaces = switch_strip_whitespace(arg);
|
||||
if (strcasecmp(cmd, "console_complete")) {
|
||||
cmd_used = switch_strip_whitespace(cmd);
|
||||
arg_used = switch_strip_whitespace(arg);
|
||||
} else {
|
||||
cmd_used = (char *) cmd;
|
||||
arg_used = (char *) arg;
|
||||
}
|
||||
|
||||
|
||||
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 (cmd_no_spaces) {
|
||||
switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command", cmd_no_spaces);
|
||||
if (cmd_used) {
|
||||
switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command", cmd_used);
|
||||
}
|
||||
if (arg_no_spaces) {
|
||||
switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command-Argument", arg_no_spaces);
|
||||
if (arg_used) {
|
||||
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 ((status = api->function(arg_no_spaces, session, stream)) != SWITCH_STATUS_SUCCESS) {
|
||||
if (cmd_used && (api = switch_loadable_module_get_api_interface(cmd_used)) != 0) {
|
||||
if ((status = api->function(arg_used, session, stream)) != SWITCH_STATUS_SUCCESS) {
|
||||
stream->write_function(stream, "COMMAND RETURNED ERROR!\n");
|
||||
}
|
||||
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_safe_free(cmd_no_spaces);
|
||||
switch_safe_free(arg_no_spaces);
|
||||
if (cmd_used != cmd) {
|
||||
switch_safe_free(cmd_used);
|
||||
}
|
||||
|
||||
if (arg_used != arg) {
|
||||
switch_safe_free(arg_used);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user