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) {