From 61c563afcbd6dfd124a6d676ed6fa1936664d103 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Thu, 8 Apr 2010 12:58:56 -0400 Subject: [PATCH 01/24] revert openzap temporary workaround for Windows compilation --- .../src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c b/libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c index 87aa0d0079..5974e8b029 100644 --- a/libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c +++ b/libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c @@ -43,8 +43,6 @@ #include "libsangoma.h" #if defined(__WINDOWS__) -/* remove this when http://jira.freeswitch.org/browse/FSBUILD-259 wanpipe issue is fixed */ -#define WINDOWS_BUILD_BROKEN 1 /*! Backward compatible defines - current code is all using the old names*/ #define sangoma_open_tdmapi_span_chan sangoma_open_api_span_chan #define sangoma_open_tdmapi_span sangoma_open_api_span @@ -96,8 +94,6 @@ static struct { ZIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event); ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event); -#define WP_INVALID_SOCKET -1 - /** * \brief Poll for event on a wanpipe socket * \param fd Wanpipe socket descriptor @@ -219,7 +215,7 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start, } for(x = start; x < end; x++) { zap_channel_t *chan; - zap_socket_t sockfd = WP_INVALID_SOCKET; + zap_socket_t sockfd = ZAP_INVALID_SOCKET; const char *dtmf = "none"; if (!strncasecmp(span->name, "smg_prid_nfas", 8) && span->trunk_type == ZAP_TRUNK_T1 && x == 24) { #ifdef LIBSANGOMA_VERSION @@ -231,7 +227,7 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start, sockfd = tdmv_api_open_span_chan(spanno, x); } - if (sockfd == WP_INVALID_SOCKET) { + if (sockfd == ZAP_INVALID_SOCKET) { zap_log(ZAP_LOG_ERROR, "Failed to open wanpipe device span %d channel %d\n", spanno, x); continue; } @@ -587,29 +583,24 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command) break; case ZAP_COMMAND_ENABLE_ECHOCANCEL: { -#ifndef WINDOWS_BUILD_BROKEN err=sangoma_tdm_enable_hwec(zchan->sockfd, &tdm_api); if (err) { snprintf(zchan->last_error, sizeof(zchan->last_error), "HWEC Enable Failed"); return ZAP_FAIL; } -#endif /* WINDOWS_BUILD_BROKEN */ } break; case ZAP_COMMAND_DISABLE_ECHOCANCEL: { -#ifndef WINDOWS_BUILD_BROKEN err=sangoma_tdm_disable_hwec(zchan->sockfd, &tdm_api); if (err) { snprintf(zchan->last_error, sizeof(zchan->last_error), "HWEC Disable Failed"); return ZAP_FAIL; } -#endif /* WINDOWS_BUILD_BROKEN */ } break; case ZAP_COMMAND_ENABLE_LOOP: { -#ifndef WINDOWS_BUILD_BROKEN #ifdef WP_API_FEATURE_LOOP err=sangoma_tdm_enable_loop(zchan->sockfd, &tdm_api); if (err) { @@ -617,11 +608,9 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command) return ZAP_FAIL; } #endif -#endif /* WINDOWS_BUILD_BROKEN */ } case ZAP_COMMAND_DISABLE_LOOP: { -#ifndef WINDOWS_BUILD_BROKEN #ifdef WP_API_FEATURE_LOOP err=sangoma_tdm_disable_loop(zchan->sockfd, &tdm_api); if (err) { @@ -629,7 +618,6 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command) return ZAP_FAIL; } #endif -#endif /* WINDOWS_BUILD_BROKEN */ } case ZAP_COMMAND_SET_INTERVAL: { @@ -1163,9 +1151,8 @@ static ZIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy) } #endif - if (zchan->sockfd > -1) { - close(zchan->sockfd); - zchan->sockfd = WP_INVALID_SOCKET; + if (zchan->sockfd != ZAP_INVALID_SOCKET) { + sangoma_close(&zchan->sockfd); } return ZAP_SUCCESS; From 1a4b6d544063593c5d44d1b8f5f320cea66eedbf Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Thu, 8 Apr 2010 13:25:44 -0400 Subject: [PATCH 02/24] fix freetdm win compilation --- libs/freetdm/msvc/freetdm.2008.vcproj | 108 +++++++++--------- libs/freetdm/src/ftdm_cpu_monitor.c | 23 ++-- libs/freetdm/src/ftdm_io.c | 14 ++- libs/freetdm/src/ftdm_threadmutex.c | 45 +++++++- .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 11 +- 5 files changed, 122 insertions(+), 79 deletions(-) diff --git a/libs/freetdm/msvc/freetdm.2008.vcproj b/libs/freetdm/msvc/freetdm.2008.vcproj index 8540fce75e..801c368aef 100644 --- a/libs/freetdm/msvc/freetdm.2008.vcproj +++ b/libs/freetdm/msvc/freetdm.2008.vcproj @@ -326,10 +326,34 @@ Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > + + + + + + + + + + + + @@ -358,34 +382,10 @@ RelativePath="..\src\include\libteletone_generate.h" > - - - - - - - - - - - - + + + + + + + + + + + + + + + + @@ -420,34 +452,6 @@ RelativePath="..\src\uart.c" > - - - - - - - - - - - - - - diff --git a/libs/freetdm/src/ftdm_cpu_monitor.c b/libs/freetdm/src/ftdm_cpu_monitor.c index eebf922b98..7c79a2e65c 100644 --- a/libs/freetdm/src/ftdm_cpu_monitor.c +++ b/libs/freetdm/src/ftdm_cpu_monitor.c @@ -201,28 +201,31 @@ FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time (struct ftdm_cpu_monitor return FTDM_SUCCESS; } -#elif defined (WIN32) || defined (WIN64) +#elif defined (__WINDOWS__) FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time(struct ftdm_cpu_monitor_stats *p, double *idle_percentage) { FILETIME idleTime; FILETIME kernelTime; FILETIME userTime; + int64_t i64UserTime; + int64_t i64KernelTime; + int64_t i64IdleTime; - if (!::GetSystemTimes(&idleTime, &kernelTime, &userTime)) { - return false; + if (!GetSystemTimes(&idleTime, &kernelTime, &userTime)) { + return FTDM_FAIL; } - __int64 i64UserTime = (__int64)userTime.dwLowDateTime | ((__int64)userTime.dwHighDateTime << 32); + i64UserTime = (int64_t)userTime.dwLowDateTime | ((int64_t)userTime.dwHighDateTime << 32); - __int64 i64KernelTime = (__int64)kernelTime.dwLowDateTime | ((__int64)kernelTime.dwHighDateTime << 32); + i64KernelTime = (int64_t)kernelTime.dwLowDateTime | ((int64_t)kernelTime.dwHighDateTime << 32); - __int64 i64IdleTime = (__int64)idleTime.dwLowDateTime | ((__int64)idleTime.dwHighDateTime << 32); + i64IdleTime = (int64_t)idleTime.dwLowDateTime | ((int64_t)idleTime.dwHighDateTime << 32); if (p->valid_last_times) { - __int64 i64User = i64UserTime - p->i64LastUserTime; - __int64 i64Kernel = i64KernelTime - p->i64LastKernelTime; - __int64 i64Idle = i64IdleTime - p->i64LastIdleTime; - __int64 i64System = i64User + i64Kernel; + int64_t i64User = i64UserTime - p->i64LastUserTime; + int64_t i64Kernel = i64KernelTime - p->i64LastKernelTime; + int64_t i64Idle = i64IdleTime - p->i64LastIdleTime; + int64_t i64System = i64User + i64Kernel; *idle_percentage = 100.0 * i64Idle / i64System; } else { *idle_percentage = 100.0; diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 033a25d675..2cacf69d90 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2855,6 +2855,7 @@ static ftdm_status_t load_config(void) ftdm_config_t cfg; char *var, *val; int catno = -1; + int intparam = 0; int currindex = 0; ftdm_span_t *span = NULL; unsigned configured = 0, d = 0; @@ -3059,14 +3060,16 @@ static ftdm_status_t load_config(void) ftdm_log(FTDM_LOG_ERROR, "Invalid cpu monitoring interval %s\n", val); } } else if (!strncasecmp(var, "cpu_set_alarm_threshold", sizeof("cpu_set_alarm_threshold")-1)) { - if (atoi(val) > 0 && atoi(val) < 100) { - globals.cpu_monitor.set_alarm_threshold = atoi(val); + intparam = atoi(val); + if (intparam > 0 && intparam < 100) { + globals.cpu_monitor.set_alarm_threshold = (uint8_t)intparam; } else { ftdm_log(FTDM_LOG_ERROR, "Invalid cpu alarm set threshold %s\n", val); } } else if (!strncasecmp(var, "cpu_reset_alarm_threshold", sizeof("cpu_reset_alarm_threshold")-1)) { - if (atoi(val) > 0 && atoi(val) < 100) { - globals.cpu_monitor.reset_alarm_threshold = atoi(val); + intparam = atoi(val); + if (intparam > 0 && intparam < 100) { + globals.cpu_monitor.reset_alarm_threshold = (uint8_t)intparam; if (globals.cpu_monitor.reset_alarm_threshold > globals.cpu_monitor.set_alarm_threshold) { globals.cpu_monitor.reset_alarm_threshold = globals.cpu_monitor.set_alarm_threshold - 10; ftdm_log(FTDM_LOG_ERROR, "Cpu alarm reset threshold must be lower than set threshold" @@ -3652,6 +3655,9 @@ static void *ftdm_cpu_monitor_run(ftdm_thread_t *me, void *obj) ftdm_delete_cpu_monitor(cpu_stats); monitor->running = 0; return NULL; +#ifdef __WINDOWS__ + UNREFERENCED_PARAMETER(me); +#endif } static ftdm_status_t ftdm_cpu_monitor_start(void) diff --git a/libs/freetdm/src/ftdm_threadmutex.c b/libs/freetdm/src/ftdm_threadmutex.c index 8e9c62ff4c..9eca9eeb3d 100644 --- a/libs/freetdm/src/ftdm_threadmutex.c +++ b/libs/freetdm/src/ftdm_threadmutex.c @@ -314,7 +314,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_wait(ftdm_interrupt_t *interrupt, int m num++; ints[1] = interrupt->device; } - res = WaitForMultipleObjects(num, &ints, FALSE, ms >= 0 ? ms : INFINITE); + res = WaitForMultipleObjects(num, ints, FALSE, ms >= 0 ? ms : INFINITE); switch (res) { case WAIT_TIMEOUT: return FTDM_TIMEOUT; @@ -366,7 +366,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_signal(ftdm_interrupt_t *interrupt) { ftdm_assert_return(interrupt != NULL, FTDM_FAIL, "Interrupt is null!\n"); #ifdef WIN32 - if (!SetEvent(interrupt->interrupt)) { + if (!SetEvent(interrupt->event)) { ftdm_log(FTDM_LOG_ERROR, "Failed to signal interrupt\n"); return FTDM_FAIL; } @@ -400,10 +400,42 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_destroy(ftdm_interrupt_t **ininterrupt) FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interrupts[], ftdm_size_t size, int ms) { -#ifndef WIN32 - int i; - int res = 0; int numdevices = 0; + unsigned i; +#if defined(__WINDOWS__) + DWORD res = 0; + HANDLE ints[20]; + if (size > (ftdm_array_len(ints)/2)) { + /* improve if needed: dynamically allocate the list of interrupts *only* when exceeding the default size */ + ftdm_log(FTDM_LOG_CRIT, "Unsupported size of interrupts: %d, implement me!\n", size); + return FTDM_FAIL; + } + + for (i = 0; i < size; i++) { + ints[i] = interrupts[i]->event; + if (interrupts[i]->device != FTDM_INVALID_SOCKET) { + ints[i+numdevices] = interrupts[i]->device; + numdevices++; + } + } + + res = WaitForMultipleObjects(size+numdevices, ints, FALSE, ms >= 0 ? ms : INFINITE); + + switch (res) { + case WAIT_TIMEOUT: + return FTDM_TIMEOUT; + case WAIT_FAILED: + case WAIT_ABANDONED: /* is it right to fail with abandoned? */ + return FTDM_FAIL; + default: + if (res >= (size+numdevices)) { + ftdm_log(FTDM_LOG_ERROR, "Error waiting for freetdm interrupt event (WaitForSingleObject returned %d)\n", res); + return FTDM_FAIL; + } + /* fall-through to FTDM_SUCCESS at the end of the function */ + } +#elif defined(__linux__) + int res = 0; char pipebuf[255]; struct pollfd ints[size*2]; @@ -432,6 +464,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru return FTDM_TIMEOUT; } + /* check for events in the pipes, NOT in the devices */ for (i = 0; i < size; i++) { if (ints[i].revents & POLLIN) { res = read(ints[i].fd, pipebuf, sizeof(pipebuf)); @@ -440,7 +473,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru } } } - +#else #endif return FTDM_SUCCESS; } diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index 46be23f60b..b941e641de 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -101,8 +101,6 @@ static struct { FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event); FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event); -#define WP_INVALID_SOCKET -1 - /** * \brief Poll for event on a wanpipe socket * \param fd Wanpipe socket descriptor @@ -224,7 +222,7 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start } for(x = start; x < end; x++) { ftdm_channel_t *chan; - ftdm_socket_t sockfd = WP_INVALID_SOCKET; + ftdm_socket_t sockfd = FTDM_INVALID_SOCKET; const char *dtmf = "none"; if (!strncasecmp(span->name, "smg_prid_nfas", 8) && span->trunk_type == FTDM_TRUNK_T1 && x == 24) { #ifdef LIBSANGOMA_VERSION @@ -236,7 +234,7 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start sockfd = tdmv_api_open_span_chan(spanno, x); } - if (sockfd == WP_INVALID_SOCKET) { + if (sockfd == FTDM_INVALID_SOCKET) { ftdm_log(FTDM_LOG_ERROR, "Failed to open wanpipe device span %d channel %d\n", spanno, x); continue; } @@ -1166,9 +1164,8 @@ static FIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy) } #endif - if (ftdmchan->sockfd > -1) { - close(ftdmchan->sockfd); - ftdmchan->sockfd = WP_INVALID_SOCKET; + if (ftdmchan->sockfd != FTDM_INVALID_SOCKET) { + sangoma_close(&ftdmchan->sockfd); } return FTDM_SUCCESS; From 3d089f0075ef70bf9206334c3d4c5bb27fc804c5 Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Thu, 8 Apr 2010 20:49:56 +0200 Subject: [PATCH 03/24] FSMOD-35: mod_tts_commandline core dump, temp file problem. flush can be called several times --- .../mod_tts_commandline/mod_tts_commandline.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/mod/asr_tts/mod_tts_commandline/mod_tts_commandline.c b/src/mod/asr_tts/mod_tts_commandline/mod_tts_commandline.c index f86b9d5156..6b261f1d96 100644 --- a/src/mod/asr_tts/mod_tts_commandline/mod_tts_commandline.c +++ b/src/mod/asr_tts/mod_tts_commandline/mod_tts_commandline.c @@ -186,10 +186,14 @@ static void tts_commandline_speech_flush_tts(switch_speech_handle_t *sh) { tts_commandline_t *info = (tts_commandline_t *) sh->private_info; assert(info != NULL); - - switch_core_file_close(info->fh); - if (unlink(info->file) != 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Sound file [%s] delete failed\n", info->file); + + if (info->fh != NULL && info->fh->file_interface != NULL) { + switch_core_file_close(info->fh); + } + if (switch_file_exists(info->file, NULL) == SWITCH_STATUS_SUCCESS) { + if (unlink(info->file) != 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Sound file [%s] delete failed\n", info->file); + } } } From 5c668de704414a7bc98e874ec657d1abaf533726 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Thu, 8 Apr 2010 19:40:53 +0000 Subject: [PATCH 04/24] Added a script to help committers configure git properly. --- scripts/setup-git.sh | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100755 scripts/setup-git.sh diff --git a/scripts/setup-git.sh b/scripts/setup-git.sh new file mode 100755 index 0000000000..9781417f98 --- /dev/null +++ b/scripts/setup-git.sh @@ -0,0 +1,76 @@ +#!/bin/bash +##### -*- mode:shell-script; indent-tabs-mode:nil; sh-basic-offset:2 -*- +##### setup git properly for FreeSWITCH + +if [ ! -d .git ]; then + echo "error: must be run from within the top level of a FreeSWITCH git tree." 1>&2 + exit 1; +fi + +err () { + echo "error: $1" 1>&2 + exit 1 +} + +if ! git config user.name >/dev/null 2>&1; then + name=$(git config user.name) + [ -z "$name" ] \ + && [ -n "$NAME" ] && name="$NAME" || name="" + echo -n "What is your name? [$name]: " + read name_ + [ -n "$name_" ] && name="$name_" + [ -z "$name" ] && err "Your name is required." + git config --global user.name "$name" +fi + +if ! git config user.email >/dev/null 2>&1; then + email=$(git config user.email) + [ -z "$email" ] \ + && [ -n "$EMAIL" ] && email="$EMAIL" || email="" + echo -n "What is your email? [$email]: " + read email_ + [ -n "$email_" ] && email="$email_" + [ -z "$email" ] && err "Your email is required." + git config --global user.email "$email" +fi + +git config branch.master.rebase true + +cat 1>&2 <&2 <&2 <&2 < Date: Thu, 8 Apr 2010 14:43:44 -0500 Subject: [PATCH 05/24] Next time ask nicer bitch(drk) and don't talk to me like that please. --- .../languages/mod_managed/freeswitch_wrap.cxx | 23 +++++++++++++++---- src/mod/languages/mod_managed/managed/swig.cs | 14 ++++++++--- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx index 737940ec6c..49fb617ef6 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx @@ -21403,21 +21403,36 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_variable_partner(void * } -SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_export_variable_var_check(void * jarg1, char * jarg2, char * jarg3, int jarg4, int jarg5) { +SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_export_variable_var_check(void * jarg1, char * jarg2, char * jarg3, int jarg4) { int jresult ; switch_channel_t *arg1 = (switch_channel_t *) 0 ; char *arg2 = (char *) 0 ; char *arg3 = (char *) 0 ; switch_bool_t arg4 ; - switch_bool_t arg5 ; switch_status_t result; arg1 = (switch_channel_t *)jarg1; arg2 = (char *)jarg2; arg3 = (char *)jarg3; arg4 = (switch_bool_t)jarg4; - arg5 = (switch_bool_t)jarg5; - result = (switch_status_t)switch_channel_export_variable_var_check(arg1,(char const *)arg2,(char const *)arg3,arg4,arg5); + result = (switch_status_t)switch_channel_export_variable_var_check(arg1,(char const *)arg2,(char const *)arg3,arg4); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_export_variable_printf(void * jarg1, char * jarg2, char * jarg3) { + int jresult ; + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + void *arg4 = 0 ; + switch_status_t result; + + arg1 = (switch_channel_t *)jarg1; + arg2 = (char *)jarg2; + arg3 = (char *)jarg3; + result = (switch_status_t)switch_channel_export_variable_printf(arg1,(char const *)arg2,(char const *)arg3,arg4); jresult = result; return jresult; } diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs index 13756d32a6..1821bbb088 100644 --- a/src/mod/languages/mod_managed/managed/swig.cs +++ b/src/mod/languages/mod_managed/managed/swig.cs @@ -2904,8 +2904,13 @@ public class freeswitch { return ret; } - public static switch_status_t switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel channel, string varname, string value, switch_bool_t var_check, switch_bool_t nolocal) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel.getCPtr(channel), varname, value, (int)var_check, (int)nolocal); + public static switch_status_t switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel channel, string varname, string value, switch_bool_t var_check) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel.getCPtr(channel), varname, value, (int)var_check); + return ret; + } + + public static switch_status_t switch_channel_export_variable_printf(SWIGTYPE_p_switch_channel channel, string varname, string fmt) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_channel_export_variable_printf(SWIGTYPE_p_switch_channel.getCPtr(channel), varname, fmt); return ret; } @@ -10215,7 +10220,10 @@ class freeswitchPINVOKE { public static extern string switch_channel_get_variable_partner(HandleRef jarg1, string jarg2); [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_export_variable_var_check")] - public static extern int switch_channel_export_variable_var_check(HandleRef jarg1, string jarg2, string jarg3, int jarg4, int jarg5); + public static extern int switch_channel_export_variable_var_check(HandleRef jarg1, string jarg2, string jarg3, int jarg4); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_export_variable_printf")] + public static extern int switch_channel_export_variable_printf(HandleRef jarg1, string jarg2, string jarg3); [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_variable_dup")] public static extern string switch_channel_get_variable_dup(HandleRef jarg1, string jarg2, int jarg3); From 3b83541f7977f4b3e760adb7947418e30ec39454 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Thu, 8 Apr 2010 19:49:24 +0000 Subject: [PATCH 06/24] Clarify the syntax for git merge. --- scripts/setup-git.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/setup-git.sh b/scripts/setup-git.sh index 9781417f98..1a5e36d339 100755 --- a/scripts/setup-git.sh +++ b/scripts/setup-git.sh @@ -49,7 +49,7 @@ cat 1>&2 < See 'man git-config' for more information. EOF From 58595bdaec90efea3a0bb636a668910f1dd3c63f Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Thu, 8 Apr 2010 22:38:24 +0200 Subject: [PATCH 07/24] Skinny: solve deadlocks and more - Solve deadlock: + associate all skinny_profile_find_session with the corresponding switch_core_session_rwunlock + lock the newly created session in skinny_create_ingoing_session + enhance rwlocks debugging - Shared lines: + Inform shared lines on answering + Answering line has info after other shared lines --- src/mod/endpoints/mod_skinny/mod_skinny.c | 9 ++- src/mod/endpoints/mod_skinny/mod_skinny.h | 5 ++ .../endpoints/mod_skinny/skinny_protocol.c | 63 ++++++++++++------- 3 files changed, 54 insertions(+), 23 deletions(-) diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c index 571223ccac..e7476b53d5 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.c +++ b/src/mod/endpoints/mod_skinny/mod_skinny.c @@ -235,14 +235,22 @@ char * skinny_profile_find_session_uuid(skinny_profile_t *profile, listener_t *l return helper.channel_uuid; } +#ifdef SWITCH_DEBUG_RWLOCKS +switch_core_session_t * skinny_profile_perform_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id, const char *file, const char *func, int line) +#else switch_core_session_t * skinny_profile_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id) +#endif { char *uuid; switch_core_session_t *result = NULL; uuid = skinny_profile_find_session_uuid(profile, listener, line_instance_p, call_id); if(!zstr(uuid)) { +#ifdef SWITCH_DEBUG_RWLOCKS + result = switch_core_session_perform_locate(uuid, file, func, line); +#else result = switch_core_session_locate(uuid); +#endif if(!result) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unable to find session %s on %s:%d, line %d\n", @@ -650,7 +658,6 @@ int channel_on_hangup_callback(void *pArg, int argc, char **argv, char **columnN /* TODO: DefineTimeDate */ send_set_speaker_mode(listener, SKINNY_SPEAKER_OFF); send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, call_id); - } return 0; } diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.h b/src/mod/endpoints/mod_skinny/mod_skinny.h index 7bcc40b96c..3443d2f7dd 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.h +++ b/src/mod/endpoints/mod_skinny/mod_skinny.h @@ -189,7 +189,12 @@ switch_status_t skinny_profile_dump(const skinny_profile_t *profile, switch_stre switch_status_t skinny_profile_find_listener_by_device_name(skinny_profile_t *profile, const char *device_name, listener_t **listener); switch_status_t skinny_profile_find_listener_by_device_name_and_instance(skinny_profile_t *profile, const char *device_name, uint32_t device_instance, listener_t **listener); char * skinny_profile_find_session_uuid(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id); +#ifdef SWITCH_DEBUG_RWLOCKS +switch_core_session_t * skinny_profile_perform_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id, const char *file, const char *func, int line); +#define skinny_profile_find_session(profile, listener, line_instance_p, call_id) skinny_profile_perform_find_session(profile, listener, line_instance_p, call_id, __FILE__, __SWITCH_FUNC__, __LINE__) +#else switch_core_session_t * skinny_profile_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id); +#endif switch_status_t dump_device(skinny_profile_t *profile, const char *device_name, switch_stream_handle_t *stream); /*****************************************************************************/ diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.c b/src/mod/endpoints/mod_skinny/skinny_protocol.c index 533a922f32..ec7ba83353 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.c +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.c @@ -446,13 +446,13 @@ switch_status_t skinny_create_ingoing_session(listener_t *listener, uint32_t *li line_instance = *line_instance_p; if((nsession = skinny_profile_find_session(listener->profile, listener, line_instance_p, 0))) { - switch_core_session_rwunlock(nsession); if(skinny_line_get_state(listener, *line_instance_p, 0) == SKINNY_OFF_HOOK) { /* Reuse existing session */ *session = nsession; return SWITCH_STATUS_SUCCESS; } skinny_session_hold_line(nsession, listener, *line_instance_p); + switch_core_session_rwunlock(nsession); } *line_instance_p = line_instance; if(*line_instance_p == 0) { @@ -494,7 +494,11 @@ switch_status_t skinny_create_ingoing_session(listener_t *listener, uint32_t *li "Error Creating Session thread\n"); goto error; } - + if (switch_core_session_read_lock(nsession) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(nsession), SWITCH_LOG_CRIT, + "Error Locking Session\n"); + goto error; + } if (!(tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(nsession), NULL, listener->profile->dialplan, button->shortname, button->name, @@ -579,8 +583,6 @@ switch_status_t skinny_session_process_dest(switch_core_session_t *session, list skinny_session_start_media(session, listener, line_instance); } - switch_core_session_rwunlock(session); - return SWITCH_STATUS_SUCCESS; } @@ -603,8 +605,6 @@ switch_status_t skinny_session_ring_out(switch_core_session_t *session, listener line_instance, tech_pvt->call_id); skinny_send_call_info(session, listener, line_instance); - switch_core_session_rwunlock(session); - return SWITCH_STATUS_SUCCESS; } @@ -643,16 +643,14 @@ int skinny_session_answer_callback(void *pArg, int argc, char **argv, char **col if(!strcmp(device_name, helper->listener->device_name) && (device_instance == helper->listener->device_instance) && (line_instance == helper->line_instance)) {/* the answering line */ - - - send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, helper->tech_pvt->call_id); - send_set_speaker_mode(listener, SKINNY_SPEAKER_ON); + /* nothing */ + } else { + send_define_current_time_date(listener); send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_ON); - skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_OFF_HOOK); - /* send_select_soft_keys(listener, line_instance, helper->tech_pvt->call_id, SKINNY_KEY_SET_OFF_HOOK, 0xffff); */ - /* display_prompt_status(listener, 0, "\200\000", - line_instance, tech_pvt->call_id); */ - send_activate_call_plane(listener, line_instance); + skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_IN_USE_REMOTELY); + send_select_soft_keys(listener, line_instance, helper->tech_pvt->call_id, 10, 0x0002); + send_display_prompt_status(listener, 0, "\200\037", line_instance, helper->tech_pvt->call_id); + send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, helper->tech_pvt->call_id); } } return 0; @@ -671,6 +669,12 @@ switch_status_t skinny_session_answer(switch_core_session_t *session, listener_t channel = switch_core_session_get_channel(session); tech_pvt = switch_core_session_get_private(session); + send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, tech_pvt->call_id); + send_set_speaker_mode(listener, SKINNY_SPEAKER_ON); + send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_ON); + skinny_line_set_state(listener, line_instance, tech_pvt->call_id, SKINNY_OFF_HOOK); + send_activate_call_plane(listener, line_instance); + helper.tech_pvt = tech_pvt; helper.listener = listener; helper.line_instance = line_instance; @@ -679,8 +683,6 @@ switch_status_t skinny_session_answer(switch_core_session_t *session, listener_t skinny_session_start_media(session, listener, line_instance); - switch_core_session_rwunlock(session); - return SWITCH_STATUS_SUCCESS; } @@ -717,8 +719,6 @@ switch_status_t skinny_session_start_media(switch_core_session_t *session, liste tech_pvt->call_id); skinny_send_call_info(session, listener, line_instance); - switch_core_session_rwunlock(session); - return SWITCH_STATUS_SUCCESS; } @@ -739,8 +739,6 @@ switch_status_t skinny_session_hold_line(switch_core_session_t *session, listene switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); - switch_core_session_rwunlock(session); - return SWITCH_STATUS_SUCCESS; } @@ -2002,6 +2000,11 @@ switch_status_t skinny_handle_off_hook_message(listener_t *listener, skinny_mess skinny_session_process_dest(session, listener, line_instance, NULL, '\0', 0); } + + if(session) { + switch_core_session_rwunlock(session); + } + return SWITCH_STATUS_SUCCESS; } @@ -2037,6 +2040,11 @@ switch_status_t skinny_handle_stimulus_message(listener_t *listener, skinny_mess default: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown Stimulus Type Received [%d]\n", request->data.stimulus.instance_type); } + + if(session) { + switch_core_session_rwunlock(session); + } + return SWITCH_STATUS_SUCCESS; } @@ -2118,9 +2126,13 @@ switch_status_t skinny_handle_open_receive_channel_ack_message(listener_t *liste } switch_channel_mark_answered(channel); - switch_core_session_rwunlock(session); } end: + + if(session) { + switch_core_session_rwunlock(session); + } + return status; } @@ -2174,6 +2186,10 @@ switch_status_t skinny_handle_keypad_button_message(listener_t *listener, skinny switch_core_session_rwunlock(session); } + if(session) { + switch_core_session_rwunlock(session); + } + return SWITCH_STATUS_SUCCESS; } @@ -2195,9 +2211,12 @@ switch_status_t skinny_handle_on_hook_message(listener_t *listener, skinny_messa channel = switch_core_session_get_channel(session); switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); + } + if(session) { switch_core_session_rwunlock(session); } + return status; } From ca8ec66ed36f67566017df054fdf24a2d57c00c3 Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Thu, 8 Apr 2010 22:48:36 +0200 Subject: [PATCH 08/24] Skinny: avoid crash on shutdown Because of uninstancied listener --- src/mod/endpoints/mod_skinny/mod_skinny.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c index e7476b53d5..56f2b5ed0e 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.c +++ b/src/mod/endpoints/mod_skinny/mod_skinny.c @@ -1236,6 +1236,9 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj) switch_clear_flag_locked(listener, LFLAG_RUNNING); break; } + if (!listener_is_ready(listener)) { + break; + } if (!request) { continue; From d3d50e6eb38b6d02e31249c2b5ca96399f65b51f Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Thu, 8 Apr 2010 22:59:31 +0200 Subject: [PATCH 09/24] Skinny: release XML config Fixes: reloadxml blocked --- src/mod/endpoints/mod_skinny/skinny_protocol.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.c b/src/mod/endpoints/mod_skinny/skinny_protocol.c index ec7ba83353..2c96022bee 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.c +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.c @@ -1478,6 +1478,9 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r } } } + if (xroot) { + switch_xml_free(xroot); + } status = SWITCH_STATUS_SUCCESS; From c15e163b889df616f8b1c8542f321029df1e03c3 Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Thu, 8 Apr 2010 23:16:44 +0200 Subject: [PATCH 10/24] Skinny: avoid non-set profile name --- src/mod/endpoints/mod_skinny/mod_skinny.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c index 56f2b5ed0e..a6adf86c4a 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.c +++ b/src/mod/endpoints/mod_skinny/mod_skinny.c @@ -1483,7 +1483,7 @@ static switch_status_t load_skinny_config(void) } profile = switch_core_alloc(profile_pool, sizeof(skinny_profile_t)); profile->pool = profile_pool; - profile->name = profile_name; + profile->name = switch_core_strdup(profile->pool, profile_name); switch_mutex_init(&profile->listener_mutex, SWITCH_MUTEX_NESTED, profile->pool); switch_mutex_init(&profile->sql_mutex, SWITCH_MUTEX_NESTED, profile->pool); switch_mutex_init(&profile->sock_mutex, SWITCH_MUTEX_NESTED, profile->pool); From bec8d75ef6d1195e36c99069205736f33458e476 Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Thu, 8 Apr 2010 23:17:13 +0200 Subject: [PATCH 11/24] Skinny: don't double unlock on keypad double unlock is same as locking :P --- src/mod/endpoints/mod_skinny/skinny_protocol.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.c b/src/mod/endpoints/mod_skinny/skinny_protocol.c index 2c96022bee..8a96f7e629 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.c +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.c @@ -2186,7 +2186,6 @@ switch_status_t skinny_handle_keypad_button_message(listener_t *listener, skinny switch_channel_queue_dtmf(channel, &dtmf); } } - switch_core_session_rwunlock(session); } if(session) { From 2666a40a122e074ddc3384311fab2d6638a6cadb Mon Sep 17 00:00:00 2001 From: Joao Mesquita Date: Thu, 8 Apr 2010 23:15:29 -0300 Subject: [PATCH 12/24] Lets test preprocessors --- fscomm/mainwindow.cpp | 16 + fscomm/mainwindow.h | 1 + fscomm/preferences/prefdialog.cpp | 1 + fscomm/preferences/prefdialog.h | 3 + fscomm/preferences/prefdialog.ui | 2098 ++++++++++++++------------ fscomm/preferences/prefportaudio.cpp | 22 + fscomm/preferences/prefportaudio.h | 5 + 7 files changed, 1173 insertions(+), 973 deletions(-) diff --git a/fscomm/mainwindow.cpp b/fscomm/mainwindow.cpp index b4720f5034..0cfb076f3e 100644 --- a/fscomm/mainwindow.cpp +++ b/fscomm/mainwindow.cpp @@ -179,10 +179,26 @@ void MainWindow::debugConsoleTriggered() } +void MainWindow::applyPreprocessors(QStringList cmds) +{ + if (g_FSHost.getCurrentActiveCall().isNull()) return; + QString uuid = g_FSHost.getCurrentActiveCall().data()->getUuid(); + foreach(QString cmd, cmds) + { + switch_stream_handle_t stream = { 0 }; + SWITCH_STANDARD_STREAM(stream); + switch_api_execute("uuid_preprocess", QString("%1 %2").arg(uuid, cmd).toAscii().data(), NULL, &stream); + switch_safe_free(stream.data); + } +} + void MainWindow::prefTriggered() { if (!preferences) + { preferences = new PrefDialog(); + connect(preferences, SIGNAL(preprocessorsApplied(QStringList)), this, SLOT(applyPreprocessors(QStringList))); + } preferences->raise(); preferences->show(); diff --git a/fscomm/mainwindow.h b/fscomm/mainwindow.h index e7348c13d6..3b87da18ed 100644 --- a/fscomm/mainwindow.h +++ b/fscomm/mainwindow.h @@ -85,6 +85,7 @@ private slots: void updateCallTimers(); void debugConsoleTriggered(); void debugEventsTriggered(); + void applyPreprocessors(QStringList); private: Ui::MainWindow *ui; diff --git a/fscomm/preferences/prefdialog.cpp b/fscomm/preferences/prefdialog.cpp index c615411591..233de4eb1b 100644 --- a/fscomm/preferences/prefdialog.cpp +++ b/fscomm/preferences/prefdialog.cpp @@ -15,6 +15,7 @@ PrefDialog::PrefDialog(QWidget *parent) : _pref_accounts = new PrefAccounts(ui); _mod_portaudio = new PrefPortaudio(ui, this); + connect(_mod_portaudio, SIGNAL(preprocessorsApplied(QStringList)), this, SIGNAL(preprocessorsApplied(QStringList))); _mod_sofia = new PrefSofia(ui, this); readConfig(); } diff --git a/fscomm/preferences/prefdialog.h b/fscomm/preferences/prefdialog.h index 7c9907f5c2..2704a501a8 100644 --- a/fscomm/preferences/prefdialog.h +++ b/fscomm/preferences/prefdialog.h @@ -26,6 +26,9 @@ protected: private slots: void writeConfig(); +signals: + void preprocessorsApplied(QStringList); + private: void readConfig(); QSettings *_settings; diff --git a/fscomm/preferences/prefdialog.ui b/fscomm/preferences/prefdialog.ui index 1192631e70..1aaef60118 100644 --- a/fscomm/preferences/prefdialog.ui +++ b/fscomm/preferences/prefdialog.ui @@ -6,1006 +6,1158 @@ 0 0 - 839 - 613 + 803 + 667 Preferences - - - - - - 120 - 0 - - - - - 120 - 16777215 - - - - false - - - QAbstractItemView::NoDragDrop - - - - 96 - 84 - - - - QListView::Static - - - QListView::LeftToRight - - - true - - - 12 - - - QListView::IconMode - + + + - - General - - - - :/images/pref_general.jpg:/images/pref_general.jpg - - - - - Accounts - - - - :/images/pref_accounts.jpg:/images/pref_accounts.jpg - - - - - Sofia - - - - :/images/pref_sip.png:/images/pref_sip.png - - - - - PortAudio - - - - :/images/pref_audio.gif:/images/pref_audio.gif - - - - - - - - 0 - - - + + + + 120 + 0 + + + + + 120 + 16777215 + + + + false + + + QAbstractItemView::NoDragDrop + + + + 96 + 84 + + + + QListView::Static + + + QListView::LeftToRight + + + true + + + 12 + + + QListView::IconMode + - - - User Information - - - - - - CallerID Name: - - - - - - - - - - CallerID Number: - - - - - - - - - - - - - - - - - QAbstractItemView::NoEditTriggers - - - QAbstractItemView::SelectRows - - - - Name - - - - - Username - - - + + General + + + + :/images/pref_general.jpg:/images/pref_general.jpg + - + + Accounts + + + + :/images/pref_accounts.jpg:/images/pref_accounts.jpg + + + + + Sofia + + + + :/images/pref_sip.png:/images/pref_sip.png + + + + + Audio + + + + :/images/pref_audio.gif:/images/pref_audio.gif + + + + + + + + 0 + + + - - - Add + + + User Information + + + + + CallerID Name: + + + + + + + + + + CallerID Number: + + + + + + + - - - - Remove - - - - - - - true - - - Edit - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - 0 - - - - General - - - - - - Global - - - - QFormLayout::AllNonFixedFieldsGrow - - - - - log-level - - - - - - - - - - auto-restart - - - - - - - - true - - - - - false - - - - - - - - debug-presence - - - - - - - - - - rewrite-multicasted-fs-path - - - - - - - - false - - - - - true - - - - - - - - - - - - 0 - 0 - - - - Profile - - - - - - user-agent-string - - - - - - - FreeSWITCH/FSComm - - - - - - - hold-music - - - - - - - localstream://moh - - - - - - - context - - - - - - - public - - - - - - - dialplan - - - - - - - XML - - - - - - - - - - - Network - - - - - - Softphone Profile - - - - QFormLayout::AllNonFixedFieldsGrow - - - - - sip-port - - - - - - - 1 - - - 65535 - - - 12345 - - - - - - - use-rtp-timer - - - - - - - - true - - - - - false - - - - - - - - rtp-ip - - - - - - - auto - - - - - - - sip-ip - - - - - - - auto - - - - - - - apply-nat-acl - - - - - - - rfc1918 - - - - - - - ext-rtp-ip - - - - - - - stun:stun.freeswitch.org - - - - - - - ext-sip-ip - - - - - - - stun:stun.freeswitch.org - - - - - - - - - - - Codecs - - - - QFormLayout::AllNonFixedFieldsGrow + + + + + + + QAbstractItemView::NoEditTriggers - - - - inbound-codec-negotiation - - - - - - - - generous - - - - - greedy - - - - - - - - Codecs - - - - - - - - - - - Advanced - - + + QAbstractItemView::SelectRows + + + + Name + + + + + Username + + + + + + - - - Profile + + + Add - - - - - rfc2833-pt - - - - - - - 101 - - - - - - - debug - - - - - - - - - - sip-trace - - - - - - - - false - - - - - true - - - - - - - - dtmf-duration - - - - - - - 1000 - - - 100 - - - - - - - rtp-timer-name - - - - - - - soft - - - - - - - manage-presence - - - - - - - - false - - - - - true - - - - - - - - max-proceeding - - - - - - - 3 - - - - - - - nonce-ttl - - - - - - - 60 - - - - - - - rtp-timeout-sec - - - - - - - 1000 - - - 300 - - - - - - - rtp-hold-timeout-sec - - - - - - - 5000 - - - 1800 - - - - - - - auth-calls - - - - - - - - false - - - - - true - - - - - - - - auth-all-packets - - - - - - - - false - - - - - true - - - - - - - - disable-register - - - - - - - - true - - - - - false - - - - - - - - challenge-realm - - - - - - - - auto_from - - - - - auto_to - - - - - + + + + Remove + + + + + + + true + + + Edit + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + - - - - - - - - - - - - 0 - 0 - - - - Devices - - - - - - indev - + + + + + + + + + 0 + + + + General + + + + + + Global + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + log-level + + + + + + + + + + auto-restart + + + + + + + + true + + + + + false + + + + + + + + debug-presence + + + + + + + + + + rewrite-multicasted-fs-path + + + + + + + + false + + + + + true + + + + + + + + + + + + 0 + 0 + + + + Profile + + + + + + user-agent-string + + + + + + + FreeSWITCH/FSComm + + + + + + + hold-music + + + + + + + localstream://moh + + + + + + + context + + + + + + + public + + + + + + + dialplan + + + + + + + XML + + + + + + + - - - - - - - - outdev - + + + Network + + + + + + Softphone Profile + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + sip-port + + + + + + + 1 + + + 65535 + + + 12345 + + + + + + + use-rtp-timer + + + + + + + + true + + + + + false + + + + + + + + rtp-ip + + + + + + + auto + + + + + + + sip-ip + + + + + + + auto + + + + + + + apply-nat-acl + + + + + + + rfc1918 + + + + + + + ext-rtp-ip + + + + + + + stun:stun.freeswitch.org + + + + + + + ext-sip-ip + + + + + + + stun:stun.freeswitch.org + + + + + + + - - - - - - - - - - false - - - - 86 - 27 - - - - Test - - - - - - - - - rindgev - + + + Codecs + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + inbound-codec-negotiation + + + + + + + + generous + + + + + greedy + + + + + + + + Codecs + + + + + + + - - - - - - - - - - true - - - - 86 - 27 - - - - Test - - - - - - - - - - - Loop Test - - - - - - - Refresh DevList - - - - - - - - - Sample Rate - + + + Advanced + + + + + + Profile + + + + + + rfc2833-pt + + + + + + + 101 + + + + + + + debug + + + + + + + + + + sip-trace + + + + + + + + false + + + + + true + + + + + + + + dtmf-duration + + + + + + + 1000 + + + 100 + + + + + + + rtp-timer-name + + + + + + + soft + + + + + + + manage-presence + + + + + + + + false + + + + + true + + + + + + + + max-proceeding + + + + + + + 3 + + + + + + + nonce-ttl + + + + + + + 60 + + + + + + + rtp-timeout-sec + + + + + + + 1000 + + + 300 + + + + + + + rtp-hold-timeout-sec + + + + + + + 5000 + + + 1800 + + + + + + + auth-calls + + + + + + + + false + + + + + true + + + + + + + + auth-all-packets + + + + + + + + false + + + + + true + + + + + + + + disable-register + + + + + + + + true + + + + + false + + + + + + + + challenge-realm + + + + + + + + auto_from + + + + + auto_to + + + + + + + + - - - - - 16000 - + + + + + + + + + + 1 + + + + General + + + + + + + 0 + 0 + + + + Devices + + + + + + indev + + + + + + + + + + outdev + + + + + + + + + + + + false + + + + 86 + 27 + + + + Test + + + + + + + + + rindgev + + + + + + + + + + + + true + + + + 86 + 27 + + + + Test + + + + + + + + + + + Loop Test + + + + + + + Refresh DevList + + + + + + + + + Sample Rate + + + + + + + 16000 + + + + + + + Codec MS + + + + + + + 10 + + + + + + + + + + + 0 + 0 + + + + Files + + + + + + ring-file + + + + + + + + + tone_stream://%(2000,4000,440.0,480.0);loops=20 + + + + + + + Open + + + + + + + + + ring-interval + + + + + + + 5 + + + + + + + hold-file + + + + + + + + + true + + + + + + + Open + + + + + + + + + - - - - - Codec MS - + + + Preprocessor + + + + + + Echo canceller + + + + + + + read + + + + + + + write + + + + + + + Tail + + + + + + + + + + Echo Suppressor + + + + + + + read + + + + + + + write + + + + + + + Db + + + + + + + + + + Noise Supressor + + + + + + + read + + + + + + + write + + + + + + + Db + + + + + + + + + + read + + + + + + + write + + + + + + + + + + AGC + + + + + + + Apply + + + true + + + + - - - - - 10 - - - - - - - - - - - 0 - 0 - - - - Files - - - - - - ring-file - - - - - - - - - tone_stream://%(2000,4000,440.0,480.0);loops=20 - - - - - - - Open - - - - - - - - - ring-interval - - - - - - - 5 - - - - - - - hold-file - - - - - - - - - true - - - - - - - Open - - - - - - - - - - - + + + + + + + - + Qt::Horizontal diff --git a/fscomm/preferences/prefportaudio.cpp b/fscomm/preferences/prefportaudio.cpp index 14137956f1..8328c500b0 100644 --- a/fscomm/preferences/prefportaudio.cpp +++ b/fscomm/preferences/prefportaudio.cpp @@ -15,6 +15,28 @@ PrefPortaudio::PrefPortaudio(Ui::PrefDialog *ui, QObject *parent) : connect(_ui->PaRingdevTestBtn, SIGNAL(clicked()), this, SLOT(ringdevTest())); connect(_ui->PaLoopTestBtn, SIGNAL(clicked()), this, SLOT(loopTest())); connect(_ui->PaRefreshDevListBtn, SIGNAL(clicked()), this, SLOT(refreshDevList())); + connect(_ui->btnApplyPreprocessor, SIGNAL(toggled(bool)), this, SLOT(applyPreprocessors(bool))); +} + +void PrefPortaudio::applyPreprocessors(bool state) +{ + QStringList cmds; + if (!state) + { + cmds.append("stop"); + } + else + { + if (_ui->checkAECRead->isChecked()) cmds.append(QString("recho_cancel=%1").arg(_ui->spinAECTail->value())); + if (_ui->checkAECWrite->isChecked()) cmds.append(QString("wecho_cancel=%1").arg(_ui->spinAECTail->value())); + if (_ui->checkESRead->isChecked()) cmds.append(QString("recho_suppress=%1").arg(_ui->spinESDb->value())); + if (_ui->checkESWrite->isChecked()) cmds.append(QString("wecho_suppress=%1").arg(_ui->spinESDb->value())); + if (_ui->checkNSRead->isChecked()) cmds.append(QString("rnoise_suppress=%1").arg(_ui->spinNSDb->value())); + if (_ui->checkNSWrite->isChecked()) cmds.append(QString("wnoise_suppress=%1").arg(_ui->spinNSDb->value())); + if (_ui->checkAGCRead->isChecked()) cmds.append(QString("ragc=%1").arg(_ui->spinAGC->value())); + if (_ui->checkAGCWrite->isChecked()) cmds.append(QString("wagc=%1").arg(_ui->spinAGC->value())); + } + emit preprocessorsApplied(cmds); } void PrefPortaudio::ringdevTest() diff --git a/fscomm/preferences/prefportaudio.h b/fscomm/preferences/prefportaudio.h index 9ffd285636..d12750ab65 100644 --- a/fscomm/preferences/prefportaudio.h +++ b/fscomm/preferences/prefportaudio.h @@ -24,6 +24,11 @@ private slots: void ringdevTest(); void loopTest(); void refreshDevList(); + void applyPreprocessors(bool); + +signals: + void preprocessorsApplied(QStringList); + private: void getPaDevlist(void); QSettings *_settings; From 8ad17db191a327a0f3763cb73dcf30b84de23390 Mon Sep 17 00:00:00 2001 From: Joao Mesquita Date: Fri, 9 Apr 2010 00:40:55 -0300 Subject: [PATCH 13/24] Negative, not positive. --- fscomm/preferences/prefdialog.ui | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/fscomm/preferences/prefdialog.ui b/fscomm/preferences/prefdialog.ui index 1aaef60118..fbab506dab 100644 --- a/fscomm/preferences/prefdialog.ui +++ b/fscomm/preferences/prefdialog.ui @@ -796,7 +796,7 @@ - 1 + 0 @@ -1080,7 +1080,14 @@ - + + + -99 + + + 0 + + From adcb11f3d3424d8d8a8efc14b7928a8305757225 Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Fri, 9 Apr 2010 11:11:40 +0200 Subject: [PATCH 14/24] Skinny: fix calls without media If party_id is 0, the phone will not properly release media --- src/mod/endpoints/mod_skinny/mod_skinny.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c index a6adf86c4a..d086c9deb0 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.c +++ b/src/mod/endpoints/mod_skinny/mod_skinny.c @@ -539,6 +539,7 @@ void tech_init(private_t *tech_pvt, skinny_profile_t *profile, switch_core_sessi switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); tech_pvt->call_id = ++profile->next_call_id; + tech_pvt->party_id = tech_pvt->call_id; tech_pvt->profile = profile; switch_core_session_set_private(session, tech_pvt); tech_pvt->session = session; From 924e960d0a0931e34c372037573df9b0439cb183 Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Fri, 9 Apr 2010 14:40:33 +0200 Subject: [PATCH 15/24] perl-skinny: enhance test - Use thread for: keepalive, receive and send - Run indefinitevly --- src/mod/endpoints/mod_skinny/Net/Skinny.pm | 36 +++--- .../endpoints/mod_skinny/Net/Skinny/Client.pm | 94 ++++++++++++++ .../mod_skinny/Net/Skinny/Message.pm | 118 ++++++++++++------ .../mod_skinny/Net/Skinny/Protocol.pm | 3 +- src/mod/endpoints/mod_skinny/test-skinny.pl | 12 +- 5 files changed, 199 insertions(+), 64 deletions(-) create mode 100644 src/mod/endpoints/mod_skinny/Net/Skinny/Client.pm diff --git a/src/mod/endpoints/mod_skinny/Net/Skinny.pm b/src/mod/endpoints/mod_skinny/Net/Skinny.pm index e0ae460eac..c4ee1992ad 100644 --- a/src/mod/endpoints/mod_skinny/Net/Skinny.pm +++ b/src/mod/endpoints/mod_skinny/Net/Skinny.pm @@ -6,26 +6,25 @@ package Net::Skinny; use strict; use warnings; -use IO::Socket; + +require IO::Socket; + use Net::Skinny::Protocol qw/:all/; -our(@ISA); -@ISA = qw(IO::Socket::INET); +our @ISA = qw(IO::Socket::INET); sub new { shift->SUPER::new(PeerPort => 2000, @_); } -sub send_data +sub send_raw { my $self = shift; my $type = shift; - my $data = shift; - my $len = length($data)+4; + my $raw = shift; + my $len = length($raw)+4; printf "Sending message (length=%d, type=%s (%X))", $len, Net::Skinny::Protocol::skinny_message_type2str($type), $type; - $self->send( - pack("VVV", $len, 0, $type). - $data); + $self->send(pack("VVV", $len, 0, $type).$raw); printf ".\n"; } @@ -33,11 +32,8 @@ sub send_message { my $self = shift; my $type = shift; - return Net::Skinny::Message->new( - $self, - $type, - @_ - )->send(); + my $message = Net::Skinny::Message->new($type, @_); + return $self->send_raw($message->type(), $message->raw()); } sub receive_message @@ -58,20 +54,26 @@ sub receive_message printf "type=%s (%X))", Net::Skinny::Protocol::skinny_message_type2str($type), $type; if($len > 4) { $self->recv($buf, $len-4); + } else { + $buf = ''; } printf ".\n"; + return Net::Skinny::Message->new_raw($type, $buf); } sub sleep { my $self = shift; my $t = shift; - + my %args = @_; + $args{'quiet'} = 0 if not $args{'quiet'}; printf "Sleeping %d seconds", $t; while(--$t){ sleep(1); - printf "." if $t % 10; - printf "_" unless $t % 10; + if(!$args{'quiet'}) { + printf "." if $t % 10; + printf "_" unless $t % 10; + } } printf ".\n"; } diff --git a/src/mod/endpoints/mod_skinny/Net/Skinny/Client.pm b/src/mod/endpoints/mod_skinny/Net/Skinny/Client.pm new file mode 100644 index 0000000000..ee063cc911 --- /dev/null +++ b/src/mod/endpoints/mod_skinny/Net/Skinny/Client.pm @@ -0,0 +1,94 @@ +# Copyright (c) 2010 Mathieu Parent . +# All rights reserved. This program is free software; you can redistribute it +# and/or modify it under the same terms as Perl itself. + +package Net::Skinny::Client; + +use strict; +use warnings; + +use Config; +use threads; +use threads::shared; +use Thread::Queue; + +require Net::Skinny; +use Net::Skinny::Protocol qw/:all/; +use Net::Skinny::Message; + +our(@ISA); +@ISA = qw(Net::Skinny); + +my $keep_alive_thread; +my $keep_alives :shared; +our $kept_self; +my $messages_send_queue; +my $messages_receive_queue; + +$Config{useithreads} or die('Recompile Perl with threads to run this program.'); + +sub new { + $kept_self = shift->SUPER::new(@_); + $messages_send_queue = Thread::Queue->new(); + $messages_receive_queue = Thread::Queue->new(); + threads->create(\&send_messages_thread_func); + threads->create(\&receive_messages_thread_func); + return $kept_self; +} + +sub send_message { + my $self = shift; + $messages_send_queue->enqueue(\@_); +} + +sub receive_message { + my $self = shift; + my $message = $messages_receive_queue->dequeue(); + if($message->type() == 0x100) {#keepaliveack + if(1) { + lock($keep_alives); + $keep_alives--; + } + $message = $messages_receive_queue->dequeue(); + } + return $message; +} + +sub launch_keep_alive_thread +{ + if(!$keep_alive_thread) { + $keep_alive_thread = threads->create(\&keep_alive_thread_func); + } else { + print "keep-alive thread is already running\n"; + } + return $keep_alive_thread; +} + +sub keep_alive_thread_func +{ + while($kept_self) { + if(1) { + lock($keep_alives); + $keep_alives++; + $kept_self->send_message(KEEP_ALIVE_MESSAGE); + } #mutex unlocked + $kept_self->sleep(30, quiet => 0); + } +} + +sub send_messages_thread_func +{ + while(my $message = $messages_send_queue->dequeue()) { + my $type = shift @$message; + $kept_self->SUPER::send_message($type, @$message); + } +} + +sub receive_messages_thread_func +{ + while(1) { + $messages_receive_queue->enqueue($kept_self->SUPER::receive_message()); + } +} + +1; diff --git a/src/mod/endpoints/mod_skinny/Net/Skinny/Message.pm b/src/mod/endpoints/mod_skinny/Net/Skinny/Message.pm index 6a1a0ef1cf..5955216e1c 100644 --- a/src/mod/endpoints/mod_skinny/Net/Skinny/Message.pm +++ b/src/mod/endpoints/mod_skinny/Net/Skinny/Message.pm @@ -7,54 +7,96 @@ package Net::Skinny::Message; use strict; use warnings; +use threads; +use threads::shared; + use Net::Skinny::Protocol qw/:all/; -use Data::Dumper; - -require Exporter; -our @ISA = qw(Exporter); -our @EXPORT = qw(send); - -sub new { +sub new_empty { my $class = shift; my $self = {}; bless $self, $class; - $self->{'socket'} = shift; - $self->{'type'} = shift; - %{$self->{'data'}} = @_; - return $ self; + $self->{'type'} = undef; + $self->{'data'} = undef; + $self->{'raw'} = undef; + return $self; } -sub send { +sub new { + my $self = shift->new_empty(); + $self->type(shift); + $self->data(@_) if @_; + return $self; +} + +sub new_raw { + my $self = shift->new_empty(); + $self->type(shift); + $self->raw(shift); + return $self; +} + +sub type +{ my $self = shift; - my $struct = Net::Skinny::Protocol::skinny_message_struct($self->{'type'}); - my $raw = ''; - my $parsed_count = 0; - for my $info ( @$struct) { - last if !defined($self->{'data'}{@$info[1]}); - if(@$info[0] eq 'char') { - $raw .= pack("a".@$info[2], $self->{'data'}{@$info[1]}); - } elsif(@$info[0] eq 'uint32_t') { - $raw .= pack("V".@$info[2], $self->{'data'}{@$info[1]}); - } elsif(@$info[0] eq 'uint16_t') { - $raw .= pack("n".@$info[2], $self->{'data'}{@$info[1]}); - } elsif(@$info[0] eq 'struct in_addr') { - $raw .= pack("V".@$info[2], $self->{'data'}{@$info[1]}); - } elsif(@$info[0] eq 'struct station_capabilities') { - $raw .= $self->{'data'}{@$info[1]}; - } else { - printf "Unknown type: %s\n", @$info[0]; - return; - } - $parsed_count++; + my $type = @_ ? shift : undef; + if(defined($type)) { + $self->{'type'} = $type; } - if($parsed_count != scalar(keys %{$self->{'data'}})) { - printf "Incomplete message (type=%s (%X)) %d out of %d\n", Net::Skinny::Protocol::skinny_message_type2str($self->{'type'}), $self->{'type'}, - $parsed_count, scalar(keys %{$self->{'data'}}); - print Dumper(@$struct); - return; + return $self->{'type'}; +} + +sub data +{ + my $self = shift; + my @data = @_; + if(@data) { + %{$self->{'data'}} = @data; + $self->{'raw'} = undef; + } elsif(!defined($self->{'data'})) { + printf "Conversion from raw to data not implemented\n"; } - $self->{'socket'}->send_data($self->{'type'}, $raw); + return $self->{'data'}; +} + +sub raw +{ + my $self = shift; + my $raw = shift || undef; + if(defined($raw)) { + $self->{'raw'} = $raw; + $self->{'data'} = undef; + } + if(!defined($self->{'raw'})) { + my $struct = Net::Skinny::Protocol::skinny_message_struct($self->{'type'}); + my $raw = ''; + my $parsed_count = 0; + for my $info ( @$struct) { + last if !defined($self->{'data'}{@$info[1]}); + if(@$info[0] eq 'char') { + $raw .= pack("a".@$info[2], $self->{'data'}{@$info[1]}); + } elsif(@$info[0] eq 'uint32_t') { + $raw .= pack("V".@$info[2], $self->{'data'}{@$info[1]}); + } elsif(@$info[0] eq 'uint16_t') { + $raw .= pack("n".@$info[2], $self->{'data'}{@$info[1]}); + } elsif(@$info[0] eq 'struct in_addr') { + $raw .= pack("V".@$info[2], $self->{'data'}{@$info[1]}); + } elsif(@$info[0] eq 'struct station_capabilities') { + $raw .= $self->{'data'}{@$info[1]}; + } else { + printf "Unknown type: %s\n", @$info[0]; + return; + } + $parsed_count++; + } + if($parsed_count != scalar(keys %{$self->{'data'}})) { + printf "Incomplete message (type=%s (%X)) %d out of %d\n", Net::Skinny::Protocol::skinny_message_type2str($self->{'type'}), $self->{'type'}, + $parsed_count, scalar(keys %{$self->{'data'}}); + return; + } + $self->{'raw'} = $raw; + } + return $self->{'raw'}; } 1; diff --git a/src/mod/endpoints/mod_skinny/Net/Skinny/Protocol.pm b/src/mod/endpoints/mod_skinny/Net/Skinny/Protocol.pm index bfe0202787..90de304817 100644 --- a/src/mod/endpoints/mod_skinny/Net/Skinny/Protocol.pm +++ b/src/mod/endpoints/mod_skinny/Net/Skinny/Protocol.pm @@ -8,7 +8,6 @@ use strict; no strict "refs"; use warnings; use Carp; -use Data::Dumper; require Exporter; our @ISA = qw(Exporter); @@ -69,7 +68,6 @@ sub _find { printf "Unparsed line '%s' in %s\n", $_, $struct_name; } } - #print "$name: ".Dumper($struct{$name}); } } @sub{@_}; @@ -77,6 +75,7 @@ sub _find { sub skinny_message_type2str { my $message_type = shift; + return "UndefinedTypeMessage" if !defined($message_type); keys %const; while (my ($key, $value) = each %const) { diff --git a/src/mod/endpoints/mod_skinny/test-skinny.pl b/src/mod/endpoints/mod_skinny/test-skinny.pl index 390466f530..a8c7bb5d68 100644 --- a/src/mod/endpoints/mod_skinny/test-skinny.pl +++ b/src/mod/endpoints/mod_skinny/test-skinny.pl @@ -15,6 +15,7 @@ use Sys::Hostname; use Net::Skinny; use Net::Skinny::Protocol qw/:all/; use Net::Skinny::Message; +use Net::Skinny::Client; #Config my $skinny_server = hostname; @@ -23,13 +24,13 @@ my $device_ip = 10+256*(11+256*(12+256*13)); # 10.11.12.13 #====== $| = 1; -my $socket = Net::Skinny->new( +my $socket = Net::Skinny::Client->new( PeerAddr => $skinny_server, PeerPort => 2000, ); if(!$socket) { - print "Unable to connect to server\n"; + printf "Unable to connect to server %s\n", $skinny_server; exit 1; } # ============================================================================= @@ -84,11 +85,8 @@ $socket->send_message( count => 2 ); -for(my $i = 0; $i < 1; $i++) { - $socket->sleep(5); - $socket->send_message(KEEP_ALIVE_MESSAGE); - $socket->receive_message(); # keepaliveack -} +$socket->launch_keep_alive_thread(); + $socket->sleep(5); #NewCall From 7e3c29c600a1109c16c7e7be5fac8d5fb984a1bf Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Fri, 9 Apr 2010 14:59:18 +0200 Subject: [PATCH 16/24] Skinny: manage shared lines from the calling POV Called POV already implemented --- .../endpoints/mod_skinny/skinny_protocol.c | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.c b/src/mod/endpoints/mod_skinny/skinny_protocol.c index 8a96f7e629..3d72a22640 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.c +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.c @@ -547,6 +547,49 @@ done: return SWITCH_STATUS_SUCCESS; } +struct skinny_session_process_dest_helper { + private_t *tech_pvt; + listener_t *listener; + uint32_t line_instance; +}; + +int skinny_session_process_dest_callback(void *pArg, int argc, char **argv, char **columnNames) +{ + struct skinny_session_process_dest_helper *helper = pArg; + listener_t *listener = NULL; + + char *device_name = argv[0]; + uint32_t device_instance = atoi(argv[1]); + /* uint32_t position = atoi(argv[2]); */ + uint32_t line_instance = atoi(argv[3]); + /* char *label = argv[4]; */ + /* char *value = argv[5]; */ + /* char *caller_name = argv[6]; */ + /* uint32_t ring_on_idle = atoi(argv[7]); */ + /* uint32_t ring_on_active = atoi(argv[8]); */ + /* uint32_t busy_trigger = atoi(argv[9]); */ + /* char *forward_all = argv[10]; */ + /* char *forward_busy = argv[11]; */ + /* char *forward_noanswer = argv[12]; */ + /* uint32_t noanswer_duration = atoi(argv[13]); */ + /* char *channel_uuid = argv[14]; */ + /* uint32_t call_id = atoi(argv[15]); */ + /* uint32_t call_state = atoi(argv[16]); */ + + skinny_profile_find_listener_by_device_name_and_instance(helper->tech_pvt->profile, device_name, device_instance, &listener); + if(listener) { + if(!strcmp(device_name, helper->listener->device_name) + && (device_instance == helper->listener->device_instance) + && (line_instance == helper->line_instance)) {/* the calling line */ + /* nothing */ + } else { + /* TODO: capture and check what should happen here*/ + skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_IN_USE_REMOTELY); + } + } + return 0; +} + switch_status_t skinny_session_process_dest(switch_core_session_t *session, listener_t *listener, uint32_t line_instance, char *dest, char append_dest, uint32_t backspace) { switch_channel_t *channel = NULL; @@ -577,10 +620,17 @@ switch_status_t skinny_session_process_dest(switch_core_session_t *session, list } /* TODO Number is complete -> check against dialplan */ if((strlen(tech_pvt->caller_profile->destination_number) >= 4) || dest) { + struct skinny_session_process_dest_helper helper = {0}; send_dialed_number(listener, tech_pvt->caller_profile->destination_number, line_instance, tech_pvt->call_id); skinny_line_set_state(listener, line_instance, tech_pvt->call_id, SKINNY_PROCEED); skinny_send_call_info(session, listener, line_instance); + skinny_session_start_media(session, listener, line_instance); + + helper.tech_pvt = tech_pvt; + helper.listener = listener; + helper.line_instance = line_instance; + skinny_session_walk_lines(tech_pvt->profile, switch_core_session_get_uuid(session), skinny_session_process_dest_callback, &helper); } return SWITCH_STATUS_SUCCESS; From a1952b863640e75f26a55e998c34bdeb26f85234 Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Fri, 9 Apr 2010 16:12:58 +0200 Subject: [PATCH 17/24] Skinny: implement hold/resume Also rework a bit softkey sets --- src/mod/endpoints/mod_skinny/mod_skinny.c | 11 +-- .../endpoints/mod_skinny/skinny_protocol.c | 72 +++++++++++++++++-- .../endpoints/mod_skinny/skinny_protocol.h | 1 + 3 files changed, 68 insertions(+), 16 deletions(-) diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c index d086c9deb0..7b5be3529f 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.c +++ b/src/mod/endpoints/mod_skinny/mod_skinny.c @@ -642,16 +642,7 @@ int channel_on_hangup_callback(void *pArg, int argc, char **argv, char **columnN send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_OFF); send_clear_prompt_status(listener, line_instance, call_id); if(call_state == SKINNY_CONNECTED) { /* calling parties */ - send_close_receive_channel(listener, - call_id, /* uint32_t conference_id, */ - helper->tech_pvt->party_id, /* uint32_t pass_thru_party_id, */ - call_id /* uint32_t conference_id2, */ - ); - send_stop_media_transmission(listener, - call_id, /* uint32_t conference_id, */ - helper->tech_pvt->party_id, /* uint32_t pass_thru_party_id, */ - call_id /* uint32_t conference_id2, */ - ); + skinny_session_stop_media(helper->tech_pvt->session, listener, line_instance); } skinny_line_set_state(listener, line_instance, call_id, SKINNY_ON_HOOK); diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.c b/src/mod/endpoints/mod_skinny/skinny_protocol.c index 3d72a22640..2361fa2801 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.c +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.c @@ -784,17 +784,66 @@ switch_status_t skinny_session_hold_line(switch_core_session_t *session, listene channel = switch_core_session_get_channel(session); tech_pvt = switch_core_session_get_private(session); - /* TODO */ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Hold is not implemented yet. Hanging up the line.\n"); + skinny_session_stop_media(session, listener, line_instance); + switch_ivr_hold(session, NULL, 1); - switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); + send_define_current_time_date(listener); + send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_WINK); + skinny_line_set_state(listener, line_instance, tech_pvt->call_id, SKINNY_HOLD); + send_select_soft_keys(listener, line_instance, tech_pvt->call_id, SKINNY_KEY_SET_ON_HOLD, 0xffff); + send_display_prompt_status(listener, 0, "\200\003", + line_instance, tech_pvt->call_id); + skinny_send_call_info(tech_pvt->session, listener, line_instance); + send_set_speaker_mode(listener, SKINNY_SPEAKER_OFF); + send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, tech_pvt->call_id); return SWITCH_STATUS_SUCCESS; } switch_status_t skinny_session_unhold_line(switch_core_session_t *session, listener_t *listener, uint32_t line_instance) { - /* TODO */ + switch_channel_t *channel = NULL; + private_t *tech_pvt = NULL; + + switch_assert(session); + switch_assert(listener); + switch_assert(listener->profile); + + channel = switch_core_session_get_channel(session); + tech_pvt = switch_core_session_get_private(session); + + send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, tech_pvt->call_id); + send_set_speaker_mode(listener, SKINNY_SPEAKER_ON); + send_select_soft_keys(listener, line_instance, tech_pvt->call_id, SKINNY_KEY_SET_RING_OUT, 0xffff); + skinny_session_start_media(session, listener, line_instance); + switch_ivr_unhold(session); + send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_ON); + return SWITCH_STATUS_SUCCESS; +} + +switch_status_t skinny_session_stop_media(switch_core_session_t *session, listener_t *listener, uint32_t line_instance) +{ + switch_channel_t *channel = NULL; + private_t *tech_pvt = NULL; + + switch_assert(session); + switch_assert(listener); + switch_assert(listener->profile); + + channel = switch_core_session_get_channel(session); + tech_pvt = switch_core_session_get_private(session); + + send_close_receive_channel(listener, + tech_pvt->call_id, /* uint32_t conference_id, */ + tech_pvt->party_id, /* uint32_t pass_thru_party_id, */ + tech_pvt->call_id /* uint32_t conference_id2, */ + ); + send_stop_media_transmission(listener, + tech_pvt->call_id, /* uint32_t conference_id, */ + tech_pvt->party_id, /* uint32_t pass_thru_party_id, */ + tech_pvt->call_id /* uint32_t conference_id2, */ + ); + return SWITCH_STATUS_SUCCESS; } @@ -1840,10 +1889,21 @@ switch_status_t skinny_handle_soft_key_set_request(listener_t *listener, skinny_ message->data.soft_key_set.total_soft_key_set_count = 11; /* TODO fill the set */ - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[0] = SOFTKEY_REDIAL; - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[1] = SOFTKEY_NEWCALL; + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[0] = SOFTKEY_NEWCALL; + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[1] = SOFTKEY_REDIAL; + + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK].soft_key_template_index[0] = SOFTKEY_BACKSPACE; + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK].soft_key_template_index[1] = SOFTKEY_REDIAL; + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[0] = SOFTKEY_ENDCALL; + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[1] = SOFTKEY_HOLD; + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[0] = SOFTKEY_ENDCALL; + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[1] = SOFTKEY_ANSWER; + + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[0] = SOFTKEY_RESUME; + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[1] = SOFTKEY_NEWCALL; + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[2] = SOFTKEY_ENDCALL; skinny_send_reply(listener, message); diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.h b/src/mod/endpoints/mod_skinny/skinny_protocol.h index ea004f12fc..74a24a0590 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.h +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.h @@ -630,6 +630,7 @@ switch_status_t skinny_session_answer(switch_core_session_t *session, listener_t switch_status_t skinny_session_start_media(switch_core_session_t *session, listener_t *listener, uint32_t line_instance); switch_status_t skinny_session_hold_line(switch_core_session_t *session, listener_t *listener, uint32_t line_instance); switch_status_t skinny_session_unhold_line(switch_core_session_t *session, listener_t *listener, uint32_t line_instance); +switch_status_t skinny_session_stop_media(switch_core_session_t *session, listener_t *listener, uint32_t line_instance); void skinny_line_get(listener_t *listener, uint32_t instance, struct line_stat_res_message **button); void skinny_speed_dial_get(listener_t *listener, uint32_t instance, struct speed_dial_stat_res_message **button); From 555b205344c89fd4df27fa82c8829e58c50a6c60 Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Fri, 9 Apr 2010 16:54:29 +0200 Subject: [PATCH 18/24] Skinny: handle backspace --- .../endpoints/mod_skinny/skinny_protocol.c | 48 ++++++++++++------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.c b/src/mod/endpoints/mod_skinny/skinny_protocol.c index 2361fa2801..0dab0fe47a 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.c +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.c @@ -602,24 +602,31 @@ switch_status_t skinny_session_process_dest(switch_core_session_t *session, list channel = switch_core_session_get_channel(session); tech_pvt = switch_core_session_get_private(session); - if(!dest) { - if(append_dest == '\0') {/* no digit yet */ - send_start_tone(listener, SKINNY_TONE_DIALTONE, 0, line_instance, tech_pvt->call_id); - } else { - if(strlen(tech_pvt->caller_profile->destination_number) == 0) {/* first digit */ - send_stop_tone(listener, line_instance, tech_pvt->call_id); - send_select_soft_keys(listener, line_instance, tech_pvt->call_id, - SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT, 0xffff); - } + if (!dest) { + if (backspace) { /* backspace */ + *tech_pvt->caller_profile->destination_number++ = '\0'; + } + if (append_dest != '\0' && !backspace) {/* append digit */ tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "%s%c", tech_pvt->caller_profile->destination_number, append_dest); } + if (strlen(tech_pvt->caller_profile->destination_number) == 0) {/* no digit yet */ + send_start_tone(listener, SKINNY_TONE_DIALTONE, 0, line_instance, tech_pvt->call_id); + if(backspace) { + send_select_soft_keys(listener, line_instance, tech_pvt->call_id, SKINNY_KEY_SET_OFF_HOOK, 0xffff); + /* TODO: How to clear the screen? */ + } + } else if (strlen(tech_pvt->caller_profile->destination_number) == 1) {/* first digit */ + send_stop_tone(listener, line_instance, tech_pvt->call_id); + send_select_soft_keys(listener, line_instance, tech_pvt->call_id, + SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT, 0xffff); + } } else { tech_pvt->caller_profile->destination_number = switch_core_strdup(tech_pvt->caller_profile->pool, dest); } /* TODO Number is complete -> check against dialplan */ - if((strlen(tech_pvt->caller_profile->destination_number) >= 4) || dest) { + if ((strlen(tech_pvt->caller_profile->destination_number) >= 4) || dest) { struct skinny_session_process_dest_helper helper = {0}; send_dialed_number(listener, tech_pvt->caller_profile->destination_number, line_instance, tech_pvt->call_id); skinny_line_set_state(listener, line_instance, tech_pvt->call_id, SKINNY_PROCEED); @@ -1892,17 +1899,18 @@ switch_status_t skinny_handle_soft_key_set_request(listener_t *listener, skinny_ message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[0] = SOFTKEY_NEWCALL; message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[1] = SOFTKEY_REDIAL; - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK].soft_key_template_index[0] = SOFTKEY_BACKSPACE; message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK].soft_key_template_index[1] = SOFTKEY_REDIAL; + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT].soft_key_template_index[0] = SOFTKEY_BACKSPACE; + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[0] = SOFTKEY_ENDCALL; message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[1] = SOFTKEY_HOLD; - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[0] = SOFTKEY_ENDCALL; - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[1] = SOFTKEY_ANSWER; + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[0] = SOFTKEY_ANSWER; + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[1] = SOFTKEY_ENDCALL; - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[0] = SOFTKEY_RESUME; - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[1] = SOFTKEY_NEWCALL; + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[0] = SOFTKEY_NEWCALL; + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[1] = SOFTKEY_RESUME; message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[2] = SOFTKEY_ENDCALL; skinny_send_reply(listener, message); @@ -2042,7 +2050,6 @@ switch_status_t skinny_handle_soft_key_event_message(listener_t *listener, skinn case SOFTKEY_NEWCALL: status = skinny_create_ingoing_session(listener, &line_instance, &session); tech_pvt = switch_core_session_get_private(session); - assert(tech_pvt != NULL); skinny_session_process_dest(session, listener, line_instance, NULL, '\0', 0); break; @@ -2053,6 +2060,13 @@ switch_status_t skinny_handle_soft_key_event_message(listener_t *listener, skinn status = skinny_session_hold_line(session, listener, line_instance); } break; + case SOFTKEY_BACKSPACE: + session = skinny_profile_find_session(listener->profile, listener, &line_instance, request->data.soft_key_event.call_id); + + if(session) { + skinny_session_process_dest(session, listener, line_instance, NULL, '\0', 1); + } + break; case SOFTKEY_ENDCALL: session = skinny_profile_find_session(listener->profile, listener, &line_instance, request->data.soft_key_event.call_id); @@ -2078,7 +2092,7 @@ switch_status_t skinny_handle_soft_key_event_message(listener_t *listener, skinn break; default: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, - "Unknown SoftKeyEvent type while busy: %d.\n", request->data.soft_key_event.event); + "Unknown SoftKeyEvent type: %d.\n", request->data.soft_key_event.event); } if(session) { From befd41c8294c0ab677800eac4b112d0df4402a15 Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Fri, 9 Apr 2010 18:02:14 +0200 Subject: [PATCH 19/24] SKinny: handle hold corner cases - try to re-use existing OffHook session - hold active lines before: newcall, resume - allow endcall on: offHook, afterFirstDigit - allow newcall on: connected, ringin --- src/mod/endpoints/mod_skinny/mod_skinny.c | 10 ++- .../endpoints/mod_skinny/skinny_protocol.c | 67 ++++++++++++++++++- .../endpoints/mod_skinny/skinny_protocol.h | 1 + 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c index 7b5be3529f..391923d5e9 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.c +++ b/src/mod/endpoints/mod_skinny/mod_skinny.c @@ -221,7 +221,7 @@ char * skinny_profile_find_session_uuid(skinny_profile_t *profile, listener_t *l "SELECT channel_uuid, line_instance " "FROM skinny_active_lines " "WHERE %s AND %s AND %s " - "ORDER BY channel_uuid DESC", + "ORDER BY call_state, channel_uuid", /* off hook first */ device_condition, line_instance_condition, call_id_condition ))) { skinny_execute_sql_callback(profile, profile->sql_mutex, sql, @@ -365,7 +365,9 @@ struct skinny_line_get_state_helper { int skinny_line_get_state_callback(void *pArg, int argc, char **argv, char **columnNames) { struct skinny_line_get_state_helper *helper = pArg; - helper->call_state = atoi(argv[0]); + if (helper->call_state == -1) { + helper->call_state = atoi(argv[0]); + } return 0; } @@ -391,10 +393,12 @@ uint32_t skinny_line_get_state(listener_t *listener, uint32_t line_instance, uin } switch_assert(call_id_condition); + helper.call_state = -1; if ((sql = switch_mprintf( "SELECT call_state FROM skinny_active_lines " "WHERE device_name='%s' AND device_instance=%d " - "AND %s AND %s", + "AND %s AND %s " + "ORDER BY call_state, channel_uuid", /* off hook first */ listener->device_name, listener->device_instance, line_instance_condition, call_id_condition ))) { diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.c b/src/mod/endpoints/mod_skinny/skinny_protocol.c index 0dab0fe47a..94c61eb1dd 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.c +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.c @@ -451,7 +451,6 @@ switch_status_t skinny_create_ingoing_session(listener_t *listener, uint32_t *li *session = nsession; return SWITCH_STATUS_SUCCESS; } - skinny_session_hold_line(nsession, listener, *line_instance_p); switch_core_session_rwunlock(nsession); } *line_instance_p = line_instance; @@ -459,6 +458,8 @@ switch_status_t skinny_create_ingoing_session(listener_t *listener, uint32_t *li *line_instance_p = 1; } + skinny_hold_active_calls(listener); + skinny_line_get(listener, *line_instance_p, &button); if (!button || !button->shortname) { @@ -819,6 +820,7 @@ switch_status_t skinny_session_unhold_line(switch_core_session_t *session, liste channel = switch_core_session_get_channel(session); tech_pvt = switch_core_session_get_private(session); + skinny_hold_active_calls(listener); send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, tech_pvt->call_id); send_set_speaker_mode(listener, SKINNY_SPEAKER_ON); send_select_soft_keys(listener, line_instance, tech_pvt->call_id, SKINNY_KEY_SET_RING_OUT, 0xffff); @@ -854,6 +856,65 @@ switch_status_t skinny_session_stop_media(switch_core_session_t *session, listen return SWITCH_STATUS_SUCCESS; } +struct skinny_hold_active_calls_helper { + listener_t *listener; +}; + +int skinny_hold_active_calls_callback(void *pArg, int argc, char **argv, char **columnNames) +{ + struct skinny_hold_active_calls_helper *helper = pArg; + switch_core_session_t *session; + + /* char *device_name = argv[0]; */ + /* uint32_t device_instance = atoi(argv[1]); */ + /* uint32_t position = atoi(argv[2]); */ + uint32_t line_instance = atoi(argv[3]); + /* char *label = argv[4]; */ + /* char *value = argv[5]; */ + /* char *caller_name = argv[6]; */ + /* uint32_t ring_on_idle = atoi(argv[7]); */ + /* uint32_t ring_on_active = atoi(argv[8]); */ + /* uint32_t busy_trigger = atoi(argv[9]); */ + /* char *forward_all = argv[10]; */ + /* char *forward_busy = argv[11]; */ + /* char *forward_noanswer = argv[12]; */ + /* uint32_t noanswer_duration = atoi(argv[13]); */ + /* char *channel_uuid = argv[14]; */ + uint32_t call_id = atoi(argv[15]); + /* uint32_t call_state = atoi(argv[16]); */ + + session = skinny_profile_find_session(helper->listener->profile, helper->listener, &line_instance, call_id); + + if(session) { + skinny_session_hold_line(session, helper->listener, line_instance); + switch_core_session_rwunlock(session); + } + + return 0; +} + +switch_status_t skinny_hold_active_calls(listener_t *listener) +{ + struct skinny_hold_active_calls_helper helper = {0}; + char *sql; + + helper.listener = listener; + + if ((sql = switch_mprintf( + "SELECT skinny_lines.*, channel_uuid, call_id, call_state " + "FROM skinny_active_lines " + "INNER JOIN skinny_lines " + "ON skinny_active_lines.device_name = skinny_lines.device_name " + "AND skinny_active_lines.device_instance = skinny_lines.device_instance " + "AND skinny_active_lines.line_instance = skinny_lines.line_instance " + "WHERE skinny_lines.device_name='%s' AND skinny_lines.device_instance=%d AND call_state=%d", + listener->device_name, listener->device_instance, SKINNY_CONNECTED))) { + skinny_execute_sql_callback(listener->profile, listener->profile->sql_mutex, sql, skinny_hold_active_calls_callback, &helper); + switch_safe_free(sql); + } + + return SWITCH_STATUS_SUCCESS; +} /*****************************************************************************/ /* SKINNY BUTTONS */ /*****************************************************************************/ @@ -1900,14 +1961,18 @@ switch_status_t skinny_handle_soft_key_set_request(listener_t *listener, skinny_ message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[1] = SOFTKEY_REDIAL; message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK].soft_key_template_index[1] = SOFTKEY_REDIAL; + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK].soft_key_template_index[2] = SOFTKEY_ENDCALL; message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT].soft_key_template_index[0] = SOFTKEY_BACKSPACE; + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT].soft_key_template_index[2] = SOFTKEY_ENDCALL; message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[0] = SOFTKEY_ENDCALL; message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[1] = SOFTKEY_HOLD; + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[2] = SOFTKEY_NEWCALL; message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[0] = SOFTKEY_ANSWER; message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[1] = SOFTKEY_ENDCALL; + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[2] = SOFTKEY_NEWCALL; message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[0] = SOFTKEY_NEWCALL; message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[1] = SOFTKEY_RESUME; diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.h b/src/mod/endpoints/mod_skinny/skinny_protocol.h index 74a24a0590..3199738856 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.h +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.h @@ -631,6 +631,7 @@ switch_status_t skinny_session_start_media(switch_core_session_t *session, liste switch_status_t skinny_session_hold_line(switch_core_session_t *session, listener_t *listener, uint32_t line_instance); switch_status_t skinny_session_unhold_line(switch_core_session_t *session, listener_t *listener, uint32_t line_instance); switch_status_t skinny_session_stop_media(switch_core_session_t *session, listener_t *listener, uint32_t line_instance); +switch_status_t skinny_hold_active_calls(listener_t *listener); void skinny_line_get(listener_t *listener, uint32_t instance, struct line_stat_res_message **button); void skinny_speed_dial_get(listener_t *listener, uint32_t instance, struct speed_dial_stat_res_message **button); From 39f732354f631b10f1a98a0ea79ccc3cd2a3f87c Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 9 Apr 2010 12:29:58 -0400 Subject: [PATCH 20/24] fix boost win compilation --- .../ftmod_sangoma_boost/ftmod_sangoma_boost.c | 4 +- .../ftmod_wanpipe/ftmod_wanpipe.2008.vcproj | 156 +++++++++--------- 2 files changed, 80 insertions(+), 80 deletions(-) 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 a258184d01..59088a3c01 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 @@ -356,7 +356,7 @@ static FIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request) ftdm_set_string(event.calling_name, caller_data->cid_name); ftdm_set_string(event.rdnis.digits, caller_data->rdnis.digits); if (strlen(caller_data->rdnis.digits)) { - event.rdnis.digits_count = strlen(caller_data->rdnis.digits)+1; + event.rdnis.digits_count = (uint8_t)strlen(caller_data->rdnis.digits)+1; event.rdnis.ton = caller_data->rdnis.type; event.rdnis.npi = caller_data->rdnis.plan; } @@ -474,7 +474,7 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(sangoma_boost_outgoing_call) ftdm_set_string(event.calling_name, ftdmchan->caller_data.cid_name); ftdm_set_string(event.rdnis.digits, ftdmchan->caller_data.rdnis.digits); if (strlen(ftdmchan->caller_data.rdnis.digits)) { - event.rdnis.digits_count = strlen(ftdmchan->caller_data.rdnis.digits)+1; + event.rdnis.digits_count = (uint8_t)strlen(ftdmchan->caller_data.rdnis.digits)+1; event.rdnis.ton = ftdmchan->caller_data.rdnis.type; event.rdnis.npi = ftdmchan->caller_data.rdnis.plan; } diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2008.vcproj b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2008.vcproj index bfc50b7468..b7698ec7a7 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2008.vcproj +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2008.vcproj @@ -67,7 +67,7 @@ Name="VCLinkerTool" AdditionalDependencies="freetdm.lib libsangoma.lib" LinkIncremental="2" - AdditionalLibraryDirectories=""$(OutDir)";"C:\Program Files\Sangoma\lib"" + AdditionalLibraryDirectories=""$(OutDir)";"C:\Program Files\Sangoma\api\lib\x86"" GenerateDebugInformation="true" SubSystem="1" RandomizedBaseAddress="1" @@ -96,6 +96,83 @@ Name="VCPostBuildEventTool" /> + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - Date: Fri, 9 Apr 2010 16:03:54 -0400 Subject: [PATCH 21/24] Fix for sangoma_boost crashing on start due to queue unitialised Updated cpu monitor to support different /proc/cpustats format --- libs/freetdm/src/ftdm_cpu_monitor.c | 51 +++++++++++++++++++++++------ libs/freetdm/src/ftdm_io.c | 3 ++ 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/libs/freetdm/src/ftdm_cpu_monitor.c b/libs/freetdm/src/ftdm_cpu_monitor.c index 7c79a2e65c..b02f5a0d1f 100644 --- a/libs/freetdm/src/ftdm_cpu_monitor.c +++ b/libs/freetdm/src/ftdm_cpu_monitor.c @@ -61,6 +61,9 @@ struct ftdm_cpu_monitor_stats double last_percentage_of_idle_time; #ifdef __linux__ + /* the cpu feature gets disabled on errors */ + int disabled; + /* all of these are the Linux jiffies last retrieved count */ unsigned long long last_user_time; unsigned long long last_system_time; @@ -97,15 +100,23 @@ static ftdm_status_t ftdm_cpu_read_stats(struct ftdm_cpu_monitor_stats *p, { // the output of proc should not change that often from one kernel to other // see fs/proc/proc_misc.c or fs/proc/stat.c in the Linux kernel for more details -// also man 5 proc is useful -#define CPU_ELEMENTS 8 // change this if you change the format string -#define CPU_INFO_FORMAT "cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu" +// also man 5 proc is useful. +#define CPU_ELEMENTS_1 7 // change this if you change the format string +#define CPU_INFO_FORMAT_1 "cpu %llu %llu %llu %llu %llu %llu %llu" + +#define CPU_ELEMENTS_2 8 // change this if you change the format string +#define CPU_INFO_FORMAT_2 "cpu %llu %llu %llu %llu %llu %llu %llu %llu" + +#define CPU_ELEMENTS_3 9 // change this if you change the format string +#define CPU_INFO_FORMAT_3 "cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu" + static const char procfile[] = "/proc/stat"; int rc = 0; int myerrno = 0; int elements = 0; const char *cpustr = NULL; char statbuff[1024]; + unsigned long long guest = 0; if (!p->initd) { p->procfd = open(procfile, O_RDONLY, 0); @@ -131,12 +142,26 @@ static ftdm_status_t ftdm_cpu_read_stats(struct ftdm_cpu_monitor_stats *p, return FTDM_FAIL; } - elements = sscanf(cpustr, CPU_INFO_FORMAT, user, nice, system, idle, iowait, irq, softirq, steal); - if (elements != CPU_ELEMENTS) { - ftdm_log(FTDM_LOG_ERROR, "wrong format for Linux proc cpu statistics: expected %d elements, but just found %d\n", CPU_ELEMENTS, elements); - return FTDM_FAIL; + /* test each of the known formats starting from the bigger one */ + elements = sscanf(cpustr, CPU_INFO_FORMAT_3, user, nice, system, idle, iowait, irq, softirq, steal, &guest); + if (elements == CPU_ELEMENTS_3) { + user += guest; /* guest operating system's run in user space */ + return FTDM_SUCCESS; } - return FTDM_SUCCESS; + + elements = sscanf(cpustr, CPU_INFO_FORMAT_2, user, nice, system, idle, iowait, irq, softirq, steal); + if (elements == CPU_ELEMENTS_2) { + return FTDM_SUCCESS; + } + + elements = sscanf(cpustr, CPU_INFO_FORMAT_1, user, nice, system, idle, iowait, irq, softirq); + if (elements == CPU_ELEMENTS_1) { + *steal = 0; + return FTDM_SUCCESS; + } + + ftdm_log(FTDM_LOG_ERROR, "Unexpected format for Linux proc cpu statistics:%s\n", cpustr); + return FTDM_FAIL; } #endif @@ -146,8 +171,13 @@ FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time (struct ftdm_cpu_monitor unsigned long long user, nice, system, idle, iowait, irq, softirq, steal; unsigned long long usertime, kerneltime, idletime, totaltime, halftime; + *idle_percentage = 100.0; + if (p->disabled) { + return FTDM_FAIL; + } if (ftdm_cpu_read_stats(p, &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal)) { - ftdm_log(FTDM_LOG_ERROR, "Failed to retrieve Linux CPU statistics\n"); + ftdm_log(FTDM_LOG_ERROR, "Failed to retrieve Linux CPU statistics - disabling cpu monitor\n"); + p->disabled = 1; return FTDM_FAIL; } @@ -243,7 +273,8 @@ FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time(struct ftdm_cpu_monitor_ #else /* Unsupported */ FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time(struct ftdm_cpu_monitor_stats *p, double *idle_percentage) -{ +{' + *idle_percentate = 100.0; return FTDM_FAIL; } #endif diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 2cacf69d90..8e56937a39 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -3407,6 +3407,9 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span_signaling(const char *type, ftdm_s if (mod->configure_span_signaling) { status = mod->configure_span_signaling(span, sig_cb, parameters); + if (status == FTDM_SUCCESS && ftdm_test_flag(span, FTDM_SPAN_USE_CHAN_QUEUE)) { + status = ftdm_queue_create(&span->pendingchans, SPAN_PENDING_CHANS_QUEUE_SIZE); + } } else { ftdm_log(FTDM_LOG_ERROR, "Module %s did not implement the signaling configuration method\n", type); } From 279326e08c4f8e7babb3c2c80f1f8c32cb189052 Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Sat, 10 Apr 2010 20:14:07 +0200 Subject: [PATCH 22/24] Dialplan: redial as destination number for the redial ext --- conf/dialplan/default.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/dialplan/default.xml b/conf/dialplan/default.xml index aeff57d407..f03fdad84e 100644 --- a/conf/dialplan/default.xml +++ b/conf/dialplan/default.xml @@ -117,7 +117,7 @@ - + From 4988ef87a728a15741666bbf7384476d8b97a418 Mon Sep 17 00:00:00 2001 From: Rupa Schomaker Date: Sat, 10 Apr 2010 13:22:13 -0500 Subject: [PATCH 23/24] MODAPP-418 --- src/mod/applications/mod_lcr/mod_lcr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mod/applications/mod_lcr/mod_lcr.c b/src/mod/applications/mod_lcr/mod_lcr.c index 700446f03e..38cf734993 100644 --- a/src/mod/applications/mod_lcr/mod_lcr.c +++ b/src/mod/applications/mod_lcr/mod_lcr.c @@ -298,6 +298,10 @@ static char *get_bridge_data(switch_memory_pool_t *pool, char *dialed_number, ch switch_core_sprintf(pool, "[lcr_carrier=%s,lcr_rate=%s%s%s%s%s]%s%s%s%s%s", cur_route->carrier_name, cur_route->rate_str, user_rate, codec, cid, header, cur_route->gw_prefix, cur_route->prefix, destination_number, cur_route->suffix, cur_route->gw_suffix); + if (session && (switch_string_var_check_const(data) || switch_string_has_escaped_data(data))) { + data = switch_channel_expand_variables(switch_core_session_get_channel(session), data); + } + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Returning Dialstring %s\n", data); return data; } From 517e0befc6babde42e03ae73ebe0639768b7d027 Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Sun, 11 Apr 2010 18:51:37 -0400 Subject: [PATCH 24/24] Send SIP MESSAGE to unregistered users by prefixing sip: to user@domain --- src/mod/endpoints/mod_sofia/sofia_presence.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index c9cc932928..80f7d248ee 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -77,6 +77,7 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co switch_status_t status = SWITCH_STATUS_FALSE; const char *ct = "text/html"; sofia_destination_t *dst = NULL; + char *to_uri = NULL; if (!to) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing To: header.\n"); @@ -98,9 +99,17 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co user = prof; prof = NULL; } + + if (!strncasecmp(user, "sip:", 4)) { + to_uri = user; + } if ((host = strchr(user, '@'))) { - *host++ = '\0'; + if (!to_uri) { + *host++ = '\0'; + } else { + host++; + } if (!prof) prof = host; } @@ -118,7 +127,8 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co host = prof; } } - if (!sofia_reg_find_reg_url(profile, user, host, buf, sizeof(buf))) { + + if (!to_uri && !sofia_reg_find_reg_url(profile, user, host, buf, sizeof(buf))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find user. [%s][%s]\n", user, host); goto end; } @@ -152,7 +162,7 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co switch_safe_free(fp); } - if (!(dst = sofia_glue_get_destination(buf))) { + if (!(dst = sofia_glue_get_destination(to_uri ? to_uri : buf))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); goto end; } @@ -162,7 +172,7 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co status = SWITCH_STATUS_SUCCESS; /* if this cries, add contact here too, change the 1 to 0 and omit the safe_free */ msg_nh = nua_handle(profile->nua, NULL, TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)), - SIPTAG_FROM_STR(from), NUTAG_URL(contact), SIPTAG_TO_STR(dst->to), SIPTAG_CONTACT_STR(profile->url), TAG_END()); + SIPTAG_FROM_STR(from), TAG_IF(contact, NUTAG_URL(contact)), SIPTAG_TO_STR(dst->to), SIPTAG_CONTACT_STR(profile->url), TAG_END()); nua_handle_bind(msg_nh, &mod_sofia_globals.destroy_private); nua_message(msg_nh, SIPTAG_CONTENT_TYPE_STR(ct), SIPTAG_PAYLOAD_STR(body), TAG_END());