diff --git a/conf/autoload_configs/modules.conf.xml b/conf/autoload_configs/modules.conf.xml
index b4dff4d96e..d8ae5e1a03 100644
--- a/conf/autoload_configs/modules.conf.xml
+++ b/conf/autoload_configs/modules.conf.xml
@@ -22,6 +22,7 @@
+
diff --git a/docs/ChangeLog b/docs/ChangeLog
index 993463c8ef..99c87c5657 100644
--- a/docs/ChangeLog
+++ b/docs/ChangeLog
@@ -7,13 +7,15 @@ freeswitch (1.0.7)
build: apply fix for MODSOFIA-71 to windows build
build: Add more excludes to .gitignore (for Windows) (r:b6628d26/FSBUILD-269)
build: Bump version of en-us-callie sounds to 1.0.13 (r:ca0a69a3)
- build: change build to use mod_spandsp instead of mod_fax and mod_voipcodecs (r: 988147a7)
- build: add mod_spandsp to windows build (r: 4fa8be62)
+ build: change build to use mod_spandsp instead of mod_fax and mod_voipcodecs (r:988147a7)
+ build: add mod_spandsp to windows build (r:4fa8be62)
+ build: merge -j option for bootstrap (r:abb7d2e5/FSBUILD-237)
+ build: dont fail on bootstrap due to missing libs (r:ff960d78)
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)
config: update config example for caller-id-type (r:8f03a7cd)
- config: default to 48k since most sound cards can do that (r: 170404a4)
+ config: default to 48k since most sound cards can do that (r:170404a4)
core: Add RTCP support (FSRTP-14)
core: handle some errors on missing db handle conditions
core: add ... and shutdown as a fail-safe when no modules are loaded
@@ -45,8 +47,9 @@ freeswitch (1.0.7)
core: (Win) bridge fails because session read lock failure (r:f8f91362/FSCORE-606)
core: Add option to hangup channel if record fails (r:a3e6bead/FSBUILD-591)
core: Crash when using tab completion on uuid_ commands (r:9637b89e/FSCORE-613)
- core: fix uuid_media state change (r: 2cc59f1e/FSCORE-615)
- core: add new callstate field to channels table (r: 0f133eae)
+ core: fix uuid_media state change (r:2cc59f1e/FSCORE-615)
+ core: add new callstate field to channels table (r:0f133eae)
+ core: fix leg_timeout issue (r:3fbd9e21/MODAPP-433)
embedded languages: Provide core level support for conditional Set Global Variable (r:c017c24b/FSCORE-612)
lang: Improve French phrase files (FSCONFIG-23)
libdingaling: fix race on shutdown causing crash (FSMOD-47)
@@ -59,7 +62,7 @@ freeswitch (1.0.7)
libsopenzap: Add CLI tracing
libspandsp: Fixed a typo in spandsp's msvc/inttypes.h Updated sig_tone processing in spandsp to the latest, to allow moy to proceed with his signaling work.
libspandsp: removed a saturate16 from spandsp that was causing problems fixed a typo in the MSVC inttypes.h file for spandsp
- libspandsp: Changes to the signaling tone detector to detect concurrent 2400Hz + 2600Hz tones. This passes voice immunity and other key tests, but it bounces a bit when transitions like 2400 -> 2400+2600 -> 2600 occur. Transitions between tone off and tone on are clean. (r: bc13e944)
+ libspandsp: 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)
mod_avmd: Initial check in - Advanced Voicemail Detect (r:10c6a30a) (by Eric Des Courtis)
mod_avmd: Add to windows build (r:df4bd935)
mod_cidlookup: null xml is bad (r:095815f8)
@@ -67,9 +70,8 @@ freeswitch (1.0.7)
mod_commands: make break uuid_break and add cascade flag
mod_commands: add uuid_autoanswer command (now uuid_phone_event)
mod_commands: expand last patch to do hold as well and rename the command to uuid_phone_event
- mod_commands: make break uuid_break and add cascade flag
- mod_commands: allow uuid_break to interrupt one or all in a delimited string of files the same as several individual files (r: eba05c3c)
- mod_commands: add show channels count auto-completion for mod_commands (r: 5ffc57e5/FSMOD-54)
+ mod_commands: allow uuid_break to interrupt one or all in a delimited string of files the same as several individual files (r:eba05c3c)
+ mod_commands: add show channels count auto-completion for mod_commands (r:5ffc57e5/FSMOD-54)
mod_conference: Fix reporting of volume up/down (MODAPP-419)
mod_conference: add last talking time per member to conference xml list
mod_conference: add terminate-on-silence conference param
@@ -78,6 +80,8 @@ freeswitch (1.0.7)
mod_conference: fix relate nohear (r:f029ce07/MODAPP-428)
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)
+ mod_dptools: add block_dtmf and unblock_dtmf apps (r:d9eb0197)
mod_fifo: allow multiple dtmf to exit fifo, set fifo_caller_exit_key to specify which (MODAPP-420)
mod_freetdm: Fix for TON and NPI not passed through to channel variables on incoming calls
mod_freetdm: add pvt data to freetdm channels fix fxs features (r:9d456900)
@@ -93,19 +97,19 @@ freeswitch (1.0.7)
mod_freetdm: run sched in the background if requested (r:22e8a442)
mod_freetdm: fix makefile and remove binary app (r:63d9768d)
mod_freetdm: add trace/notrace commands to trace input and output from channels (r:f4da0e5c)
- mod_freetdm: add logging when failing to read a frame in mod_freetdm (r: e596fc2e)
- mod_freetdm: add new logging macro (r: 75be3da8)
- mod_freetdm: check for hw dtmf before enabling (r: b1fd88d7)
- mod_freetdm: adding ftmod_sangoma_ss7 support (r: 94283355)
- mod_freetdm: added SIGEVENT_COLLISION (r: 501f8704)
+ mod_freetdm: add logging when failing to read a frame in mod_freetdm (r:e596fc2e)
+ mod_freetdm: add new logging macro (r:75be3da8)
+ mod_freetdm: check for hw dtmf before enabling (r:b1fd88d7)
+ mod_freetdm: adding ftmod_sangoma_ss7 support (r:94283355)
+ mod_freetdm: added SIGEVENT_COLLISION (r:501f8704)
mod_gsmopen: copy from branch
mod_java: fix eventConsumer issue and add flush() method (r:7fd3aff6)
- mod_java: Allow user defined java methods to be called at startup and shutdown of JVM (r: 1339e218/MODLANG-117)
+ mod_java: Allow user defined java methods to be called at startup and shutdown of JVM (r:1339e218/MODLANG-117)
mod_lcr: Expand variables (MODAPP-418)
mod_lcr: add enable_sip_redir parameter (r:70bf7a0a/MODAPP-427)
mod_loopback: add loopback_bowout_on_execute var to make 1 legged loopback calls bow out of the picture
- mod_loopback: only execute app once in app mode (r: 64f58f2d)
- mod_managed: Added wrapper for switch_event_bind for .net (r: a5f07a80/MODLANG-165)
+ mod_loopback: only execute app once in app mode (r:64f58f2d)
+ mod_managed: Added wrapper for switch_event_bind for .net (r:a5f07a80/MODLANG-165)
mod_mp4v: MP4V-ES passthru for washibechi on IRC
mod_nibblebill: free allocated mem at shutdown; free properly if using custom_sql
mod_nibblebill: Add SAF_SUPPORT_NOMEDIA to nibblebill
@@ -122,7 +126,7 @@ freeswitch (1.0.7)
mod_sangoma_codec: Add sample config file
mod_sangoma_codec: added load/noload options for the supported codecs
mod_sangoma_codec: rename load/noload to register/noregister
- mod_sangoma_codec: silence suppression (r: 73d9d56f)
+ mod_sangoma_codec: silence suppression (r:73d9d56f)
mod_say_es: fix grammar when saying dates and time (r:6bed19b2/MODAPP-429)
mod_say_zh: Number reading should now be OK for the whole range of integers for Cantonese and Mandarin
mod_skinny: Add the missing api files
@@ -154,12 +158,14 @@ freeswitch (1.0.7)
mod_sofia: fire an event for gateway ping
mod_sofia: initial handling of udptl and t.38 re-invite
mod_sofia: Implement "redirect server" functionality with 300 Multiple Choices (r:e15abcf9/BOUNTY-18)
- mod_sofia: allow video negotiation on re-invite (r: be92e5d/SFSIP-211)
- mod_sofia: use rfc recommended default session timeout of 30 min according to RFC 4028 4.2 (r: 52cd8cdd/MODSOFIA-76)
- mod_sofia: add sip_force_audio_fmtp (r: 6360264f)
- mod_sofia: add sip_copy_multipart to work like sip_copy_custom_headers (r: a291af57)
- mod_sofia: Rename sofia_glue_get_user_host to switch_split_user_domain and move to switch_utils. To allow use by other modules. (r: 3f7cafd7)
- mod_sofia: allow the profile gateway config to set sip_cid_type for each gateway (r: 0152706f/BOUNTY-19)
+ mod_sofia: allow video negotiation on re-invite (r:be92e5d/SFSIP-211)
+ mod_sofia: use rfc recommended default session timeout of 30 min according to RFC 4028 4.2 (r:52cd8cdd/MODSOFIA-76)
+ mod_sofia: add sip_force_audio_fmtp (r:6360264f)
+ mod_sofia: add sip_copy_multipart to work like sip_copy_custom_headers (r:a291af57)
+ mod_sofia: Rename sofia_glue_get_user_host to switch_split_user_domain and move to switch_utils. To allow use by other modules. (r:3f7cafd7)
+ mod_sofia: allow the profile gateway config to set sip_cid_type for each gateway (r:0152706f/BOUNTY-19)
+ mod_sofia: Adding subject to SEND_MESSAGE (r:2e347c93)
+ mod_sofia: add multiple rtp-ip support to sofia profiles add extra rtp-ip params to a profile to add more ip which will be used round-robin as new calls progress. (r:22569d4a)
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)
@@ -175,9 +181,9 @@ freeswitch (1.0.7)
mod_xml_cdr: add force_process_cdr var to process b leg cdr on a case by case basis when b leg cdr is disabled (XML-17)
mod_xml_cdr: add leg param to query string (XML-24)
mod_xml_cdr: fix locked sessions (XML-26)
- mod_xml_cdr: fix minor memory leaks and config bug (r: 19253d83/MODEVENT-62)
+ mod_xml_cdr: fix minor memory leaks and config bug (r:19253d83/MODEVENT-62)
sofia-sip: fix null derefernce segfault in soa (r:f356c5e6)
- sofia-sip: extend timeout for session expires on short timeouts to be 90% of timeout instead of 1/3 to handle devices that do not refresh in time such as polycom (r: a7f48928/SFSIP-212)
+ sofia-sip: extend timeout for session expires on short timeouts to be 90% of timeout instead of 1/3 to handle devices that do not refresh in time such as polycom (r:a7f48928/SFSIP-212)
freeswitch (1.0.6)
diff --git a/libs/esl/src/esl_oop.cpp b/libs/esl/src/esl_oop.cpp
index 1b6629c066..231950f892 100644
--- a/libs/esl/src/esl_oop.cpp
+++ b/libs/esl/src/esl_oop.cpp
@@ -355,7 +355,7 @@ const char *ESLevent::serialize(const char *format)
return "";
}
- if (!strcasecmp(format, "json")) {
+ if (format && !strcasecmp(format, "json")) {
esl_event_serialize_json(event, &serialized_string);
return serialized_string;
}
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c
index 42090710b1..b5121b995b 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c
@@ -1031,6 +1031,10 @@ tryagain:
ftdm_set_string(ftdmchan->caller_data.ani.digits, (char *)event->calling.digits);
ftdm_set_string(ftdmchan->caller_data.dnis.digits, (char *)event->called.digits);
ftdm_set_string(ftdmchan->caller_data.rdnis.digits, (char *)event->rdnis.digits);
+ if (event->custom_data_size) {
+ ftdm_set_string(ftdmchan->caller_data.raw_data, event->custom_data);
+ ftdmchan->caller_data.raw_data_len = event->custom_data_size;
+ }
if (strlen(event->calling_name)) {
ftdm_set_string(ftdmchan->caller_data.cid_name, (char *)event->calling_name);
diff --git a/libs/libteletone/libteletone.2010.vcxproj b/libs/libteletone/libteletone.2010.vcxproj
index e8335ddd41..8d2c30a66a 100644
--- a/libs/libteletone/libteletone.2010.vcxproj
+++ b/libs/libteletone/libteletone.2010.vcxproj
@@ -48,19 +48,19 @@
-
+
-
+
-
+
-
+
@@ -79,7 +79,6 @@
true
- $(ProjectDir)teletone.def
false
false
false
@@ -102,7 +101,6 @@
true
- $(ProjectDir)teletone.def
false
false
false
@@ -120,7 +118,6 @@
true
- $(ProjectDir)teletone.def
false
@@ -137,7 +134,6 @@
true
- $(ProjectDir)teletone.def
false
MachineX64
diff --git a/libs/win32/apr-util/libaprutil.2010.vcxproj b/libs/win32/apr-util/libaprutil.2010.vcxproj
index a39f21e091..b105ab4bc8 100644
--- a/libs/win32/apr-util/libaprutil.2010.vcxproj
+++ b/libs/win32/apr-util/libaprutil.2010.vcxproj
@@ -73,17 +73,10 @@
if not exist "$(ProjectDir)..\..\apr-util\include\apu.h" type "$(ProjectDir)..\..\apr-util\include\apu.hw" > "$(ProjectDir)..\..\apr-util\include\apu.h"
if not exist "$(ProjectDir)..\..\apr-util\include\apu_config.h" type "$(ProjectDir)..\..\apr-util\include\apu_config.hw" > "$(ProjectDir)..\..\apr-util\include\apu_config.h"
if not exist "$(ProjectDir)..\..\apr-util\include\apu_select_dbm.h" type "$(ProjectDir)..\..\apr-util\include\apu_select_dbm.hw" > "$(ProjectDir)..\..\apr-util\include\apu_select_dbm.h"
-if not exist "$(ProjectDir)..\..\apr-util\include\apu_want.h" type "$(ProjectDir)..\..\apr-util\include\apu_want.hw" > "$(ProjectDir)..\..\apr-util\include\apu_want.h"
+if not exist "$(ProjectDir)..\..\apr-util\include\apu_want.h" type "$(ProjectDir)..\..\apr-util\include\apu_want.hw" > "$(ProjectDir)..\..\apr-util\include\apu_want.h"
+xcopy "$(ProjectDir)..\..\apr-util\include\*.h" "$(ProjectDir)..\..\include\" /C /D /Y
+
-
- _DEBUG;%(PreprocessorDefinitions)
- true
- true
- Win32
- $(IntDir)libaprutil.tlb
-
-
-
/EHsc %(AdditionalOptions)
Disabled
@@ -100,7 +93,6 @@ if not exist "$(ProjectDir)..\..\apr-util\include\apu_want.h" type "$(ProjectDir
ws2_32.lib;mswsock.lib;wldap32.lib;%(AdditionalDependencies)
- $(OutDir)$(ProjectName).dll
true
%(AdditionalLibraryDirectories)
true
@@ -111,12 +103,7 @@ if not exist "$(ProjectDir)..\..\apr-util\include\apu_want.h" type "$(ProjectDir
true
- $(IntDir)libaprutil.bsc
-
-
-
-
@@ -125,17 +112,9 @@ if not exist "$(ProjectDir)..\..\apr-util\include\apu.h" type "$(ProjectDir)..\.
if not exist "$(ProjectDir)..\..\apr-util\include\apu_config.h" type "$(ProjectDir)..\..\apr-util\include\apu_config.hw" > "$(ProjectDir)..\..\apr-util\include\apu_config.h"
if not exist "$(ProjectDir)..\..\apr-util\include\apu_select_dbm.h" type "$(ProjectDir)..\..\apr-util\include\apu_select_dbm.hw" > "$(ProjectDir)..\..\apr-util\include\apu_select_dbm.h"
if not exist "$(ProjectDir)..\..\apr-util\include\apu_want.h" type "$(ProjectDir)..\..\apr-util\include\apu_want.hw" > "$(ProjectDir)..\..\apr-util\include\apu_want.h"
+xcopy "$(ProjectDir)..\..\apr-util\include\*.h" "$(ProjectDir)..\..\include\" /C /D /Y
-
- _DEBUG;%(PreprocessorDefinitions)
- true
- true
- X64
- $(IntDir)libaprutil.tlb
-
-
-
/EHsc %(AdditionalOptions)
Disabled
@@ -152,7 +131,6 @@ if not exist "$(ProjectDir)..\..\apr-util\include\apu_want.h" type "$(ProjectDir
ws2_32.lib;mswsock.lib;wldap32.lib;%(AdditionalDependencies)
- $(OutDir)$(ProjectName).dll
true
%(AdditionalLibraryDirectories)
true
@@ -163,12 +141,7 @@ if not exist "$(ProjectDir)..\..\apr-util\include\apu_want.h" type "$(ProjectDir
true
- $(IntDir)libaprutil.bsc
-
-
-
-
@@ -177,17 +150,9 @@ if not exist "$(ProjectDir)..\..\apr-util\include\apu.h" type "$(ProjectDir)..\.
if not exist "$(ProjectDir)..\..\apr-util\include\apu_config.h" type "$(ProjectDir)..\..\apr-util\include\apu_config.hw" > "$(ProjectDir)..\..\apr-util\include\apu_config.h"
if not exist "$(ProjectDir)..\..\apr-util\include\apu_select_dbm.h" type "$(ProjectDir)..\..\apr-util\include\apu_select_dbm.hw" > "$(ProjectDir)..\..\apr-util\include\apu_select_dbm.h"
if not exist "$(ProjectDir)..\..\apr-util\include\apu_want.h" type "$(ProjectDir)..\..\apr-util\include\apu_want.hw" > "$(ProjectDir)..\..\apr-util\include\apu_want.h"
+xcopy "$(ProjectDir)..\..\apr-util\include\*.h" "$(ProjectDir)..\..\include\" /C /D /Y
-
- NDEBUG;%(PreprocessorDefinitions)
- true
- true
- Win32
- $(IntDir)libaprutil.tlb
-
-
-
MaxSpeed
OnlyExplicitInline
@@ -206,7 +171,6 @@ if not exist "$(ProjectDir)..\..\apr-util\include\apu_want.h" type "$(ProjectDir
ws2_32.lib;mswsock.lib;wldap32.lib;%(AdditionalDependencies)
- $(OutDir)$(ProjectName).dll
true
%(AdditionalLibraryDirectories)
true
@@ -214,17 +178,11 @@ if not exist "$(ProjectDir)..\..\apr-util\include\apu_want.h" type "$(ProjectDir
true
0x6EE60000
false
- $(IntDir)libaprutil-1.lib
MachineX86
true
- $(IntDir)libaprutil.bsc
-
-
-
-
@@ -233,17 +191,9 @@ if not exist "$(ProjectDir)..\..\apr-util\include\apu.h" type "$(ProjectDir)..\.
if not exist "$(ProjectDir)..\..\apr-util\include\apu_config.h" type "$(ProjectDir)..\..\apr-util\include\apu_config.hw" > "$(ProjectDir)..\..\apr-util\include\apu_config.h"
if not exist "$(ProjectDir)..\..\apr-util\include\apu_select_dbm.h" type "$(ProjectDir)..\..\apr-util\include\apu_select_dbm.hw" > "$(ProjectDir)..\..\apr-util\include\apu_select_dbm.h"
if not exist "$(ProjectDir)..\..\apr-util\include\apu_want.h" type "$(ProjectDir)..\..\apr-util\include\apu_want.hw" > "$(ProjectDir)..\..\apr-util\include\apu_want.h"
+xcopy "$(ProjectDir)..\..\apr-util\include\*.h" "$(ProjectDir)..\..\include\" /C /D /Y
-
- NDEBUG;%(PreprocessorDefinitions)
- true
- true
- X64
- $(IntDir)libaprutil.tlb
-
-
-
MaxSpeed
OnlyExplicitInline
@@ -262,7 +212,6 @@ if not exist "$(ProjectDir)..\..\apr-util\include\apu_want.h" type "$(ProjectDir
ws2_32.lib;mswsock.lib;wldap32.lib;%(AdditionalDependencies)
- $(OutDir)$(ProjectName).dll
true
%(AdditionalLibraryDirectories)
true
@@ -274,12 +223,7 @@ if not exist "$(ProjectDir)..\..\apr-util\include\apu_want.h" type "$(ProjectDir
true
- $(IntDir)libaprutil.bsc
-
-
-
-
diff --git a/libs/win32/apr/libapr.2010.vcxproj b/libs/win32/apr/libapr.2010.vcxproj
index 6638ec7d43..5c6b686ee0 100644
--- a/libs/win32/apr/libapr.2010.vcxproj
+++ b/libs/win32/apr/libapr.2010.vcxproj
@@ -70,6 +70,7 @@
if not exist "$(ProjectDir)..\..\apr\include\apr.h" type "$(ProjectDir)apr.hw" > "$(ProjectDir)..\..\apr\include\apr.h"
+xcopy "$(ProjectDir)..\..\apr\include\*.h" "$(ProjectDir)..\..\include\" /C /D /Y
@@ -88,7 +89,6 @@
ws2_32.lib;mswsock.lib;rpcrt4.lib;advapi32.lib;%(AdditionalDependencies)
- $(OutDir)$(ProjectName).dll
true
true
Windows
@@ -100,16 +100,12 @@
true
- $(IntDir)libapr.bsc
-
-
-
-
if not exist "$(ProjectDir)..\..\apr\include\apr.h" type "$(ProjectDir)apr.hw" > "$(ProjectDir)..\..\apr\include\apr.h"
+xcopy "$(ProjectDir)..\..\apr\include\*.h" "$(ProjectDir)..\..\include\" /C /D /Y
@@ -128,7 +124,6 @@
ws2_32.lib;mswsock.lib;rpcrt4.lib;advapi32.lib;%(AdditionalDependencies)
- $(OutDir)$(ProjectName).dll
true
true
Windows
@@ -138,16 +133,12 @@
true
- $(IntDir)libapr.bsc
-
-
-
-
if not exist "$(ProjectDir)..\..\apr\include\apr.h" type "$(ProjectDir)apr.hw" > "$(ProjectDir)..\..\apr\include\apr.h"
+xcopy "$(ProjectDir)..\..\apr\include\*.h" "$(ProjectDir)..\..\include\" /C /D /Y
@@ -168,7 +159,6 @@
ws2_32.lib;mswsock.lib;rpcrt4.lib;advapi32.lib;%(AdditionalDependencies)
- $(OutDir)$(ProjectName).dll
true
true
Windows
@@ -179,16 +169,12 @@
true
- $(IntDir)libapr.bsc
-
-
-
-
if not exist "$(ProjectDir)..\..\apr\include\apr.h" type "$(ProjectDir)apr.hw" > "$(ProjectDir)..\..\apr\include\apr.h"
+xcopy "$(ProjectDir)..\..\apr\include\*.h" "$(ProjectDir)..\..\include\" /C /D /Y
@@ -209,7 +195,6 @@
ws2_32.lib;mswsock.lib;rpcrt4.lib;advapi32.lib;%(AdditionalDependencies)
- $(OutDir)$(ProjectName).dll
true
true
Windows
@@ -220,12 +205,7 @@
true
- $(IntDir)libapr.bsc
-
-
-
-
diff --git a/libs/win32/pcre/libpcre.2010.vcxproj b/libs/win32/pcre/libpcre.2010.vcxproj
index 4ca6dbcb9d..22db6b7a50 100644
--- a/libs/win32/pcre/libpcre.2010.vcxproj
+++ b/libs/win32/pcre/libpcre.2010.vcxproj
@@ -120,12 +120,6 @@
false
-
- _DEBUG;%(PreprocessorDefinitions)
- true
- true
- Win32
-
Disabled
$(ProjectDir);$(ProjectDir)..\..\pcre;%(AdditionalIncludeDirectories)
@@ -136,27 +130,11 @@
Level3
true
-
- _DEBUG;%(PreprocessorDefinitions)
- 0x0409
-
-
- true
-
-
- odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
-
true
-
- _DEBUG;%(PreprocessorDefinitions)
- true
- true
- X64
-
Disabled
$(ProjectDir);$(ProjectDir)..\..\pcre;%(AdditionalIncludeDirectories)
@@ -167,27 +145,8 @@
Level3
true
-
- _DEBUG;%(PreprocessorDefinitions)
- 0x0409
-
-
- true
-
-
- odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
-
-
- true
-
-
- NDEBUG;%(PreprocessorDefinitions)
- true
- true
- Win32
-
MaxSpeed
OnlyExplicitInline
@@ -199,27 +158,11 @@
Level3
true
-
- NDEBUG;%(PreprocessorDefinitions)
- 0x0409
-
-
- true
-
-
- odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
-
true
-
- NDEBUG;%(PreprocessorDefinitions)
- true
- true
- X64
-
MaxSpeed
OnlyExplicitInline
@@ -231,16 +174,6 @@
Level3
true
-
- NDEBUG;%(PreprocessorDefinitions)
- 0x0409
-
-
- true
-
-
- odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
-
true
diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h
index bc174c67eb..50dde95dc7 100644
--- a/src/include/private/switch_core_pvt.h
+++ b/src/include/private/switch_core_pvt.h
@@ -166,6 +166,7 @@ struct switch_core_session {
uint32_t track_duration;
uint32_t track_id;
switch_log_level_t loglevel;
+ uint32_t soft_lock;
};
struct switch_media_bug {
diff --git a/src/include/switch_core.h b/src/include/switch_core.h
index 9d7d02b6e1..650ffc15fb 100644
--- a/src/include/switch_core.h
+++ b/src/include/switch_core.h
@@ -483,6 +483,7 @@ SWITCH_DECLARE(unsigned int) switch_core_session_started(_In_ switch_core_sessio
SWITCH_DECLARE(void *) switch_core_perform_permanent_alloc(_In_ switch_size_t memory, _In_z_ const char *file, _In_z_ const char *func, _In_ int line);
+
/*!
\brief Allocate memory from the main pool with no intention of returning it
\param _memory the number of bytes to allocate
@@ -698,6 +699,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_set_loglevel(switch_core_ses
*/
SWITCH_DECLARE(switch_log_level_t) switch_core_session_get_loglevel(switch_core_session_t *session);
+
+SWITCH_DECLARE(void) switch_core_session_soft_lock(switch_core_session_t *session, uint32_t sec);
+SWITCH_DECLARE(void) switch_core_session_soft_unlock(switch_core_session_t *session);
+
+
/*!
\brief Retrieve the unique identifier from the core
\return a string representing the uuid
@@ -1973,6 +1979,7 @@ SWITCH_DECLARE(void) switch_core_memory_reclaim_events(void);
SWITCH_DECLARE(void) switch_core_memory_reclaim_logger(void);
SWITCH_DECLARE(void) switch_core_memory_reclaim_all(void);
SWITCH_DECLARE(void) switch_core_setrlimits(void);
+SWITCH_DECLARE(switch_time_t) switch_time_ref(void);
SWITCH_DECLARE(void) switch_time_sync(void);
/*!
\brief Get the current epoch time
diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c
index 29d7d17140..f41e95cca1 100644
--- a/src/mod/applications/mod_commands/mod_commands.c
+++ b/src/mod/applications/mod_commands/mod_commands.c
@@ -235,9 +235,9 @@ SWITCH_STANDARD_API(time_test_function)
}
for (x = 1; x <= max; x++) {
- then = switch_time_now();
+ then = switch_time_ref();
switch_yield(mss);
- now = switch_time_now();
+ now = switch_time_ref();
diff = (int) (now - then);
stream->write_function(stream, "test %d sleep %ld %d\n", x, mss, diff);
total += diff;
@@ -299,17 +299,17 @@ SWITCH_STANDARD_API(timer_test_function)
goto end;
}
- start = switch_time_now();
+ start = switch_time_ref();
for (x = 1; x <= max; x++) {
- then = switch_time_now();
+ then = switch_time_ref();
switch_core_timer_next(&timer);
- now = switch_time_now();
+ now = switch_time_ref();
diff = (int) (now - then);
//stream->write_function(stream, "test %d sleep %ld %d\n", x, mss, diff);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Timer Test: %d sleep %d %d\n", x, mss, diff);
total += diff;
}
- end = switch_time_now();
+ end = switch_time_ref();
switch_yield(250000);
@@ -1599,7 +1599,7 @@ SWITCH_STANDARD_API(ctl_function)
arg = atoi(argv[1]);
}
switch_core_session_ctl(SCSC_MAX_SESSIONS, &arg);
- stream->write_function(stream, "+OK max sessions: %f\n", arg);
+ stream->write_function(stream, "+OK max sessions: %d\n", arg);
} else if (!strcasecmp(argv[0], "min_idle_cpu")) {
double d = -1;
@@ -4279,12 +4279,17 @@ end:
return SWITCH_STATUS_SUCCESS;
}
-#define LIMIT_HASH_USAGE_USAGE " [rate]"
+#define LIMIT_HASH_USAGE_USAGE " [rate] (Using deprecated limit api, check limit_usage with backend param)"
SWITCH_STANDARD_API(limit_hash_usage_function)
{
char *mydata = NULL;
- mydata = switch_core_session_sprintf(session, "hash %s", cmd);
- return limit_usage_function(mydata, session, stream);
+ if (!zstr(cmd)) {
+ mydata = switch_core_session_sprintf(session, "hash %s", cmd);
+ return limit_usage_function(mydata, session, stream);
+ } else {
+ stream->write_function(stream, "USAGE: limit_hash_usage %s\n", LIMIT_HASH_USAGE_USAGE);
+ return SWITCH_STATUS_SUCCESS;
+ }
}
#define LIMIT_STATUS_USAGE ""
diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c
index a394d64a9a..00dcda3c08 100755
--- a/src/mod/applications/mod_dptools/mod_dptools.c
+++ b/src/mod/applications/mod_dptools/mod_dptools.c
@@ -2688,20 +2688,22 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
}
+ switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS);
+ switch_assert(params);
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "as_channel", "true");
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "action", "user_call");
+
+ if (var_event) {
+ switch_event_merge(params, var_event);
+ }
+
if (var_event && (skip = switch_event_get_header(var_event, "user_recurse_variables")) && switch_false(skip)) {
if ((var = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) || (var = switch_event_get_header(var_event, "leg_timeout"))) {
timelimit = atoi(var);
}
var_event = NULL;
}
-
-
-
- switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS);
- switch_assert(params);
- switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "as_channel", "true");
- switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "action", "user_call");
-
+
if (switch_xml_locate_user("id", user, domain, NULL, &xml, &x_domain, &x_user, &x_group, params) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Can't find user [%s@%s]\n", user, domain);
cause = SWITCH_CAUSE_SUBSCRIBER_ABSENT;
diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c
index cc2589a4f4..58d7879aaf 100644
--- a/src/mod/applications/mod_fifo/mod_fifo.c
+++ b/src/mod/applications/mod_fifo/mod_fifo.c
@@ -34,6 +34,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown);
SWITCH_MODULE_LOAD_FUNCTION(mod_fifo_load);
SWITCH_MODULE_DEFINITION(mod_fifo, mod_fifo_load, mod_fifo_shutdown, NULL);
+#define MANUAL_QUEUE_NAME "manual_calls"
#define FIFO_EVENT "fifo::info"
#define FIFO_DELAY_DESTROY 100
static switch_status_t load_config(int reload, int del_all);
@@ -136,7 +137,11 @@ static switch_status_t fifo_queue_pop(fifo_queue_t *queue, switch_event_t **pop,
return SWITCH_STATUS_FALSE;
}
- *pop = queue->data[0];
+ if (remove) {
+ *pop = queue->data[0];
+ } else {
+ switch_event_dup(pop, queue->data[0]);
+ }
if (remove) {
for (i = 1; i < queue->idx; i++) {
@@ -169,7 +174,12 @@ static switch_status_t fifo_queue_pop_nameval(fifo_queue_t *queue, const char *n
for (j = 0; j < queue->idx; j++) {
const char *j_val = switch_event_get_header(queue->data[j], name);
if (j_val && val && !strcmp(j_val, val)) {
- *pop = queue->data[j];
+
+ if (remove) {
+ *pop = queue->data[j];
+ } else {
+ switch_event_dup(pop, queue->data[j]);
+ }
break;
}
}
@@ -178,7 +188,7 @@ static switch_status_t fifo_queue_pop_nameval(fifo_queue_t *queue, const char *n
switch_mutex_unlock(queue->mutex);
return SWITCH_STATUS_FALSE;
}
-
+
if (remove) {
for (i = j+1; i < queue->idx; i++) {
queue->data[i-1] = queue->data[i];
@@ -245,7 +255,7 @@ struct fifo_node {
switch_memory_pool_t *pool;
int has_outbound;
int ready;
- int busy;
+ long busy;
int is_static;
int outbound_per_cycle;
char *outbound_name;
@@ -485,6 +495,8 @@ static switch_status_t consumer_read_frame_callback(switch_core_session_t *sessi
}
static struct {
+ switch_hash_t *orig_hash;
+ switch_mutex_t *orig_mutex;
switch_hash_t *fifo_hash;
switch_mutex_t *mutex;
switch_mutex_t *sql_mutex;
@@ -670,6 +682,269 @@ struct callback_helper {
};
+static switch_status_t messagehook (switch_core_session_t *session, switch_core_session_message_t *msg)
+{
+ switch_event_t *event;
+ switch_core_session_t *caller_session = NULL, *consumer_session = NULL;
+ switch_channel_t *caller_channel = NULL, *consumer_channel = NULL;
+ const char *outbound_id;
+ char *sql;
+
+ consumer_session = session;
+ consumer_channel = switch_core_session_get_channel(consumer_session);
+
+ switch (msg->message_id) {
+ case SWITCH_MESSAGE_INDICATE_BRIDGE:
+ case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
+ if ((caller_session = switch_core_session_locate(msg->string_arg))) {
+ caller_channel = switch_core_session_get_channel(caller_session);
+ if (msg->message_id == SWITCH_MESSAGE_INDICATE_BRIDGE) {
+ switch_core_session_soft_lock(caller_session, 5);
+ } else {
+ switch_core_session_soft_unlock(caller_session);
+ }
+ }
+ break;
+ case SWITCH_MESSAGE_INDICATE_DISPLAY:
+ sql = switch_mprintf("update fifo_bridge set caller_caller_id_name='%q', caller_caller_id_number='%q' where consumer_uuid='%q'",
+ switch_str_nil(msg->string_array_arg[0]),
+ switch_str_nil(msg->string_array_arg[1]),
+ switch_core_session_get_uuid(session));
+ fifo_execute_sql(sql, globals.sql_mutex);
+ switch_safe_free(sql);
+ goto end;
+ default:
+ goto end;
+ }
+
+ outbound_id = switch_channel_get_variable(consumer_channel, "fifo_outbound_uuid");
+
+ switch (msg->message_id) {
+ case SWITCH_MESSAGE_INDICATE_BRIDGE:
+ {
+
+ long epoch_start = 0;
+ char date[80] = "";
+ switch_time_t ts;
+ switch_time_exp_t tm;
+ switch_size_t retsize;
+ const char *ced_name, *ced_number, *cid_name, *cid_number;
+
+ if (switch_channel_test_app_flag(consumer_channel, CF_APP_TAGGED)) {
+ goto end;
+ }
+
+ switch_channel_set_app_flag(consumer_channel, CF_APP_TAGGED);
+
+ switch_channel_set_variable(consumer_channel, "fifo_bridged", "true");
+ switch_channel_set_variable(consumer_channel, "fifo_manual_bridge", "true");
+ switch_channel_set_variable(consumer_channel, "fifo_role", "consumer");
+
+ if (caller_channel) {
+ switch_channel_set_variable(caller_channel, "fifo_role", "caller");
+ switch_process_import(consumer_session, caller_channel, "fifo_caller_consumer_import");
+ switch_process_import(caller_session, consumer_channel, "fifo_consumer_caller_import");
+ }
+
+
+ ced_name = switch_channel_get_variable(consumer_channel, "callee_id_name");
+ ced_number = switch_channel_get_variable(consumer_channel, "callee_id_number");
+
+ cid_name = switch_channel_get_variable(consumer_channel, "caller_id_name");
+ cid_number = switch_channel_get_variable(consumer_channel, "caller_id_number");
+
+ if (switch_channel_direction(consumer_channel) == SWITCH_CALL_DIRECTION_INBOUND) {
+ if (zstr(ced_name) || !strcmp(ced_name, cid_name)) {
+ ced_name = ced_number;
+ }
+
+ if (zstr(ced_number) || !strcmp(ced_number, cid_number)) {
+ ced_name = switch_channel_get_variable(consumer_channel, "destination_number");
+ ced_number = ced_name;
+ }
+ } else {
+ ced_name = cid_name;
+ ced_number = cid_number;
+ }
+
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(consumer_channel, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", MANUAL_QUEUE_NAME);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-consumer-start");
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-CID-Name", ced_name);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-CID-Number", ced_number);
+ switch_event_fire(&event);
+ }
+
+ if (caller_channel) {
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(caller_channel, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", MANUAL_QUEUE_NAME);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-caller-start");
+ switch_event_fire(&event);
+ }
+
+ sql = switch_mprintf("insert into fifo_bridge "
+ "(fifo_name,caller_uuid,caller_caller_id_name,caller_caller_id_number,consumer_uuid,consumer_outgoing_uuid,bridge_start) "
+ "values ('%q','%q','%q','%q','%q','%q',%ld)",
+ MANUAL_QUEUE_NAME,
+ switch_core_session_get_uuid(caller_session),
+ ced_name,
+ ced_number,
+ switch_core_session_get_uuid(session),
+ switch_str_nil(outbound_id),
+ (long) switch_epoch_time_now(NULL)
+ );
+ } else {
+ sql = switch_mprintf("insert into fifo_bridge "
+ "(fifo_name,caller_uuid,caller_caller_id_name,caller_caller_id_number,consumer_uuid,consumer_outgoing_uuid,bridge_start) "
+ "values ('%q','%q','%q','%q','%q','%q',%ld)",
+ MANUAL_QUEUE_NAME,
+ "N/A",
+ ced_name,
+ ced_number,
+ switch_core_session_get_uuid(session),
+ switch_str_nil(outbound_id),
+ (long) switch_epoch_time_now(NULL)
+ );
+ }
+
+ fifo_execute_sql(sql, globals.sql_mutex);
+ switch_safe_free(sql);
+
+
+ epoch_start = (long)switch_epoch_time_now(NULL);
+
+ ts = switch_micro_time_now();
+ switch_time_exp_lt(&tm, ts);
+ epoch_start = (long)switch_epoch_time_now(NULL);
+ switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
+ switch_channel_set_variable(consumer_channel, "fifo_status", "TALKING");
+ if (caller_session) {
+ switch_channel_set_variable(consumer_channel, "fifo_target", switch_core_session_get_uuid(caller_session));
+ }
+ switch_channel_set_variable(consumer_channel, "fifo_timestamp", date);
+ switch_channel_set_variable_printf(consumer_channel, "fifo_epoch_start_bridge", "%ld", epoch_start);
+ switch_channel_set_variable(consumer_channel, "fifo_role", "consumer");
+
+ if (caller_channel) {
+ switch_channel_set_variable(caller_channel, "fifo_status", "TALKING");
+ switch_channel_set_variable(caller_channel, "fifo_timestamp", date);
+ switch_channel_set_variable_printf(caller_channel, "fifo_epoch_start_bridge", "%ld", epoch_start);
+ switch_channel_set_variable(caller_channel, "fifo_target", switch_core_session_get_uuid(session));
+ switch_channel_set_variable(caller_channel, "fifo_role", "caller");
+ }
+ }
+ break;
+ case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
+ {
+ if (switch_channel_test_app_flag(consumer_channel, CF_APP_TAGGED)) {
+ char date[80] = "";
+ switch_time_exp_t tm;
+ switch_time_t ts = switch_micro_time_now();
+ switch_size_t retsize;
+ long epoch_start = 0, epoch_end = 0;
+ const char *epoch_start_a = NULL;
+
+ switch_channel_clear_app_flag(consumer_channel, CF_APP_TAGGED);
+ switch_channel_set_variable(consumer_channel, "fifo_bridged", NULL);
+
+ ts = switch_micro_time_now();
+ switch_time_exp_lt(&tm, ts);
+ switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
+
+ sql = switch_mprintf("delete from fifo_bridge where consumer_uuid='%q'", switch_core_session_get_uuid(consumer_session));
+ fifo_execute_sql(sql, globals.sql_mutex);
+ switch_safe_free(sql);
+
+
+
+ switch_channel_set_variable(consumer_channel, "fifo_status", "WAITING");
+ switch_channel_set_variable(consumer_channel, "fifo_timestamp", date);
+
+ if (caller_channel) {
+ switch_channel_set_variable(caller_channel, "fifo_status", "DONE");
+ switch_channel_set_variable(caller_channel, "fifo_timestamp", date);
+ }
+
+ if ((epoch_start_a = switch_channel_get_variable(consumer_channel, "fifo_epoch_start_bridge"))) {
+ epoch_start = atol(epoch_start_a);
+ }
+
+ epoch_end = (long)switch_epoch_time_now(NULL);
+
+ switch_channel_set_variable_printf(consumer_channel, "fifo_epoch_stop_bridge", "%ld", epoch_end);
+ switch_channel_set_variable_printf(consumer_channel, "fifo_bridge_seconds", "%d", epoch_end - epoch_start);
+
+ if (caller_channel) {
+ switch_channel_set_variable_printf(caller_channel, "fifo_epoch_stop_bridge", "%ld", epoch_end);
+ switch_channel_set_variable_printf(caller_channel, "fifo_bridge_seconds", "%d", epoch_end - epoch_start);
+ }
+
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(consumer_channel, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", MANUAL_QUEUE_NAME);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-consumer-stop");
+ switch_event_fire(&event);
+ }
+
+ if (caller_channel) {
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(caller_channel, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", MANUAL_QUEUE_NAME);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-caller-stop");
+ switch_event_fire(&event);
+ }
+ }
+
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(consumer_channel, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", MANUAL_QUEUE_NAME);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "consumer_stop");
+ switch_event_fire(&event);
+ }
+ }
+
+ }
+ break;
+ default:
+ break;
+ }
+
+ end:
+
+ if (caller_session) {
+ switch_core_session_rwunlock(caller_session);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+static void add_outbound_call(const char *key, switch_call_cause_t *cancel_cause)
+{
+ switch_mutex_lock(globals.orig_mutex);
+ switch_core_hash_insert(globals.orig_hash, key, cancel_cause);
+ switch_mutex_unlock(globals.orig_mutex);
+}
+
+static void del_outbound_call(const char *key)
+{
+ switch_mutex_lock(globals.orig_mutex);
+ switch_core_hash_delete(globals.orig_hash, key);
+ switch_mutex_unlock(globals.orig_mutex);
+}
+
+static void cancel_outbound_call(const char *key, switch_call_cause_t cause)
+{
+ switch_call_cause_t *cancel_cause = NULL;
+
+ switch_mutex_lock(globals.orig_mutex);
+ if ((cancel_cause = (switch_call_cause_t *) switch_core_hash_find(globals.orig_hash, key))) {
+ *cancel_cause = cause;
+ }
+ switch_mutex_unlock(globals.orig_mutex);
+}
static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void *obj)
{
@@ -678,6 +953,7 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void
int i = 0;
int timeout = 0;
switch_stream_handle_t stream = { 0 };
+ switch_stream_handle_t stream2 = { 0 };
fifo_node_t *node = NULL;
char *originate_string = NULL;
switch_event_t *ovars = NULL;
@@ -688,17 +964,20 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void
switch_caller_extension_t *extension = NULL;
switch_channel_t *channel;
char *caller_id_name = NULL, *cid_num = NULL, *id = NULL;
- switch_event_t *pop = NULL;
+ switch_event_t *pop = NULL, *pop_dup = NULL;
fifo_queue_t *q = NULL;
int x = 0;
switch_event_t *event;
switch_uuid_t uuid;
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
+ switch_call_cause_t cancel_cause = 0;
+ char *uuid_list = NULL;
+ int connected = 0;
+ const char *codec;
switch_uuid_get(&uuid);
switch_uuid_format(uuid_str, &uuid);
-
-
+
if (!cbh->rowcount) {
goto end;
}
@@ -711,14 +990,15 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void
if (node) {
switch_mutex_lock(node->mutex);
- node->busy++;
- node->ring_consumer_count++;
+ node->busy = switch_epoch_time_now(NULL) + 600;
+ node->ring_consumer_count = 1;
switch_mutex_unlock(node->mutex);
} else {
goto end;
}
SWITCH_STANDARD_STREAM(stream);
+ SWITCH_STANDARD_STREAM(stream2);
switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS);
switch_assert(ovars);
@@ -729,69 +1009,65 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void
char *parsed = NULL;
switch_event_create_brackets(h->originate_string, '{', '}', ',', &ovars, &parsed);
+ switch_event_del_header(ovars, "fifo_outbound_uuid");
if (!h->timeout) h->timeout = 60;
if (timeout < h->timeout) timeout = h->timeout;
stream.write_function(&stream, "[leg_timeout=%d,fifo_outbound_uuid=%s]%s,", h->timeout, h->uuid, parsed ? parsed : h->originate_string);
+ stream2.write_function(&stream2, "%s,", h->uuid);
switch_safe_free(parsed);
}
-
originate_string = (char *) stream.data;
if (originate_string) {
end_of(originate_string) = '\0';
}
+ uuid_list = (char *) stream2.data;
+
+ if (uuid_list) {
+ end_of(uuid_list) = '\0';
+ }
+
if (!timeout) timeout = 60;
+ pop = pop_dup = NULL;
+
for (x = 0; x < MAX_PRI; x++) {
q = node->fifo_list[x];
- switch_mutex_lock(q->mutex);
-
- if (fifo_queue_pop_nameval(q, "variable_fifo_vip", "true", &pop, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS && pop) {
- goto found;
+ if (fifo_queue_pop_nameval(q, "variable_fifo_vip", "true", &pop_dup, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS && pop_dup) {
+ pop = pop_dup;
+ break;
}
- switch_mutex_unlock(q->mutex);
- q = NULL;
}
if (!pop) {
for (x = 0; x < MAX_PRI; x++) {
q = node->fifo_list[x];
- switch_mutex_lock(q->mutex);
-
- if (fifo_queue_pop(node->fifo_list[x], &pop, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS && pop) {
- goto found;
+ if (fifo_queue_pop(node->fifo_list[x], &pop_dup, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS && pop_dup) {
+ pop = pop_dup;
+ break;
}
}
- switch_mutex_unlock(q->mutex);
- q = NULL;
}
- found:
-
-
- if (!q) goto end;
-
if (!pop) {
- if (q) switch_mutex_unlock(q->mutex);
goto end;
}
-
-
+
if (!switch_event_get_header(ovars, "origination_caller_id_name")) {
if ((caller_id_name = switch_event_get_header(pop, "caller-caller-id-name"))) {
- if (node->outbound_name) {
+ if (!zstr(node->outbound_name)) {
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "origination_caller_id_name", "(%s) %s", node->outbound_name, caller_id_name);
} else {
switch_event_add_header_string(ovars, SWITCH_STACK_BOTTOM, "origination_caller_id_name", caller_id_name);
}
}
}
-
+
if (!switch_event_get_header(ovars, "origination_caller_id_number")) {
if ((cid_num = switch_event_get_header(pop, "caller-caller-id-number"))) {
switch_event_add_header_string(ovars, SWITCH_STACK_BOTTOM, "origination_caller_id_number", cid_num);
@@ -804,6 +1080,7 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void
switch_event_add_header_string(ovars, SWITCH_STACK_BOTTOM, "fifo_originate_uuid", uuid_str);
+
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_core_session_t *session;
if (id && (session = switch_core_session_locate(id))) {
@@ -813,48 +1090,99 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void
switch_channel_event_set_data(channel, event);
switch_core_session_rwunlock(session);
}
-
+
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", node->name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "pre-dial");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "outbound-strategy", "ringall");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "caller-uuid", id);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "originate_string", originate_string);
-
- for (i = 0; i < cbh->rowcount; i++) {
- struct call_helper *h = cbh->rows[i];
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Outbound-UUID", h->uuid);
- }
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Outbound-UUID-List", uuid_list);
switch_event_fire(&event);
}
- switch_mutex_unlock(q->mutex);
- pop = NULL;
- status = switch_ivr_originate(NULL, &session, &cause, originate_string, timeout, NULL, NULL, NULL, NULL, ovars, SOF_NONE, NULL);
-
- if (status != SWITCH_STATUS_SUCCESS) {
- for (i = 0; i < cbh->rowcount; i++) {
- struct call_helper *h = cbh->rows[i];
- char *sql = switch_mprintf("update fifo_outbound set outbound_fail_count=outbound_fail_count+1, next_avail=%ld + lag where uuid='%q'",
- (long) switch_epoch_time_now(NULL), h->uuid);
- fifo_execute_sql(sql, globals.sql_mutex);
- switch_safe_free(sql);
-
- }
+ for (i = 0; i < cbh->rowcount; i++) {
+ struct call_helper *h = cbh->rows[i];
+ char *sql = switch_mprintf("update fifo_outbound set ring_count=ring_count+1 where uuid='%s'", h->uuid);
+ fifo_execute_sql(sql, globals.sql_mutex);
+ switch_safe_free(sql);
+ }
+
+ if ((codec = switch_event_get_header(pop, "variable_sip_use_codec_name"))) {
+ const char *rate = switch_event_get_header(pop, "variable_sip_use_codec_rate");
+ const char *ptime = switch_event_get_header(pop, "variable_sip_use_codec_ptime");
+ char nstr[256] = "";
+
+ if (strcasecmp(codec, "PCMU") && strcasecmp(codec, "PCMA")) {
+ switch_snprintf(nstr, sizeof(nstr), "%s@%si@%sh,PCMU,PCMA", codec, ptime, rate);
+ } else {
+ switch_snprintf(nstr, sizeof(nstr), "%s@%si@%sh", codec, ptime, rate);
+ }
+
+ switch_event_add_header_string(ovars, SWITCH_STACK_BOTTOM, "absolute_codec_string", nstr);
+ }
+
+ add_outbound_call(id, &cancel_cause);
+
+ status = switch_ivr_originate(NULL, &session, &cause, originate_string, timeout, NULL, NULL, NULL, NULL, ovars, SOF_NONE, &cancel_cause);
+
+ del_outbound_call(id);
+
+
+ if (status != SWITCH_STATUS_SUCCESS || cause != SWITCH_CAUSE_SUCCESS) {
+ const char *acceptable = "false";
+
+ switch (cause) {
+ case SWITCH_CAUSE_ORIGINATOR_CANCEL:
+ case SWITCH_CAUSE_PICKED_OFF:
+ {
+ acceptable = "true";
+
+ for (i = 0; i < cbh->rowcount; i++) {
+ struct call_helper *h = cbh->rows[i];
+ char *sql = switch_mprintf("update fifo_outbound set ring_count=ring_count-1 "
+ "where uuid='%q' and ring_count > 0", h->uuid);
+ fifo_execute_sql(sql, globals.sql_mutex);
+ switch_safe_free(sql);
+ }
+
+ }
+ break;
+ default:
+ {
+ for (i = 0; i < cbh->rowcount; i++) {
+ struct call_helper *h = cbh->rows[i];
+ char *sql = switch_mprintf("update fifo_outbound set ring_count=ring_count-1, "
+ "outbound_fail_count=outbound_fail_count+1, "
+ "outbound_fail_total_count = outbound_fail_total_count+1, "
+ "next_avail=%ld + lag where uuid='%q' and ring_count > 0",
+ (long) switch_epoch_time_now(NULL), h->uuid);
+ fifo_execute_sql(sql, globals.sql_mutex);
+ switch_safe_free(sql);
+
+ }
+ }
+ }
+
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", node->name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "post-dial");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "outbound-strategy", "ringall");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "caller-uuid", id);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "result", "failure");
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "acceptable", acceptable);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "cause", switch_channel_cause2str(cause));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "originate_string", originate_string);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Outbound-UUID-List", uuid_list);
switch_event_fire(&event);
}
+
goto end;
}
+ connected = 1;
+
channel = switch_core_session_get_channel(session);
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
@@ -864,6 +1192,7 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "outbound-strategy", "ringall");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "caller-uuid", id);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Outbound-UUID", switch_channel_get_variable(channel, "fifo_outbound_uuid"));
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Outbound-UUID-List", uuid_list);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "result", "success");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "originate_string", originate_string);
switch_event_fire(&event);
@@ -878,19 +1207,31 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void
switch_caller_extension_add_application(session, extension, app_name, arg);
switch_channel_set_caller_extension(channel, extension);
switch_channel_set_state(channel, CS_EXECUTE);
+ switch_channel_wait_for_state(channel, NULL, CS_EXECUTE);
switch_core_session_rwunlock(session);
+
+ for (i = 0; i < cbh->rowcount; i++) {
+ struct call_helper *h = cbh->rows[i];
+ char *sql = switch_mprintf("update fifo_outbound set ring_count=ring_count-1 where uuid='%q' and ring_count > 0", h->uuid);
+ fifo_execute_sql(sql, globals.sql_mutex);
+ switch_safe_free(sql);
+ }
end:
switch_safe_free(originate_string);
+ switch_safe_free(uuid_list);
switch_event_destroy(&ovars);
+
+ if (pop_dup) {
+ switch_event_destroy(&pop_dup);
+ }
+
if (node) {
switch_mutex_lock(node->mutex);
- if (node->ring_consumer_count-- < 0) {
- node->ring_consumer_count = 0;
- }
- if (node->busy) node->busy--;
+ node->ring_consumer_count = 0;
+ node->busy = switch_epoch_time_now(NULL) + connected;
switch_mutex_unlock(node->mutex);
}
@@ -913,7 +1254,9 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj)
switch_event_t *ovars = NULL;
switch_status_t status = SWITCH_STATUS_FALSE;
switch_event_t *event = NULL;
-
+ char *sql = NULL;
+ int connected = 0;
+
switch_mutex_lock(globals.mutex);
node = switch_core_hash_find(globals.fifo_hash, h->node_name);
switch_mutex_unlock(globals.mutex);
@@ -921,7 +1264,7 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj)
if (node) {
switch_mutex_lock(node->mutex);
node->ring_consumer_count++;
- node->busy++;
+ node->busy = switch_epoch_time_now(NULL) + 600;
switch_mutex_unlock(node->mutex);
}
@@ -933,7 +1276,7 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj)
originate_string = switch_mprintf("{execute_on_answer='unset fifo_hangup_check',fifo_hangup_check='%q'}%s",
node->name, h->originate_string);
} else {
- if (node->outbound_name) {
+ if (!zstr(node->outbound_name)) {
originate_string = switch_mprintf("{execute_on_answer='unset fifo_hangup_check',fifo_hangup_check='%q',"
"origination_caller_id_name=Queue,origination_caller_id_number='Queue: %q'}%s",
node->name, node->outbound_name, h->originate_string);
@@ -954,13 +1297,22 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj)
switch_event_fire(&event);
}
+
+ sql = switch_mprintf("update fifo_outbound set ring_count=ring_count+1 where uuid='%s'", h->uuid);
+ fifo_execute_sql(sql, globals.sql_mutex);
+ switch_safe_free(sql);
status = switch_ivr_originate(NULL, &session, &cause, originate_string, h->timeout, NULL, NULL, NULL, NULL, ovars, SOF_NONE, NULL);
free(originate_string);
-
if (status != SWITCH_STATUS_SUCCESS) {
+ sql = switch_mprintf("update fifo_outbound set ring_count=ring_count-1, "
+ "outbound_fail_count=outbound_fail_count+1, next_avail=%ld + lag where uuid='%q' and use_count > 0",
+ (long) switch_epoch_time_now(NULL), h->uuid);
+ fifo_execute_sql(sql, globals.sql_mutex);
+ switch_safe_free(sql);
+
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", node->name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "post-dial");
@@ -975,6 +1327,8 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj)
goto end;
}
+ connected = 1;
+
channel = switch_core_session_get_channel(session);
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
@@ -1012,7 +1366,7 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj)
if (node->ring_consumer_count-- < 0) {
node->ring_consumer_count = 0;
}
- if (node->busy) node->busy--;
+ node->busy = switch_epoch_time_now(NULL) + connected;
switch_mutex_unlock(node->mutex);
}
switch_core_destroy_memory_pool(&h->pool);
@@ -1034,11 +1388,14 @@ static int place_call_ringall_callback(void *pArg, int argc, char **argv, char *
cbh->rows[cbh->rowcount++] = h;
- cbh->need--;
-
if (cbh->rowcount == MAX_ROWS) return -1;
-
- return cbh->need ? 0 : -1;
+
+ if (cbh->need) {
+ cbh->need--;
+ return cbh->need ? 0 : -1;
+ }
+
+ return 0;
}
@@ -1079,7 +1436,7 @@ static void find_consumers(fifo_node_t *node)
sql = switch_mprintf("select uuid, fifo_name, originate_string, simo_count, use_count, timeout, lag, "
"next_avail, expires, static, outbound_call_count, outbound_fail_count, hostname "
"from fifo_outbound "
- "where taking_calls = 1 and (fifo_name = '%q') and (use_count < simo_count) and (next_avail = 0 or next_avail <= %ld) "
+ "where taking_calls = 1 and (fifo_name = '%q') and ((use_count+ring_count) < simo_count) and (next_avail = 0 or next_avail <= %ld) "
"order by next_avail, outbound_fail_count, outbound_call_count",
node->name, (long) switch_epoch_time_now(NULL)
);
@@ -1109,9 +1466,9 @@ static void find_consumers(fifo_node_t *node)
switch_core_new_memory_pool(&pool);
cbh = switch_core_alloc(pool, sizeof(*cbh));
cbh->pool = pool;
- cbh->need = node_consumer_wait_count(node);
+ cbh->need = 1;
- if (node->outbound_per_cycle && node->outbound_per_cycle < cbh->need) {
+ if (node->outbound_per_cycle != cbh->need) {
cbh->need = node->outbound_per_cycle;
}
@@ -1150,8 +1507,8 @@ static void *SWITCH_THREAD_FUNC node_thread_run(switch_thread_t *thread, void *o
for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &var, NULL, &val);
if ((node = (fifo_node_t *) val)) {
- if (node->has_outbound && node->ready && !node->busy) {
- switch_mutex_lock(node->mutex);
+ switch_mutex_lock(node->mutex);
+ if (node->has_outbound && node->ready && switch_epoch_time_now(NULL) > node->busy) {
ppl_waiting = node_consumer_wait_count(node);
consumer_total = node->consumer_count;
idle_consumers = node_idle_consumers(node);
@@ -1162,8 +1519,8 @@ static void *SWITCH_THREAD_FUNC node_thread_run(switch_thread_t *thread, void *o
if ((ppl_waiting - node->ring_consumer_count > 0) && (!consumer_total || !idle_consumers)) {
find_consumers(node);
}
- switch_mutex_unlock(node->mutex);
}
+ switch_mutex_unlock(node->mutex);
}
}
switch_mutex_unlock(globals.mutex);
@@ -1206,32 +1563,35 @@ static int stop_node_thread(void)
static void check_ocancel(switch_core_session_t *session)
{
- switch_channel_t *channel;
- const char *var;
+ //switch_channel_t *channel;
+ //const char *var;
switch_assert(session);
- channel = switch_core_session_get_channel(session);
+ //channel = switch_core_session_get_channel(session);
+
+ cancel_outbound_call(switch_core_session_get_uuid(session), SWITCH_CAUSE_ORIGINATOR_CANCEL);
- if (!switch_channel_test_flag(channel, CF_TRANSFER) && (var = switch_channel_get_variable(channel, "fifo_originate_uuid"))) {
- switch_core_session_hupall_matching_var("fifo_originate_uuid", var,
- switch_channel_test_flag(channel, CF_ANSWERED) ?
- SWITCH_CAUSE_NORMAL_CLEARING : SWITCH_CAUSE_ORIGINATOR_CANCEL);
- }
}
static void check_cancel(fifo_node_t *node)
{
- int ppl_waiting = node_consumer_wait_count(node);
+ int ppl_waiting;
- if (node->ring_consumer_count > 0 && ppl_waiting < 1) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Outbound call count (%d) exceeds required value for queue %s (%d), "
- "Ending extraneous calls\n", node->ring_consumer_count, node->name, ppl_waiting);
-
-
- switch_core_session_hupall_matching_var("fifo_hangup_check", node->name, SWITCH_CAUSE_ORIGINATOR_CANCEL);
+ if (node->outbound_strategy != NODE_STRATEGY_ENTERPRISE) {
+ return;
}
+
+ ppl_waiting = node_consumer_wait_count(node);
+
+ if (node->ring_consumer_count > 0 && ppl_waiting < 1) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Outbound call count (%d) exceeds required value for queue %s (%d), "
+ "Ending extraneous calls\n", node->ring_consumer_count, node->name, ppl_waiting);
+
+
+ switch_core_session_hupall_matching_var("fifo_hangup_check", node->name, SWITCH_CAUSE_ORIGINATOR_CANCEL);
+ }
}
static void send_presence(fifo_node_t *node)
@@ -1324,7 +1684,6 @@ static uint32_t fifo_add_outbound(const char *node_name, const char *url, uint32
}
-
SWITCH_STANDARD_API(fifo_add_outbound_function)
{
char *data = NULL, *argv[4] = { 0 };
@@ -1363,6 +1722,91 @@ SWITCH_STANDARD_API(fifo_add_outbound_function)
}
+static void dec_use_count(switch_channel_t *channel)
+{
+ char *sql;
+ const char *outbound_id;
+ switch_event_t *event;
+ long now = (long) switch_epoch_time_now(NULL);
+
+ if ((outbound_id = switch_channel_get_variable(channel, "fifo_outbound_uuid"))) {
+ sql = switch_mprintf("update fifo_outbound set use_count=use_count-1, stop_time=%ld, next_avail=%ld + lag where use_count > 0 and uuid='%q'",
+ now, now, outbound_id);
+ fifo_execute_sql(sql, globals.sql_mutex);
+ switch_safe_free(sql);
+ }
+
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(channel, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", MANUAL_QUEUE_NAME);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-consumer-stop");
+ switch_event_fire(&event);
+ }
+
+
+}
+
+static switch_status_t hanguphook(switch_core_session_t *session)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_channel_state_t state = switch_channel_get_state(channel);
+
+ if (state == CS_HANGUP) {
+ dec_use_count(channel);
+ switch_core_event_hook_remove_state_change(session, hanguphook);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_STANDARD_APP(fifo_track_call_function)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ char *sql;
+ const char *col1 = NULL, *col2 = NULL, *cid_name, *cid_number;
+ switch_event_t *event;
+
+ if (zstr(data)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid!\n");
+ return;
+ }
+
+ switch_channel_set_variable(channel, "fifo_outbound_uuid", data);
+
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
+ col1 = "manual_calls_in_count";
+ col2 = "manual_calls_in_total_count";
+ } else {
+ col1 = "manual_calls_out_count";
+ col2 = "manual_calls_out_total_count";
+ }
+
+ sql = switch_mprintf("update fifo_outbound set start_time=%ld,outbound_fail_count=0,use_count=use_count+1,%s=%s+1,%s=%s+1 where uuid='%q'",
+ (long) switch_epoch_time_now(NULL), col1, col1, col2, col2, data);
+ fifo_execute_sql(sql, globals.sql_mutex);
+ switch_safe_free(sql);
+
+
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
+ cid_name = switch_channel_get_variable(channel, "destination_number");
+ cid_number = cid_name;
+ } else {
+ cid_name = switch_channel_get_variable(channel, "caller_id_name");
+ cid_number = switch_channel_get_variable(channel, "caller_id_number");
+ }
+
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(channel, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", MANUAL_QUEUE_NAME);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-consumer-start");
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-CID-Name", cid_name);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-CID-Number", cid_number);
+ switch_event_fire(&event);
+ }
+
+ switch_core_event_hook_add_receive_message(session, messagehook);
+ switch_core_event_hook_add_state_change(session, hanguphook);
+}
typedef enum {
STRAT_MORE_PPL,
@@ -1394,6 +1838,11 @@ SWITCH_STANDARD_APP(fifo_function)
const char *arg_inout = NULL;
const char *serviced_uuid = NULL;
+ if (switch_core_event_hook_remove_receive_message(session, messagehook) == SWITCH_STATUS_SUCCESS) {
+ dec_use_count(channel);
+ switch_core_event_hook_remove_state_change(session, hanguphook);
+ }
+
if (!globals.running) {
return;
}
@@ -1725,8 +2174,9 @@ SWITCH_STANDARD_APP(fifo_function)
const char *caller_uuid = NULL;
switch_event_t *call_event;
const char *outbound_id = switch_channel_get_variable(channel, "fifo_outbound_uuid");
-
-
+ //const char *track_use_count = switch_channel_get_variable(channel, "fifo_track_use_count");
+ //int do_track = switch_true(track_use_count);
+
if (!zstr(strat_str)) {
if (!strcasecmp(strat_str, "more_ppl")) {
strat = STRAT_MORE_PPL;
@@ -1853,6 +2303,7 @@ SWITCH_STANDARD_APP(fifo_function)
if ((varval = switch_channel_get_variable(channel, "fifo_bridge_uuid"))) {
for (x = 0; x < MAX_PRI; x++) {
if (fifo_queue_pop_nameval(node->fifo_list[pop_array[x]], "unique-id", varval, &pop, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS && pop) {
+ cancel_outbound_call(varval, SWITCH_CAUSE_PICKED_OFF);
break;
}
}
@@ -1973,7 +2424,8 @@ SWITCH_STANDARD_APP(fifo_function)
const char *record_template = switch_channel_get_variable(channel, "fifo_record_template");
char *expanded = NULL;
char *sql = NULL;
-
+ long epoch_start, epoch_end;
+
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
@@ -2040,14 +2492,19 @@ SWITCH_STANDARD_APP(fifo_function)
ts = switch_micro_time_now();
switch_time_exp_lt(&tm, ts);
+ epoch_start = (long)switch_epoch_time_now(NULL);
switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
switch_channel_set_variable(channel, "fifo_status", "TALKING");
switch_channel_set_variable(channel, "fifo_target", caller_uuid);
switch_channel_set_variable(channel, "fifo_timestamp", date);
+ switch_channel_set_variable_printf(channel, "fifo_epoch_start_bridge", "%ld", epoch_start);
+ switch_channel_set_variable(channel, "fifo_role", "consumer");
switch_channel_set_variable(other_channel, "fifo_status", "TALKING");
switch_channel_set_variable(other_channel, "fifo_timestamp", date);
+ switch_channel_set_variable_printf(other_channel, "fifo_epoch_start_bridge", "%ld", epoch_start);
switch_channel_set_variable(other_channel, "fifo_target", switch_core_session_get_uuid(session));
+ switch_channel_set_variable(other_channel, "fifo_role", "caller");
send_presence(node);
@@ -2063,19 +2520,19 @@ SWITCH_STANDARD_APP(fifo_function)
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-consumer");
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-consumer-start");
switch_event_fire(&event);
}
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(other_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-caller");
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-caller-start");
switch_event_fire(&event);
}
if (outbound_id) {
- sql = switch_mprintf("update fifo_outbound set use_count=use_count+1,outbound_fail_count=0 where uuid='%s'", outbound_id);
-
+ sql = switch_mprintf("update fifo_outbound set start_time=%ld,use_count=use_count+1,outbound_fail_count=0 where uuid='%s'",
+ switch_epoch_time_now(NULL), outbound_id);
fifo_execute_sql(sql, globals.sql_mutex);
switch_safe_free(sql);
}
@@ -2097,14 +2554,42 @@ SWITCH_STANDARD_APP(fifo_function)
switch_safe_free(sql);
switch_ivr_multi_threaded_bridge(session, other_session, on_dtmf, other_session, session);
-
+
if (outbound_id) {
- sql = switch_mprintf("update fifo_outbound set use_count=use_count-1, outbound_call_count=outbound_call_count+1, next_avail=%ld + lag where uuid='%s' and use_count > 0", (long) switch_epoch_time_now(NULL), outbound_id);
+ long now = (long) switch_epoch_time_now(NULL);
+
+ sql = switch_mprintf("update fifo_outbound set stop_time=%ld, use_count=use_count-1, "
+ "outbound_call_total_count=outbound_call_total_count+1, "
+ "outbound_call_count=outbound_call_count+1, next_avail=%ld + lag where uuid='%s' and use_count > 0",
+ now, now, outbound_id);
fifo_execute_sql(sql, globals.sql_mutex);
switch_safe_free(sql);
}
+
+
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(channel, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-consumer-stop");
+ switch_event_fire(&event);
+ }
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(other_channel, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-caller-stop");
+ switch_event_fire(&event);
+ }
+
+ epoch_end = (long)switch_epoch_time_now(NULL);
+
+ switch_channel_set_variable_printf(channel, "fifo_epoch_stop_bridge", "%ld", epoch_end);
+ switch_channel_set_variable_printf(channel, "fifo_bridge_seconds", "%d", epoch_end - epoch_start);
+
+ switch_channel_set_variable_printf(other_channel, "fifo_epoch_stop_bridge", "%ld", epoch_end);
+ switch_channel_set_variable_printf(other_channel, "fifo_bridge_seconds", "%d", epoch_end - epoch_start);
+
sql = switch_mprintf("delete from fifo_bridge where consumer_uuid='%q'", switch_core_session_get_uuid(session));
fifo_execute_sql(sql, globals.sql_mutex);
switch_safe_free(sql);
@@ -2274,12 +2759,22 @@ struct xml_helper {
static int xml_callback(void *pArg, int argc, char **argv, char **columnNames)
{
struct xml_helper *h = (struct xml_helper *) pArg;
- switch_xml_t x_tmp, x_out;
+ switch_xml_t x_out;
int c_off = 0;
char exp_buf[128] = "";
switch_time_exp_t tm;
switch_time_t etime = 0;
- char *expires = exp_buf;
+ char atime[128] = "";
+ char *expires = exp_buf, *tb = atime;
+ int arg = 0;
+
+ for(arg = 0; arg < argc; arg++) {
+ if (!argv[arg]) {
+ argv[arg] = "";
+ }
+ }
+
+ arg = 0;
if (argv[7]) {
if ((etime = atol(argv[7]))) {
@@ -2292,9 +2787,24 @@ static int xml_callback(void *pArg, int argc, char **argv, char **columnNames)
}
}
- x_tmp = switch_xml_add_child_d(h->xml, h->container, h->cc_off++);
- x_out = switch_xml_add_child_d(x_tmp, h->tag, c_off++);
+ if (atoi(argv[13])) {
+ arg = 17;
+ } else {
+ arg = 18;
+ }
+
+
+ if ((etime = atol(argv[arg]))) {
+ switch_size_t retsize;
+ switch_time_exp_lt(&tm, switch_time_from_sec(etime));
+ switch_strftime_nocheck(atime, &retsize, sizeof(atime), "%Y-%m-%d %T", &tm);
+ } else {
+ switch_set_string(atime, "now");
+ }
+
+
+ x_out = switch_xml_add_child_d(h->xml, h->tag, c_off++);
switch_xml_set_attr_d(x_out, "simo", argv[3]);
switch_xml_set_attr_d(x_out, "use_count", argv[4]);
switch_xml_set_attr_d(x_out, "timeout", argv[5]);
@@ -2303,6 +2813,46 @@ static int xml_callback(void *pArg, int argc, char **argv, char **columnNames)
switch_xml_set_attr_d(x_out, "outbound-fail-count", argv[11]);
switch_xml_set_attr_d(x_out, "taking-calls", argv[13]);
switch_xml_set_attr_d(x_out, "status", argv[14]);
+
+ switch_xml_set_attr_d(x_out, "outbound-call-total-count", argv[15]);
+ switch_xml_set_attr_d(x_out, "outbound-fail-total-count", argv[16]);
+
+ if (arg == 17) {
+ switch_xml_set_attr_d(x_out, "logged-on-since", tb);
+ } else {
+ switch_xml_set_attr_d(x_out, "logged-off-since", tb);
+ }
+
+ switch_xml_set_attr_d(x_out, "manual-calls-out-count", argv[19]);
+ switch_xml_set_attr_d(x_out, "manual-calls-in-count", argv[20]);
+ switch_xml_set_attr_d(x_out, "manual-calls-out-total-count", argv[21]);
+ switch_xml_set_attr_d(x_out, "manual-calls-in-total-count", argv[22]);
+
+ if (argc > 23) {
+ switch_xml_set_attr_d(x_out, "ring-count", argv[23]);
+
+ if ((etime = atol(argv[24]))) {
+ switch_size_t retsize;
+ switch_time_exp_lt(&tm, switch_time_from_sec(etime));
+ switch_strftime_nocheck(atime, &retsize, sizeof(atime), "%Y-%m-%d %T", &tm);
+ } else {
+ switch_set_string(atime, "never");
+ }
+
+ switch_xml_set_attr_d(x_out, "start-time", tb);
+
+ if ((etime = atol(argv[25]))) {
+ switch_size_t retsize;
+ switch_time_exp_lt(&tm, switch_time_from_sec(etime));
+ switch_strftime_nocheck(atime, &retsize, sizeof(atime), "%Y-%m-%d %T", &tm);
+ } else {
+ switch_set_string(atime, "never");
+ }
+
+ switch_xml_set_attr_d(x_out, "stop-time", tb);
+ }
+
+
switch_xml_set_attr_d(x_out, "next-available", expires);
switch_xml_set_txt_d(x_out, argv[2]);
@@ -2313,9 +2863,30 @@ static int xml_callback(void *pArg, int argc, char **argv, char **columnNames)
static int xml_outbound(switch_xml_t xml, fifo_node_t *node, char *container, char *tag, int cc_off, int verbose)
{
struct xml_helper h = { 0 };
- char *sql = switch_mprintf("select uuid, fifo_name, originate_string, simo_count, use_count, timeout, "
- "lag, next_avail, expires, static, outbound_call_count, outbound_fail_count, "
- "hostname, taking_calls, status from fifo_outbound where fifo_name = '%q'", node->name);
+ char *sql;
+
+ if (!strcmp(node->name, MANUAL_QUEUE_NAME)) {
+
+ sql = switch_mprintf("select uuid, '%s', originate_string, simo_count, use_count, timeout,"
+ "lag, next_avail, expires, static, outbound_call_count, outbound_fail_count,"
+ "hostname, taking_calls, status, outbound_call_total_count, outbound_fail_total_count, active_time, inactive_time,"
+ "manual_calls_out_count, manual_calls_in_count, manual_calls_out_total_count, manual_calls_in_total_count from fifo_outbound "
+ "group by "
+ "uuid, originate_string, simo_count, use_count, timeout,"
+ "lag, next_avail, expires, static, outbound_call_count, outbound_fail_count,"
+ "hostname, taking_calls, status, outbound_call_total_count, outbound_fail_total_count, active_time, inactive_time,"
+ "manual_calls_out_count, manual_calls_in_count, manual_calls_out_total_count, manual_calls_in_total_count",
+ MANUAL_QUEUE_NAME);
+
+
+ } else {
+ sql = switch_mprintf("select uuid, fifo_name, originate_string, simo_count, use_count, timeout, "
+ "lag, next_avail, expires, static, outbound_call_count, outbound_fail_count, "
+ "hostname, taking_calls, status, outbound_call_total_count, outbound_fail_total_count, active_time, inactive_time, "
+ "manual_calls_out_count, manual_calls_in_count, manual_calls_out_total_count, manual_calls_in_total_count,"
+ "ring_count,start_time,stop_time "
+ "from fifo_outbound where fifo_name = '%q'", node->name);
+ }
h.xml = xml;
h.node = node;
@@ -2325,6 +2896,8 @@ static int xml_outbound(switch_xml_t xml, fifo_node_t *node, char *container, ch
h.row_off = 0;
h.verbose = verbose;
+ h.xml = switch_xml_add_child_d(h.xml, h.container, h.cc_off++);
+
fifo_execute_sql_callback(globals.sql_mutex, sql, xml_callback, &h);
switch_safe_free(sql);
@@ -2748,14 +3321,25 @@ const char outbound_sql[] =
" use_count integer,\n"
" timeout integer,\n"
" lag integer,\n"
- " next_avail integer,\n"
- " expires integer,\n"
- " static integer,\n"
- " outbound_call_count integer,\n"
- " outbound_fail_count integer,\n"
+ " next_avail integer not null default 0,\n"
+ " expires integer not null default 0,\n"
+ " static integer not null default 0,\n"
+ " outbound_call_count integer not null default 0,\n"
+ " outbound_fail_count integer not null default 0,\n"
" hostname varchar(255),\n"
" taking_calls integer not null default 1,\n"
- " status varchar(255)\n"
+ " status varchar(255),\n"
+ " outbound_call_total_count integer not null default 0,\n"
+ " outbound_fail_total_count integer not null default 0,\n"
+ " active_time integer not null default 0,\n"
+ " inactive_time integer not null default 0,\n"
+ " manual_calls_out_count integer not null default 0,\n"
+ " manual_calls_in_count integer not null default 0,\n"
+ " manual_calls_out_total_count integer not null default 0,\n"
+ " manual_calls_in_total_count integer not null default 0,\n"
+ " ring_count integer not null default 0,\n"
+ " start_time integer not null default 0,\n"
+ " stop_time integer not null default 0\n"
");\n";
@@ -2772,6 +3356,26 @@ const char bridge_sql[] =
");\n"
;
+
+
+static void extract_fifo_outbound_uuid(char *string, char *uuid, switch_size_t len)
+{
+ switch_event_t *ovars;
+ char *parsed = NULL;
+ const char *fifo_outbound_uuid;
+
+ switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS);
+
+ switch_event_create_brackets(string, '{', '}', ',', &ovars, &parsed);
+
+ if ((fifo_outbound_uuid = switch_event_get_header(ovars, "fifo_outbound_uuid"))) {
+ switch_snprintf(uuid, len, "%s", fifo_outbound_uuid);
+ }
+
+ switch_safe_free(parsed);
+ switch_event_destroy(&ovars);
+}
+
static switch_status_t load_config(int reload, int del_all)
{
char *cf = "fifo.conf";
@@ -2780,6 +3384,7 @@ static switch_status_t load_config(int reload, int del_all)
char *sql;
switch_bool_t delete_all_outbound_member_on_startup = SWITCH_FALSE;
switch_cache_db_handle_t *dbh = NULL;
+ fifo_node_t *node;
gethostname(globals.hostname, sizeof(globals.hostname));
@@ -2829,10 +3434,14 @@ static switch_status_t load_config(int reload, int del_all)
goto done;
}
- switch_cache_db_test_reactive(dbh, "delete from fifo_outbound where static = 1 or taking_calls < 0", "drop table fifo_outbound", outbound_sql);
+ switch_cache_db_test_reactive(dbh, "delete from fifo_outbound where static = 1 or taking_calls < 0 or stop_time < 0",
+ "drop table fifo_outbound", outbound_sql);
switch_cache_db_test_reactive(dbh, "delete from fifo_bridge", "drop table fifo_bridge", bridge_sql);
switch_cache_db_release_db_handle(&dbh);
+ fifo_execute_sql("update fifo_outbound set start_time=0,stop_time=0,ring_count=0,use_count=0,"
+ "outbound_call_count=0,outbound_fail_count=0 where static=0", globals.sql_mutex);
+
if (reload) {
switch_hash_index_t *hi;
fifo_node_t *node;
@@ -2856,20 +3465,34 @@ static switch_status_t load_config(int reload, int del_all)
fifo_execute_sql(sql, globals.sql_mutex);
switch_safe_free(sql);
+ if (!(node = switch_core_hash_find(globals.fifo_hash, MANUAL_QUEUE_NAME))) {
+ node = create_node(MANUAL_QUEUE_NAME, 0, globals.sql_mutex);
+ node->is_static = 0;
+ }
if ((fifos = switch_xml_child(cfg, "fifos"))) {
for (fifo = switch_xml_child(fifos, "fifo"); fifo; fifo = fifo->next) {
const char *name, *outbound_strategy;
const char *val;
- int imp = 0, outbound_per_cycle = 0;
+ int imp = 0, outbound_per_cycle = 1;
int simo_i = 1;
int taking_calls_i = 1;
int timeout_i = 60;
int lag_i = 10;
- fifo_node_t *node;
name = switch_xml_attr(fifo, "name");
+
+ if (!name) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "fifo has no name!\n");
+ continue;
+ }
+
+ if (!strcasecmp(name, MANUAL_QUEUE_NAME)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s is a reserved name, use another name please.\n", MANUAL_QUEUE_NAME);
+ continue;
+ }
+
outbound_strategy = switch_xml_attr(fifo, "outbound_strategy");
@@ -2884,18 +3507,13 @@ static switch_status_t load_config(int reload, int del_all)
outbound_per_cycle = 0;
}
}
-
- if (!name) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "fifo has no name!\n");
- continue;
- }
-
+
switch_mutex_lock(globals.mutex);
if (!(node = switch_core_hash_find(globals.fifo_hash, name))) {
node = create_node(name, imp, globals.sql_mutex);
}
- if ((val = switch_xml_attr(fifo, "outbound_name"))) {
+ if ((val = switch_xml_attr(fifo, "outbound_name")) && !zstr(val)) {
node->outbound_name = switch_core_strdup(node->pool, val);
}
@@ -2919,8 +3537,13 @@ static switch_status_t load_config(int reload, int del_all)
const char *taking_calls = switch_xml_attr_soft(member, "taking_calls");
char *name_dup, *p;
char digest[SWITCH_MD5_DIGEST_STRING_SIZE] = { 0 };
- switch_md5_string(digest, (void *) member->txt, strlen(member->txt));
+ if (switch_stristr("fifo_outbound_uuid=", member->txt)) {
+ extract_fifo_outbound_uuid(member->txt, digest, sizeof(digest));
+ } else {
+ switch_md5_string(digest, (void *) member->txt, strlen(member->txt));
+ }
+
if (simo) {
simo_i = atoi(simo);
}
@@ -2952,9 +3575,11 @@ static switch_status_t load_config(int reload, int del_all)
sql = switch_mprintf("insert into fifo_outbound "
"(uuid, fifo_name, originate_string, simo_count, use_count, timeout, lag, "
- "next_avail, expires, static, outbound_call_count, outbound_fail_count, hostname, taking_calls) "
- "values ('%q','%q','%q',%d,%d,%d,%d,0,0,1,0,0,'%q',%d)",
- digest, node->name, member->txt, simo_i, 0, timeout_i, lag_i, globals.hostname, taking_calls_i);
+ "next_avail, expires, static, outbound_call_count, outbound_fail_count, hostname, taking_calls, "
+ "active_time, inactive_time) "
+ "values ('%q','%q','%q',%d,%d,%d,%d,0,0,1,0,0,'%q',%d,%ld,0)",
+ digest, node->name, member->txt, simo_i, 0, timeout_i, lag_i, globals.hostname, taking_calls_i,
+ (long) switch_epoch_time_now(NULL));
switch_assert(sql);
fifo_execute_sql(sql, globals.sql_mutex);
@@ -3023,7 +3648,11 @@ static void fifo_member_add(char *fifo_name, char *originate_string, int simo_co
char *sql, *name_dup, *p;
fifo_node_t *node = NULL;
- switch_md5_string(digest, (void *) originate_string, strlen(originate_string));
+ if (switch_stristr("fifo_outbound_uuid=", originate_string)) {
+ extract_fifo_outbound_uuid(originate_string, digest, sizeof(digest));
+ } else {
+ switch_md5_string(digest, (void *) originate_string, strlen(originate_string));
+ }
sql = switch_mprintf("delete from fifo_outbound where fifo_name='%q' and uuid = '%q'", fifo_name, digest);
switch_assert(sql);
@@ -3047,9 +3676,10 @@ static void fifo_member_add(char *fifo_name, char *originate_string, int simo_co
sql = switch_mprintf("insert into fifo_outbound "
"(uuid, fifo_name, originate_string, simo_count, use_count, timeout, "
- "lag, next_avail, expires, static, outbound_call_count, outbound_fail_count, hostname, taking_calls) "
- "values ('%q','%q','%q',%d,%d,%d,%d,%d,%ld,0,0,0,'%q',%d)",
- digest, fifo_name, originate_string, simo_count, 0, timeout, lag, 0, (long) expires, globals.hostname, taking_calls);
+ "lag, next_avail, expires, static, outbound_call_count, outbound_fail_count, hostname, taking_calls, active_time, inactive_time) "
+ "values ('%q','%q','%q',%d,%d,%d,%d,%d,%ld,0,0,0,'%q',%d,%ld,0)",
+ digest, fifo_name, originate_string, simo_count, 0, timeout, lag, 0, (long) expires, globals.hostname, taking_calls,
+ (long)switch_epoch_time_now(NULL));
switch_assert(sql);
fifo_execute_sql(sql, globals.sql_mutex);
free(sql);
@@ -3065,7 +3695,11 @@ static void fifo_member_del(char *fifo_name, char *originate_string)
callback_t cbt = { 0 };
fifo_node_t *node = NULL;
- switch_md5_string(digest, (void *) originate_string, strlen(originate_string));
+ if (switch_stristr("fifo_outbound_uuid=", originate_string)) {
+ extract_fifo_outbound_uuid(originate_string, digest, sizeof(digest));
+ } else {
+ switch_md5_string(digest, (void *) originate_string, strlen(originate_string));
+ }
sql = switch_mprintf("delete from fifo_outbound where fifo_name='%q' and uuid = '%q' and hostname='%q'", fifo_name, digest, globals.hostname);
switch_assert(sql);
@@ -3073,11 +3707,11 @@ static void fifo_member_del(char *fifo_name, char *originate_string)
free(sql);
switch_mutex_lock(globals.mutex);
- if (!(node = switch_core_hash_find(globals.fifo_hash, fifo_name))) {
- node = create_node(fifo_name, 0, globals.sql_mutex);
- node->ready = 1;
- }
- switch_mutex_unlock(globals.mutex);
+ if (!(node = switch_core_hash_find(globals.fifo_hash, fifo_name))) {
+ node = create_node(fifo_name, 0, globals.sql_mutex);
+ node->ready = 1;
+ }
+ switch_mutex_unlock(globals.mutex);
cbt.buf = outbound_count;
cbt.len = sizeof(outbound_count);
@@ -3196,6 +3830,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_fifo_load)
switch_core_new_memory_pool(&globals.pool);
switch_core_hash_init(&globals.fifo_hash, globals.pool);
+
+ switch_core_hash_init(&globals.orig_hash, globals.pool);
+ switch_mutex_init(&globals.orig_mutex, SWITCH_MUTEX_NESTED, globals.pool);
+
switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool);
switch_mutex_init(&globals.sql_mutex, SWITCH_MUTEX_NESTED, globals.pool);
@@ -3212,6 +3850,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_fifo_load)
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_APP(app_interface, "fifo", "Park with FIFO", FIFO_DESC, fifo_function, FIFO_USAGE, SAF_NONE);
+ SWITCH_ADD_APP(app_interface, "fifo_track_call", "Count a call as a fifo call in the manual_calls queue",
+ "", fifo_track_call_function, "", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_API(commands_api_interface, "fifo", "Return data about a fifo", fifo_api_function, FIFO_API_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "fifo_member", "Add members to a fifo", fifo_member_api_function, FIFO_MEMBER_API_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "fifo_add_outbound", "Add outbound members to a fifo", fifo_add_outbound_function, " []");
diff --git a/src/mod/applications/mod_hash/mod_hash.c b/src/mod/applications/mod_hash/mod_hash.c
index eb02e5104a..8179690928 100644
--- a/src/mod/applications/mod_hash/mod_hash.c
+++ b/src/mod/applications/mod_hash/mod_hash.c
@@ -486,8 +486,35 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_hash_load)
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_hash_shutdown)
{
+ switch_hash_index_t *hi = NULL;
+
switch_scheduler_del_task_group("mod_hash");
+ switch_thread_rwlock_wrlock(globals.limit_hash_rwlock);
+ switch_thread_rwlock_wrlock(globals.db_hash_rwlock);
+
+ while ((hi = switch_hash_first(NULL, globals.limit_hash))) {
+ void *val = NULL;
+ const void *key;
+ switch_ssize_t keylen;
+ switch_hash_this(hi, &key, &keylen, &val);
+ free(val);
+ switch_core_hash_delete(globals.limit_hash, key);
+ }
+
+ while ((hi = switch_hash_first(NULL, globals.db_hash))) {
+ void *val = NULL;
+ const void *key;
+ switch_ssize_t keylen;
+ switch_hash_this(hi, &key, &keylen, &val);
+ free(val);
+ switch_core_hash_delete(globals.db_hash, key);
+ }
+
+
+ switch_thread_rwlock_unlock(globals.limit_hash_rwlock);
+ switch_thread_rwlock_unlock(globals.db_hash_rwlock);
+
switch_thread_rwlock_destroy(globals.db_hash_rwlock);
switch_thread_rwlock_destroy(globals.limit_hash_rwlock);
diff --git a/src/mod/applications/mod_lcr/mod_lcr.c b/src/mod/applications/mod_lcr/mod_lcr.c
index c6f1a56d1b..f0362b71bf 100644
--- a/src/mod/applications/mod_lcr/mod_lcr.c
+++ b/src/mod/applications/mod_lcr/mod_lcr.c
@@ -1311,11 +1311,11 @@ static switch_call_cause_t lcr_outgoing_channel(switch_core_session_t *session,
if (lcr_do_lookup(&routes) == SWITCH_STATUS_SUCCESS) {
if (channel) {
if (zstr(switch_channel_get_variable(channel, "import"))) {
- switch_channel_set_variable(channel, "import", "lcr_carrier,lcr_rate");
+ switch_channel_set_variable(channel, "import", "lcr_carrier,lcr_rate,lcr_user_rate");
} else {
const char *tmp = switch_channel_get_variable(channel, "import");
- if (!strstr(tmp, "lcr_carrier,lcr_rate")) {
- switch_channel_set_variable_printf(channel, "import", "%s,lcr_carrier,lcr_rate", tmp);
+ if (!strstr(tmp, "lcr_carrier,lcr_rate,lcr_user_rate")) {
+ switch_channel_set_variable_printf(channel, "import", "%s,lcr_carrier,lcr_rate,lcr_user_rate", tmp);
}
}
}
@@ -1440,11 +1440,11 @@ SWITCH_STANDARD_DIALPLAN(lcr_dialplan_hunt)
switch_channel_set_variable(channel, SWITCH_CONTINUE_ON_FAILURE_VARIABLE, "true");
switch_channel_set_variable(channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, "true");
if (zstr(switch_channel_get_variable(channel, "import"))) {
- switch_channel_set_variable(channel, "import", "lcr_carrier,lcr_rate");
+ switch_channel_set_variable(channel, "import", "lcr_carrier,lcr_rate,lcr_user_rate");
} else {
const char *tmp = switch_channel_get_variable(channel, "import");
- if (!strstr(tmp, "lcr_carrier,lcr_rate")) {
- switch_channel_set_variable_printf(channel, "import", "%s,lcr_carrier,lcr_rate", tmp);
+ if (!strstr(tmp, "lcr_carrier,lcr_rate,lcr_user_rate")) {
+ switch_channel_set_variable_printf(channel, "import", "%s,lcr_carrier,lcr_rate,lcr_user_rate", tmp);
}
}
@@ -1589,11 +1589,11 @@ SWITCH_STANDARD_APP(lcr_app_function)
switch_channel_set_variable(channel, "lcr_route_count", vbuf);
switch_channel_set_variable(channel, "lcr_auto_route", (char *)dig_stream.data);
if (zstr(switch_channel_get_variable(channel, "import"))) {
- switch_channel_set_variable(channel, "import", "lcr_carrier,lcr_rate");
+ switch_channel_set_variable(channel, "import", "lcr_carrier,lcr_rate,lcr_user_rate");
} else {
const char *tmp = switch_channel_get_variable(channel, "import");
- if (!strstr(tmp, "lcr_carrier,lcr_rate")) {
- switch_channel_set_variable_printf(channel, "import", "%s,lcr_carrier,lcr_rate", tmp);
+ if (!strstr(tmp, "lcr_carrier,lcr_rate,lcr_user_rate")) {
+ switch_channel_set_variable_printf(channel, "import", "%s,lcr_carrier,lcr_rate,lcr_user_rate", tmp);
}
}
free(dig_stream.data);
diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c
index ae35a47fb3..f47711ecb1 100644
--- a/src/mod/endpoints/mod_sofia/sofia.c
+++ b/src/mod/endpoints/mod_sofia/sofia.c
@@ -684,6 +684,12 @@ void sofia_event_callback(nua_event_t event,
int locked = 0;
int check_destroy = 1;
+
+ if (!sofia_test_pflag(profile, PFLAG_RUNNING)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Profile is shutting down.\n");
+ return;
+ }
+
/* sofia_private will be == &mod_sofia_globals.keep_private whenever a request is done with a new handle that has to be
freed whenever the request is done */
if (nh && sofia_private == &mod_sofia_globals.keep_private) {
diff --git a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
index ccaba559fd..177b5586a1 100644
--- a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
+++ b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
@@ -1823,7 +1823,7 @@ static JSBool session_set_variable(JSContext * cx, JSObject * obj, uintN argc, j
var = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
val = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
- switch_channel_set_variable(channel, var, val);
+ switch_channel_set_variable_var_check(channel, var, val, SWITCH_FALSE);
*rval = BOOLEAN_TO_JSVAL(JS_TRUE);
} else {
*rval = BOOLEAN_TO_JSVAL(JS_FALSE);
diff --git a/src/switch_channel.c b/src/switch_channel.c
index 9a85d5efbd..e82af1e792 100644
--- a/src/switch_channel.c
+++ b/src/switch_channel.c
@@ -1072,18 +1072,19 @@ SWITCH_DECLARE(switch_bool_t) switch_channel_clear_flag_partner(switch_channel_t
SWITCH_DECLARE(void) switch_channel_wait_for_state(switch_channel_t *channel, switch_channel_t *other_channel, switch_channel_state_t want_state)
{
- switch_channel_state_t state, mystate, ostate;
- ostate = switch_channel_get_state(channel);
+ switch_channel_state_t state, mystate;
for (;;) {
- state = switch_channel_get_running_state(other_channel);
+ if (other_channel) {
+ state = switch_channel_get_running_state(other_channel);
+ }
mystate = switch_channel_get_running_state(channel);
if ((channel->state == channel->running_state && channel->running_state == want_state) ||
- other_channel->state >= CS_HANGUP || channel->state >= CS_HANGUP) {
+ (other_channel && other_channel->state >= CS_HANGUP) || channel->state >= CS_HANGUP) {
break;
}
- switch_cond_next();
+ switch_yield(20000);
}
}
@@ -1225,16 +1226,22 @@ SWITCH_DECLARE(char *) switch_channel_get_cap_string(switch_channel_t *channel)
SWITCH_DECLARE(void) switch_channel_set_flag_value(switch_channel_t *channel, switch_channel_flag_t flag, uint32_t value)
{
+ int HELD = 0;
+
switch_assert(channel);
switch_assert(channel->flag_mutex);
switch_mutex_lock(channel->flag_mutex);
if (flag == CF_LEG_HOLDING && !channel->flags[flag] && channel->flags[CF_ANSWERED]) {
- switch_channel_set_callstate(channel, CCS_HELD);
+ HELD = 1;
}
channel->flags[flag] = value;
switch_mutex_unlock(channel->flag_mutex);
+ if (HELD) {
+ switch_channel_set_callstate(channel, CCS_HELD);
+ }
+
if (flag == CF_OUTBOUND) {
switch_channel_set_variable(channel, "is_outbound", "true");
}
@@ -1316,16 +1323,22 @@ SWITCH_DECLARE(void) switch_channel_set_state_flag(switch_channel_t *channel, sw
SWITCH_DECLARE(void) switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
{
+ int ACTIVE = 0;
+
switch_assert(channel != NULL);
switch_assert(channel->flag_mutex);
switch_mutex_lock(channel->flag_mutex);
if (flag == CF_LEG_HOLDING && channel->flags[flag] && channel->flags[CF_ANSWERED]) {
- switch_channel_set_callstate(channel, CCS_ACTIVE);
+ ACTIVE = 1;
}
channel->flags[flag] = 0;
switch_mutex_unlock(channel->flag_mutex);
+ if (ACTIVE) {
+ switch_channel_set_callstate(channel, CCS_ACTIVE);
+ }
+
if (flag == CF_OUTBOUND) {
switch_channel_set_variable(channel, "is_outbound", NULL);
}
@@ -1761,6 +1774,11 @@ SWITCH_DECLARE(void) switch_channel_event_set_basic_data(switch_channel_t *chann
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Presence-Data", v);
}
+
+ if ((v = switch_channel_get_variable(channel, "presence_data_cols"))) {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Presence-Data-Cols", v);
+ }
+
if ((v = switch_channel_get_variable(channel, "call_uuid"))) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Call-UUID", v);
}
@@ -1813,13 +1831,15 @@ SWITCH_DECLARE(void) switch_channel_event_set_basic_data(switch_channel_t *chann
SWITCH_DECLARE(void) switch_channel_event_set_extended_data(switch_channel_t *channel, switch_event_t *event)
{
switch_event_header_t *hi;
- int x, global_verbos_events = 0;
+ int x, global_verbose_events = 0;
switch_mutex_lock(channel->profile_mutex);
- switch_core_session_ctl(SCSC_VERBOSE_EVENTS, &global_verbos_events);
+ switch_core_session_ctl(SCSC_VERBOSE_EVENTS, &global_verbose_events);
- if (global_verbos_events || switch_channel_test_flag(channel, CF_VERBOSE_EVENTS) ||
+ if (global_verbose_events ||
+ switch_channel_test_flag(channel, CF_VERBOSE_EVENTS) ||
+ switch_event_get_header(event, "presence-data-cols") ||
event->event_id == SWITCH_EVENT_CHANNEL_CREATE ||
event->event_id == SWITCH_EVENT_CHANNEL_ORIGINATE ||
event->event_id == SWITCH_EVENT_CHANNEL_UUID ||
diff --git a/src/switch_core_session.c b/src/switch_core_session.c
index b1196adda0..45c83de320 100644
--- a/src/switch_core_session.c
+++ b/src/switch_core_session.c
@@ -38,6 +38,16 @@
struct switch_session_manager session_manager;
+SWITCH_DECLARE(void) switch_core_session_soft_lock(switch_core_session_t *session, uint32_t sec)
+{
+ session->soft_lock = sec;
+}
+
+SWITCH_DECLARE(void) switch_core_session_soft_unlock(switch_core_session_t *session)
+{
+ session->soft_lock = 0;
+}
+
#ifdef SWITCH_DEBUG_RWLOCKS
SWITCH_DECLARE(switch_core_session_t *) switch_core_session_perform_locate(const char *uuid_str, const char *file, const char *func, int line)
#else
@@ -569,14 +579,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_perform_receive_message(swit
switch_assert(session != NULL);
- if (switch_channel_down(session->channel)) {
- return SWITCH_STATUS_FALSE;
- }
-
- if ((status = switch_core_session_read_lock(session)) != SWITCH_STATUS_SUCCESS) {
+ if ((status = switch_core_session_read_lock_hangup(session)) != SWITCH_STATUS_SUCCESS) {
return status;
}
-
+
if (!message->_file) {
message->_file = file;
}
@@ -610,7 +616,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_perform_receive_message(swit
goto end;
}
- if (session->endpoint_interface->io_routines->receive_message) {
+ if (switch_channel_down(session->channel)) {
+ switch_log_printf(SWITCH_CHANNEL_ID_LOG, message->_file, message->_func, message->_line,
+ switch_core_session_get_uuid(session), SWITCH_LOG_DEBUG, "%s skip receive message [%s] (channel is hungup already)\n",
+ switch_channel_get_name(session->channel), message_names[message->message_id]);
+
+ } else if (session->endpoint_interface->io_routines->receive_message) {
status = session->endpoint_interface->io_routines->receive_message(session, message);
}
@@ -626,28 +637,29 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_perform_receive_message(swit
message->_func = NULL;
message->_line = 0;
-
- switch (message->message_id) {
- case SWITCH_MESSAGE_REDIRECT_AUDIO:
- case SWITCH_MESSAGE_INDICATE_ANSWER:
- case SWITCH_MESSAGE_INDICATE_PROGRESS:
- case SWITCH_MESSAGE_INDICATE_BRIDGE:
- case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
- case SWITCH_MESSAGE_INDICATE_TRANSFER:
- case SWITCH_MESSAGE_INDICATE_RINGING:
- case SWITCH_MESSAGE_INDICATE_MEDIA:
- case SWITCH_MESSAGE_INDICATE_NOMEDIA:
- case SWITCH_MESSAGE_INDICATE_HOLD:
- case SWITCH_MESSAGE_INDICATE_UNHOLD:
- case SWITCH_MESSAGE_INDICATE_REDIRECT:
- case SWITCH_MESSAGE_INDICATE_RESPOND:
- case SWITCH_MESSAGE_INDICATE_BROADCAST:
- case SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT:
- case SWITCH_MESSAGE_INDICATE_DEFLECT:
- switch_core_session_kill_channel(session, SWITCH_SIG_BREAK);
- break;
- default:
- break;
+ if (switch_channel_up(session->channel)) {
+ switch (message->message_id) {
+ case SWITCH_MESSAGE_REDIRECT_AUDIO:
+ case SWITCH_MESSAGE_INDICATE_ANSWER:
+ case SWITCH_MESSAGE_INDICATE_PROGRESS:
+ case SWITCH_MESSAGE_INDICATE_BRIDGE:
+ case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
+ case SWITCH_MESSAGE_INDICATE_TRANSFER:
+ case SWITCH_MESSAGE_INDICATE_RINGING:
+ case SWITCH_MESSAGE_INDICATE_MEDIA:
+ case SWITCH_MESSAGE_INDICATE_NOMEDIA:
+ case SWITCH_MESSAGE_INDICATE_HOLD:
+ case SWITCH_MESSAGE_INDICATE_UNHOLD:
+ case SWITCH_MESSAGE_INDICATE_REDIRECT:
+ case SWITCH_MESSAGE_INDICATE_RESPOND:
+ case SWITCH_MESSAGE_INDICATE_BROADCAST:
+ case SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT:
+ case SWITCH_MESSAGE_INDICATE_DEFLECT:
+ switch_core_session_kill_channel(session, SWITCH_SIG_BREAK);
+ break;
+ default:
+ break;
+ }
}
end:
@@ -1172,6 +1184,21 @@ static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread_t *thre
switch_core_session_run(session);
switch_core_media_bug_remove_all(session);
+
+ if (session->soft_lock) {
+ uint32_t loops = session->soft_lock * 10;
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Session %" SWITCH_SIZE_T_FMT " (%s) Soft-Locked, "
+ "Waiting %u for external entities\n",
+ session->id, switch_channel_get_name(session->channel), session->soft_lock);
+
+ while(--loops > 0) {
+ if (!session->soft_lock) break;
+ switch_yield(100000);
+ }
+
+ }
+
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Session %" SWITCH_SIZE_T_FMT " (%s) Locked, Waiting on external entities\n",
session->id, switch_channel_get_name(session->channel));
switch_core_session_write_lock(session);
diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c
index 7fc32c0a3f..810de2ddda 100644
--- a/src/switch_core_sqldb.c
+++ b/src/switch_core_sqldb.c
@@ -964,6 +964,45 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread,
return NULL;
}
+static char *parse_presence_data_cols(switch_event_t *event)
+{
+ char *cols[25] = { 0 };
+ int col_count = 0;
+ char *data_copy;
+ switch_stream_handle_t stream = { 0 };
+ int i;
+ char *r;
+ char col_name[128] = "";
+ const char *data = switch_event_get_header(event, "presence-data-cols");
+
+ if (zstr(data)) {
+ return NULL;
+ }
+
+ data_copy = strdup(data);
+
+ col_count = switch_split(data_copy, ':', cols);
+
+ SWITCH_STANDARD_STREAM(stream);
+
+ for (i = 0; i < col_count; i++) {
+ switch_snprintf(col_name, sizeof(col_name), "variable_%s", cols[i]);
+ stream.write_function(&stream, "%q='%q',", cols[i], switch_event_get_header_nil(event, col_name));
+ }
+
+ r = (char *) stream.data;
+
+ if (end_of(r) == ',') {
+ end_of(r) = '\0';
+ }
+
+ switch_safe_free(data_copy);
+
+ return r;
+
+}
+
+
#define MAX_SQL 5
#define new_sql() switch_assert(sql_idx+1 < MAX_SQL); sql[sql_idx++]
@@ -971,6 +1010,7 @@ static void core_event_handler(switch_event_t *event)
{
char *sql[MAX_SQL] = { 0 };
int sql_idx = 0;
+ char *extra_cols;
switch_assert(event);
@@ -1053,7 +1093,8 @@ static void core_event_handler(switch_event_t *event)
break;
case SWITCH_EVENT_CHANNEL_HOLD:
case SWITCH_EVENT_CHANNEL_UNHOLD:
- case SWITCH_EVENT_CHANNEL_EXECUTE:
+ case SWITCH_EVENT_CHANNEL_EXECUTE: {
+
new_sql() = switch_mprintf("update channels set application='%q',application_data='%q',"
"presence_id='%q',presence_data='%q' where uuid='%q' and hostname='%q'",
switch_event_get_header_nil(event, "application"),
@@ -1061,18 +1102,30 @@ static void core_event_handler(switch_event_t *event)
switch_event_get_header_nil(event, "channel-presence-id"),
switch_event_get_header_nil(event, "channel-presence-data"),
switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname")
-
);
+
+ }
break;
case SWITCH_EVENT_CHANNEL_ORIGINATE:
{
- new_sql() = switch_mprintf("update channels set "
- "presence_id='%q',presence_data='%q', call_uuid='%q' where uuid='%q' and hostname='%q'",
- switch_event_get_header_nil(event, "channel-presence-id"),
- switch_event_get_header_nil(event, "channel-presence-data"),
- switch_event_get_header_nil(event, "channel-call-uuid"),
- switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname"));
+ if ((extra_cols = parse_presence_data_cols(event))) {
+ new_sql() = switch_mprintf("update channels set "
+ "presence_id='%q',presence_data='%q', call_uuid='%q',%s where uuid='%q' and hostname='%q'",
+ switch_event_get_header_nil(event, "channel-presence-id"),
+ switch_event_get_header_nil(event, "channel-presence-data"),
+ switch_event_get_header_nil(event, "channel-call-uuid"),
+ extra_cols,
+ switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname"));
+ free(extra_cols);
+ } else {
+ new_sql() = switch_mprintf("update channels set "
+ "presence_id='%q',presence_data='%q', call_uuid='%q' where uuid='%q' and hostname='%q'",
+ switch_event_get_header_nil(event, "channel-presence-id"),
+ switch_event_get_header_nil(event, "channel-presence-data"),
+ switch_event_get_header_nil(event, "channel-call-uuid"),
+ switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname"));
+ }
}
@@ -1124,19 +1177,37 @@ static void core_event_handler(switch_event_t *event)
case CS_DESTROY:
break;
case CS_ROUTING:
- new_sql() = switch_mprintf("update channels set state='%s',cid_name='%q',cid_num='%q',"
- "ip_addr='%s',dest='%q',dialplan='%q',context='%q',presence_id='%q',presence_data='%q' "
- "where uuid='%s' and hostname='%q'",
- switch_event_get_header_nil(event, "channel-state"),
- switch_event_get_header_nil(event, "caller-caller-id-name"),
- switch_event_get_header_nil(event, "caller-caller-id-number"),
- switch_event_get_header_nil(event, "caller-network-addr"),
- switch_event_get_header_nil(event, "caller-destination-number"),
- switch_event_get_header_nil(event, "caller-dialplan"),
- switch_event_get_header_nil(event, "caller-context"),
- switch_event_get_header_nil(event, "channel-presence-id"),
- switch_event_get_header_nil(event, "channel-presence-data"),
- switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname"));
+ if ((extra_cols = parse_presence_data_cols(event))) {
+ new_sql() = switch_mprintf("update channels set state='%s',cid_name='%q',cid_num='%q',"
+ "ip_addr='%s',dest='%q',dialplan='%q',context='%q',presence_id='%q',presence_data='%q',%s "
+ "where uuid='%s' and hostname='%q'",
+ switch_event_get_header_nil(event, "channel-state"),
+ switch_event_get_header_nil(event, "caller-caller-id-name"),
+ switch_event_get_header_nil(event, "caller-caller-id-number"),
+ switch_event_get_header_nil(event, "caller-network-addr"),
+ switch_event_get_header_nil(event, "caller-destination-number"),
+ switch_event_get_header_nil(event, "caller-dialplan"),
+ switch_event_get_header_nil(event, "caller-context"),
+ switch_event_get_header_nil(event, "channel-presence-id"),
+ switch_event_get_header_nil(event, "channel-presence-data"),
+ extra_cols,
+ switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname"));
+ free(extra_cols);
+ } else {
+ new_sql() = switch_mprintf("update channels set state='%s',cid_name='%q',cid_num='%q',"
+ "ip_addr='%s',dest='%q',dialplan='%q',context='%q',presence_id='%q',presence_data='%q' "
+ "where uuid='%s' and hostname='%q'",
+ switch_event_get_header_nil(event, "channel-state"),
+ switch_event_get_header_nil(event, "caller-caller-id-name"),
+ switch_event_get_header_nil(event, "caller-caller-id-number"),
+ switch_event_get_header_nil(event, "caller-network-addr"),
+ switch_event_get_header_nil(event, "caller-destination-number"),
+ switch_event_get_header_nil(event, "caller-dialplan"),
+ switch_event_get_header_nil(event, "caller-context"),
+ switch_event_get_header_nil(event, "channel-presence-id"),
+ switch_event_get_header_nil(event, "channel-presence-data"),
+ switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname"));
+ }
break;
default:
new_sql() = switch_mprintf("update channels set state='%s' where uuid='%s' and hostname='%q'",
diff --git a/src/switch_cpp.cpp b/src/switch_cpp.cpp
index ec4c9c40b4..5368cdddeb 100644
--- a/src/switch_cpp.cpp
+++ b/src/switch_cpp.cpp
@@ -623,7 +623,7 @@ SWITCH_DECLARE(void) CoreSession::setVariable(char *var, char *val)
{
this_check_void();
sanity_check_noreturn;
- switch_channel_set_variable(channel, var, val);
+ switch_channel_set_variable_var_check(channel, var, val, SWITCH_FALSE);
}
SWITCH_DECLARE(const char *)CoreSession::getVariable(char *var)
diff --git a/src/switch_event.c b/src/switch_event.c
index c2cbc7cb2e..eccc695679 100644
--- a/src/switch_event.c
+++ b/src/switch_event.c
@@ -1062,8 +1062,8 @@ SWITCH_DECLARE(switch_status_t) switch_event_create_brackets(char *data, char a,
int var_count = 0;
char *next;
- vdata = strdup(data);
- vdatap = vdata;
+ vdatap = strdup(data);
+ vdata = vdatap;
end = switch_find_end_paren(vdata, a, b);
@@ -1081,7 +1081,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_create_brackets(char *data, char a,
vdata++;
*end++ = '\0';
} else {
- vdata = NULL;
+ free(vdatap);
return SWITCH_STATUS_FALSE;
}
diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c
index 356d07956a..b32a61f1a2 100644
--- a/src/switch_ivr_bridge.c
+++ b/src/switch_ivr_bridge.c
@@ -515,12 +515,6 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
switch_safe_free(stream.data);
}
-
- msg.string_arg = data->b_uuid;
- msg.message_id = SWITCH_MESSAGE_INDICATE_UNBRIDGE;
- msg.from = __FILE__;
- switch_core_session_receive_message(session_a, &msg);
-
if (!inner_bridge && switch_channel_up(chan_a)) {
if ((app_name = switch_channel_get_variable(chan_a, SWITCH_EXEC_AFTER_BRIDGE_APP_VARIABLE))) {
switch_caller_extension_t *extension = NULL;
@@ -1048,6 +1042,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses
int inner_bridge = switch_channel_test_flag(caller_channel, CF_INNER_BRIDGE);
const char *var;
switch_call_cause_t cause;
+ switch_core_session_message_t msg = { 0 };
if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Call has no media... Redirecting to signal bridge.\n");
@@ -1084,7 +1079,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses
if (switch_channel_test_flag(peer_channel, CF_ANSWERED) || switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA) ||
switch_channel_test_flag(peer_channel, CF_RING_READY)) {
- switch_core_session_message_t msg = { 0 };
const char *app, *data;
switch_channel_set_state(peer_channel, CS_CONSUME_MEDIA);
@@ -1250,6 +1244,14 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses
switch_event_fire(&event);
}
+ msg.message_id = SWITCH_MESSAGE_INDICATE_UNBRIDGE;
+ msg.from = __FILE__;
+ msg.string_arg = switch_core_session_strdup(peer_session, switch_core_session_get_uuid(session));
+ switch_core_session_receive_message(peer_session, &msg);
+
+ msg.string_arg = switch_core_session_strdup(session, switch_core_session_get_uuid(peer_session));
+ switch_core_session_receive_message(session, &msg);
+
state = switch_channel_get_state(caller_channel);
diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c
index 605a23270e..f54639d883 100644
--- a/src/switch_ivr_originate.c
+++ b/src/switch_ivr_originate.c
@@ -32,6 +32,8 @@
*/
#include
+#define QUOTED_ESC_COMMA 1
+#define UNQUOTED_ESC_COMMA 2
static const switch_state_handler_table_t originate_state_handlers;
@@ -2268,6 +2270,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
for (r = 0; r < or_argc; r++) {
char *p, *end = NULL;
const char *var_begin, *var_end;
+ int q = 0;
oglobals.hups = 0;
reason = SWITCH_CAUSE_NONE;
@@ -2287,6 +2290,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
oglobals.sent_ring = 0;
oglobals.progress = 0;
myflags = dftflags;
+
if (try > 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Originate attempt %d/%d in %d ms\n", try + 1, retries,
@@ -2308,8 +2312,16 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
end = switch_find_end_paren(p, '[', ']');
}
+ if (*p == '\'') {
+ q = !q;
+ }
+
if (end && p < end && *p == ',') {
- *p = '|';
+ if (q) {
+ *p = QUOTED_ESC_COMMA;
+ } else {
+ *p = UNQUOTED_ESC_COMMA;
+ }
}
if (p == end) {
@@ -2450,7 +2462,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
if (vdata && (var_begin = switch_stristr("origination_uuid=", vdata))) {
char tmp[512] = "";
var_begin += strlen("origination_uuid=");
- var_end = strchr(var_begin, '|');
+ var_end = strchr(var_begin, UNQUOTED_ESC_COMMA);
if (var_end) {
strncpy(tmp, var_begin, var_end - var_begin);
@@ -2467,7 +2479,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
if (vdata && (var_begin = switch_stristr("origination_caller_id_number=", vdata))) {
var_begin += strlen("origination_caller_id_number=");
- var_end = strchr(var_begin, '|');
+ var_end = strchr(var_begin, UNQUOTED_ESC_COMMA);
if (var_end) {
strncpy(variable_buffer, var_begin, var_end - var_begin);
@@ -2487,7 +2499,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
if (vdata && (var_begin = switch_stristr("origination_caller_id_name=", vdata))) {
var_begin += strlen("origination_caller_id_name=");
- var_end = strchr(var_begin, '|');
+ var_end = strchr(var_begin, UNQUOTED_ESC_COMMA);
if (var_end) {
strncpy(variable_buffer, var_begin, var_end - var_begin);
@@ -2507,7 +2519,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
if (vdata && (var_begin = switch_stristr("origination_privacy=", vdata))) {
var_begin += strlen("origination_privacy=");
- var_end = strchr(var_begin, '|');
+ var_end = strchr(var_begin, UNQUOTED_ESC_COMMA);
if (var_end) {
strncpy(variable_buffer, var_begin, var_end - var_begin);
@@ -2556,16 +2568,27 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
}
}
- if ((var_count = switch_separate_string(vdata, '|', var_array, (sizeof(var_array) / sizeof(var_array[0]))))) {
+ if ((var_count = switch_separate_string(vdata, UNQUOTED_ESC_COMMA, var_array, (sizeof(var_array) / sizeof(var_array[0]))))) {
int x = 0;
for (x = 0; x < var_count; x++) {
char *inner_var_array[2] = { 0 };
int inner_var_count;
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "local variable string %d = [%s]\n",
- x, var_array[x]);
+ char *p;
+
+ for (p = var_array[x]; p && *p; p++) {
+ if (*p == QUOTED_ESC_COMMA) {
+ *p = ',';
+ }
+ }
+
+
+
if ((inner_var_count =
switch_separate_string(var_array[x], '=',
inner_var_array, (sizeof(inner_var_array) / sizeof(inner_var_array[0])))) == 2) {
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "local variable string %d = [%s=%s]\n",
+ x, inner_var_array[0], inner_var_array[1]);
switch_event_add_header_string(local_var_event, SWITCH_STACK_BOTTOM, inner_var_array[0], inner_var_array[1]);
}
diff --git a/src/switch_limit.c b/src/switch_limit.c
index a27a822156..810d83b105 100755
--- a/src/switch_limit.c
+++ b/src/switch_limit.c
@@ -81,19 +81,18 @@ static switch_status_t limit_state_handler(switch_core_session_t *session)
switch_channel_state_t state = switch_channel_get_state(channel);
const char *vval = switch_channel_get_variable(channel, LIMIT_IGNORE_TRANSFER_VARIABLE);
const char *backendlist = switch_channel_get_variable(channel, LIMIT_BACKEND_VARIABLE);
- int argc = 0;
- char *argv[6] = { 0 };
- char *mydata = NULL;
if (zstr(backendlist)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unset limit backendlist!\n");
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unset limit backendlist!\n");
return SWITCH_STATUS_SUCCESS;
}
- mydata = strdup(backendlist);
-
if (state >= CS_HANGUP || (state == CS_ROUTING && !switch_true(vval))) {
+ int argc = 0;
+ char *argv[6] = { 0 };
+ char *mydata = strdup(backendlist);
int x;
+
argc = switch_separate_string(mydata, ',', argv, (sizeof(argv) / sizeof(argv[0])));
for (x = 0; x < argc; x++) {
switch_limit_release(argv[x], session, NULL, NULL);
@@ -101,7 +100,10 @@ static switch_status_t limit_state_handler(switch_core_session_t *session)
switch_core_event_hook_remove_state_change(session, limit_state_handler);
/* Remove limit_realm variable so we register another hook if limit is called again */
switch_channel_set_variable(channel, "limit_realm", NULL);
+
+ free(mydata);
}
+
return SWITCH_STATUS_SUCCESS;
}
@@ -117,7 +119,7 @@ SWITCH_DECLARE(switch_status_t) switch_limit_incr(const char *backend, switch_co
/* locate impl, call appropriate func */
if (!(limit = get_backend(backend))) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Limit subsystem %s not found!\n", backend);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Limit subsystem %s not found!\n", backend);
switch_goto_status(SWITCH_STATUS_GENERR, end);
}
@@ -149,7 +151,7 @@ SWITCH_DECLARE(switch_status_t) switch_limit_release(const char *backend, switch
/* locate impl, call appropriate func */
if (!(limit = get_backend(backend))) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Limit subsystem %s not found!\n", backend);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Limit subsystem %s not found!\n", backend);
switch_goto_status(SWITCH_STATUS_GENERR, end);
}
diff --git a/src/switch_time.c b/src/switch_time.c
index 2d74e60594..5e93d59261 100644
--- a/src/switch_time.c
+++ b/src/switch_time.c
@@ -48,7 +48,10 @@
#define MAX_ELEMENTS 3600
#define IDLE_SPEED 100
-#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
+/* For now enable WIN32_MONOTONIC on Windows 2003 Server and Windows XP systems for improved timer support */
+/* GetSystemTimeAsFileTime does not update on timeBeginPeriod on these OS */
+/* we leave the normal timer support as the default for now */
+#if (defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)) || defined(WIN32_MONOTONIC)
static int MONO = 1;
#else
static int MONO = 0;
@@ -67,6 +70,12 @@ static int COND = 1;
static int MATRIX = 1;
+#ifdef WIN32
+static switch_time_t win32_tick_time_since_start = -1;
+static DWORD win32_last_get_time_tick = 0;
+CRITICAL_SECTION timer_section;
+#endif
+
#define ONEMS
#ifdef ONEMS
static int STEP_MS = 1;
@@ -174,9 +183,9 @@ static switch_interval_time_t average_time(switch_interval_time_t t, int reps)
switch_time_t start, stop, sum = 0;
for (x = 0; x < reps; x++) {
- start = switch_time_now();
+ start = switch_time_ref();
do_sleep(t);
- stop = switch_time_now();
+ stop = switch_time_ref();
sum += (stop - start);
}
@@ -335,22 +344,49 @@ static switch_time_t time_now(int64_t offset)
{
switch_time_t now;
-#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
+#if (defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)) || defined(WIN32_MONOTONIC)
if (MONO) {
+#ifndef WIN32
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
now = ts.tv_sec * APR_USEC_PER_SEC + (ts.tv_nsec / 1000) + offset;
+#else
+ DWORD tick_now;
+ DWORD tick_diff;
+
+ tick_now = timeGetTime();
+ if (win32_tick_time_since_start != -1) {
+ EnterCriticalSection(&timer_section);
+ /* just add diff (to make it work more than 50 days). */
+ tick_diff = tick_now - win32_last_get_time_tick;
+ win32_tick_time_since_start += tick_diff;
+
+ win32_last_get_time_tick = tick_now;
+ now = (win32_tick_time_since_start * 1000) + offset;
+ LeaveCriticalSection(&timer_section);
+ } else {
+ /* If someone is calling us before timer is initialized,
+ * return the current tick + offset
+ */
+ now = (tick_now * 1000) + offset;
+ }
+#endif
} else {
#endif
now = switch_time_now();
-#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
+#if (defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)) || defined(WIN32_MONOTONIC)
}
#endif
return now;
}
+SWITCH_DECLARE(switch_time_t) switch_time_ref(void)
+{
+ return time_now(0);
+}
+
SWITCH_DECLARE(void) switch_time_sync(void)
{
runtime.reference = switch_time_now();
@@ -999,6 +1035,9 @@ SWITCH_MODULE_LOAD_FUNCTION(softtimer_load)
#if defined(WIN32)
timeBeginPeriod(1);
+ InitializeCriticalSection(&timer_section);
+ win32_last_get_time_tick = timeGetTime();
+ win32_tick_time_since_start = win32_last_get_time_tick;
#endif
memset(&globals, 0, sizeof(globals));
@@ -1054,6 +1093,8 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(softtimer_shutdown)
}
#if defined(WIN32)
timeEndPeriod(1);
+ win32_tick_time_since_start = -1; /* we are not initialized anymore */
+ DeleteCriticalSection(&timer_section);
#endif
if (TIMEZONES_LIST.hash) {